Skip to content
parachains_loop.rs 35.7 KiB
Newer Older
		// 5) best finalized source relay chain block is 95
		// 6) at source relay chain block 95 source parachain block is 42
		// =>
		// without free requirement, parachain block 42 would have been relayed
		// with free requirement we relay parachain block 9
		let (exit_signal_sender, exit_signal) = futures::channel::mpsc::unbounded();
		let clients_data = TestClientData {
			source_sync_status: Ok(true),
			source_head: vec![
				(90, Ok(AvailableHeader::Available(HeaderId(9, [9u8; 32].into())))),
				(95, Ok(AvailableHeader::Available(HeaderId(42, [42u8; 32].into())))),
			]
			.into_iter()
			.collect(),
			source_proof: Ok(()),

			target_free_source_relay_headers_interval: Ok(Some(10)),
			target_best_block: Ok(HeaderId(200, [200u8; 32].into())),
			target_best_finalized_source_block: Ok(HeaderId(95, [95u8; 32].into())),
			target_head: Ok(Some((HeaderId(50, [50u8; 32].into()), HeaderId(5, [5u8; 32].into())))),
			target_submit_result: Ok(()),

			submitted_proof_at_source_relay_block: None,
			exit_signal_sender: Some(Box::new(exit_signal_sender)),
		};

		let source_client = TestClient::from(clients_data.clone());
		let target_client = TestClient::from(clients_data);
		assert_eq!(
			run_until_connection_lost(
				source_client.clone(),
				target_client.clone(),
				None,
				true,
				exit_signal.into_future().map(|(_, _)| ()),
			)
			.await,
			Ok(()),
		);

		assert_eq!(
			target_client
				.data
				.lock()
				.await
				.submitted_proof_at_source_relay_block
				.map(|id| id.0),
			Some(90)
		);
	}

	fn test_tx_tracker() -> SubmittedHeadsTracker<TestParachainsPipeline> {
		SubmittedHeadsTracker::new(
			AvailableHeader::Available(HeaderId(20, PARA_20_HASH)),
	impl From<SubmittedHeadStatus<TestParachainsPipeline>> for Option<()> {
		fn from(status: SubmittedHeadStatus<TestParachainsPipeline>) -> Option<()> {
				SubmittedHeadStatus::Waiting(_) => Some(()),
	async fn tx_tracker_update_when_head_at_target_has_none_value() {
				.update(&HeaderId(0, Default::default()), &Some(HeaderId(10, PARA_10_HASH)))
	async fn tx_tracker_update_when_head_at_target_has_old_value() {
			test_tx_tracker()
				.update(&HeaderId(0, Default::default()), &Some(HeaderId(10, PARA_10_HASH)))
	async fn tx_tracker_update_when_head_at_target_has_same_value() {
		assert!(matches!(
			test_tx_tracker()
				.update(&HeaderId(0, Default::default()), &Some(HeaderId(20, PARA_20_HASH)))
				.await,
			SubmittedHeadStatus::Final(TrackedTransactionStatus::Finalized(_)),
		));
	async fn tx_tracker_update_when_head_at_target_has_better_value() {
		assert!(matches!(
			test_tx_tracker()
				.update(&HeaderId(0, Default::default()), &Some(HeaderId(30, PARA_20_HASH)))
				.await,
			SubmittedHeadStatus::Final(TrackedTransactionStatus::Finalized(_)),
		));
	async fn tx_tracker_update_when_tx_is_lost() {
		let mut tx_tracker = test_tx_tracker();
		tx_tracker.transaction_tracker =
			futures::future::ready(TrackedTransactionStatus::Lost).boxed().shared();
				.update(&HeaderId(0, Default::default()), &Some(HeaderId(10, PARA_10_HASH)))
			SubmittedHeadStatus::Final(TrackedTransactionStatus::Lost),
		));
	}

	#[async_std::test]
	async fn tx_tracker_update_when_tx_is_finalized_but_heads_are_not_updated() {
		let mut tx_tracker = test_tx_tracker();
		tx_tracker.transaction_tracker =
			futures::future::ready(TrackedTransactionStatus::Finalized(Default::default()))
				.boxed()
				.shared();
		assert!(matches!(
			tx_tracker
				.update(&HeaderId(0, Default::default()), &Some(HeaderId(10, PARA_10_HASH)))
			SubmittedHeadStatus::Final(TrackedTransactionStatus::Lost),
	#[test]
	fn parachain_is_not_updated_if_it_is_unavailable() {
		assert!(!is_update_required::<TestParachainsPipeline>(
			AvailableHeader::Unavailable,
			None,
			Default::default(),
			Default::default(),
		));
		assert!(!is_update_required::<TestParachainsPipeline>(
			AvailableHeader::Unavailable,
			Some(HeaderId(10, PARA_10_HASH)),
			Default::default(),
			Default::default(),
	#[test]
	fn parachain_is_not_updated_if_it_is_unknown_to_both_clients() {
		assert!(!is_update_required::<TestParachainsPipeline>(
			AvailableHeader::Missing,
			None,
			Default::default(),
			Default::default(),
		),);
	fn parachain_is_not_updated_if_target_has_better_head() {
		assert!(!is_update_required::<TestParachainsPipeline>(
			AvailableHeader::Available(HeaderId(10, Default::default())),
			Some(HeaderId(20, Default::default())),
	}

	#[test]
	fn parachain_is_updated_after_offboarding() {
		assert!(is_update_required::<TestParachainsPipeline>(
			AvailableHeader::Missing,
			Some(HeaderId(20, Default::default())),
	}

	#[test]
	fn parachain_is_updated_after_onboarding() {
		assert!(is_update_required::<TestParachainsPipeline>(
			AvailableHeader::Available(HeaderId(30, Default::default())),
			None,
	}

	#[test]
	fn parachain_is_updated_if_newer_head_is_known() {
		assert!(is_update_required::<TestParachainsPipeline>(
			AvailableHeader::Available(HeaderId(40, Default::default())),
			Some(HeaderId(30, Default::default())),