Skip to content
lib.rs 70.1 KiB
Newer Older
			));

			// first tx with messages 1+2
			assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
				Origin::signed(1),
				TestMessagesDeliveryProof(messages_1_and_2_proof),
				UnrewardedRelayersState {
					unrewarded_relayer_entries: 1,
					total_messages: 2,
					..Default::default()
				},
			));
			// second tx with message 3
			assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
				Origin::signed(1),
				TestMessagesDeliveryProof(messages_3_proof),
				UnrewardedRelayersState {
					unrewarded_relayer_entries: 1,
					total_messages: 1,
					..Default::default()
				},
			));

			// ensure that both callbacks have been called twice: for 1+2, then for 3
			TestOnDeliveryConfirmed1::ensure_called(&TEST_LANE_ID, &delivered_messages_1_and_2);
			TestOnDeliveryConfirmed1::ensure_called(&TEST_LANE_ID, &delivered_message_3);
			TestOnDeliveryConfirmed2::ensure_called(&TEST_LANE_ID, &delivered_messages_1_and_2);
			TestOnDeliveryConfirmed2::ensure_called(&TEST_LANE_ID, &delivered_message_3);
		});
	}

	fn confirm_3_messages_delivery() -> (Weight, Weight) {
		send_regular_message();
		send_regular_message();
		send_regular_message();

		let proof = TestMessagesDeliveryProof(Ok((
			TEST_LANE_ID,
			InboundLaneData {
				last_confirmed_nonce: 0,
				relayers: vec![unrewarded_relayer(1, 3, TEST_RELAYER_A)].into_iter().collect(),
			},
		)));
		let relayers_state = UnrewardedRelayersState {
			unrewarded_relayer_entries: 1,
			total_messages: 3,
			..Default::default()
		};
		let pre_dispatch_weight = <TestRuntime as Config>::WeightInfo::receive_messages_delivery_proof_weight(
			&proof,
			&relayers_state,
			crate::mock::DbWeight::get(),
		);
		let post_dispatch_weight =
			Pallet::<TestRuntime>::receive_messages_delivery_proof(Origin::signed(1), proof, relayers_state)
				.expect("confirmation has failed")
				.actual_weight
				.expect("receive_messages_delivery_proof always returns Some");
		(pre_dispatch_weight, post_dispatch_weight)
	}

	#[test]
	fn receive_messages_delivery_proof_refunds_zero_weight() {
		run_test(|| {
			let (pre_dispatch_weight, post_dispatch_weight) = confirm_3_messages_delivery();
			assert_eq!(pre_dispatch_weight, post_dispatch_weight);
		});
	}

	#[test]
	fn receive_messages_delivery_proof_refunds_non_zero_weight() {
		run_test(|| {
			TestOnDeliveryConfirmed1::set_consumed_weight_per_message(crate::mock::DbWeight::get().writes(1));

			let (pre_dispatch_weight, post_dispatch_weight) = confirm_3_messages_delivery();
			assert_eq!(
				pre_dispatch_weight.saturating_sub(post_dispatch_weight),
				crate::mock::DbWeight::get().reads(1) * 3
			);
		});
	}

	#[test]
	#[should_panic]
	fn receive_messages_panics_in_debug_mode_if_callback_is_wrong() {
		run_test(|| {
			TestOnDeliveryConfirmed1::set_consumed_weight_per_message(crate::mock::DbWeight::get().reads_writes(2, 2));
			confirm_3_messages_delivery()

	#[test]
	fn receive_messages_delivery_proof_rejects_proof_if_trying_to_confirm_more_messages_than_expected() {
		run_test(|| {
			// send message first to be able to check that delivery_proof fails later
			send_regular_message();

			// 1) InboundLaneData declares that the `last_confirmed_nonce` is 1;
			// 2) InboundLaneData has no entries => `InboundLaneData::last_delivered_nonce()`
			//    returns `last_confirmed_nonce`;
			// 3) it means that we're going to confirm delivery of messages 1..=1;
			// 4) so the number of declared messages (see `UnrewardedRelayersState`) is `0` and
			//    numer of actually confirmed messages is `1`.
			assert_noop!(
				Pallet::<TestRuntime>::receive_messages_delivery_proof(
					Origin::signed(1),
					TestMessagesDeliveryProof(Ok((
						TEST_LANE_ID,
						InboundLaneData {
							last_confirmed_nonce: 1,
							relayers: Default::default(),
						},
					))),
					UnrewardedRelayersState::default(),
				),
				Error::<TestRuntime, DefaultInstance>::TryingToConfirmMoreMessagesThanExpected,
			);
		});
	}

	#[test]
	fn weight_is_refunded_for_messages_that_are_not_pruned() {
		run_test(|| {
			// send first MAX messages - no messages are pruned
			let max_messages_to_prune = crate::mock::MaxMessagesToPruneAtOnce::get();
			let when_zero_messages_are_pruned = send_regular_message();
			let mut delivered_messages = DeliveredMessages::new(1, true);
			for _ in 1..max_messages_to_prune {
				assert_eq!(send_regular_message(), when_zero_messages_are_pruned);
				delivered_messages.note_dispatched_message(true);
			}

			// confirm delivery of all sent messages
			assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
				Origin::signed(1),
				TestMessagesDeliveryProof(Ok((
					TEST_LANE_ID,
					InboundLaneData {
						last_confirmed_nonce: 1,
						relayers: vec![UnrewardedRelayer {
							relayer: 0,
							messages: delivered_messages,
						}]
						.into_iter()
						.collect(),
					},
				))),
				UnrewardedRelayersState {
					unrewarded_relayer_entries: 1,
					total_messages: max_messages_to_prune,
					..Default::default()
				},
			));

			// when next message is sent, MAX messages are pruned
			let weight_when_max_messages_are_pruned = send_regular_message();
			assert_eq!(
				weight_when_max_messages_are_pruned,
				when_zero_messages_are_pruned + crate::mock::DbWeight::get().writes(max_messages_to_prune),
			);
		});
	}