diff --git a/bridges/bin/millau/runtime/src/lib.rs b/bridges/bin/millau/runtime/src/lib.rs
index d1ef18eb3c175f2ff6bb773d27859afd730eb060..8e0a2f3bd7d2b568ef65720f0450027b02af8cda 100644
--- a/bridges/bin/millau/runtime/src/lib.rs
+++ b/bridges/bin/millau/runtime/src/lib.rs
@@ -314,9 +314,6 @@ parameter_types! {
 
 impl pallet_finality_verifier::Config for Runtime {
 	type BridgedChain = bp_rialto::Rialto;
-	type HeaderChain = pallet_substrate_bridge::Module<Runtime>;
-	type AncestryProof = ();
-	type AncestryChecker = ();
 	type MaxRequests = MaxRequests;
 }
 
diff --git a/bridges/bin/rialto/runtime/src/lib.rs b/bridges/bin/rialto/runtime/src/lib.rs
index 6410e824221c5998a24e2079ef84461411980ed1..0c9a97318515d3ea9f1df91e3b0418a3670710fd 100644
--- a/bridges/bin/rialto/runtime/src/lib.rs
+++ b/bridges/bin/rialto/runtime/src/lib.rs
@@ -421,9 +421,6 @@ parameter_types! {
 
 impl pallet_finality_verifier::Config for Runtime {
 	type BridgedChain = bp_millau::Millau;
-	type HeaderChain = pallet_substrate_bridge::Module<Runtime>;
-	type AncestryProof = ();
-	type AncestryChecker = ();
 	type MaxRequests = MaxRequests;
 }
 
diff --git a/bridges/modules/finality-verifier/src/lib.rs b/bridges/modules/finality-verifier/src/lib.rs
index 7c331bc09e5610f0f9f81970e5a33af30d49ce66..a072fc537b801ba7e268892f2222bdfd3053a9ad 100644
--- a/bridges/modules/finality-verifier/src/lib.rs
+++ b/bridges/modules/finality-verifier/src/lib.rs
@@ -16,27 +16,30 @@
 
 //! Substrate Finality Verifier Pallet
 //!
-//! The goal of this pallet is to provide a safe interface for writing finalized headers to an
-//! external pallet which tracks headers and finality proofs. By safe, we mean that only headers
-//! whose finality has been verified will be written to the underlying pallet.
+//! This pallet is an on-chain GRANDPA light client for Substrate based chains.
 //!
-//! By verifying the finality of headers before writing them to storage we prevent DoS vectors in
-//! which unfinalized headers get written to storage even if they don't have a chance of being
-//! finalized in the future (such as in the case where a different fork gets finalized).
+//! This pallet achieves this by trustlessly verifying GRANDPA finality proofs on-chain. Once
+//! verified, finalized headers are stored in the pallet, thereby creating a sparse header chain.
+//! This sparse header chain can be used as a source of truth for other higher-level applications.
 //!
-//! The underlying pallet used for storage is assumed to be a pallet which tracks headers and
-//! GRANDPA authority set changes. This information is used during the verification of GRANDPA
-//! finality proofs.
+//! The pallet is responsible for tracking GRANDPA validator set hand-offs. We only import headers
+//! with justifications signed by the current validator set we know of. The header is inspected for
+//! a `ScheduledChanges` digest item, which is then used to update to next validator set.
+//!
+//! Since this pallet only tracks finalized headers it does not deal with forks. Forks can only
+//! occur if the GRANDPA validator set on the bridged chain is either colluding or there is a severe
+//! bug causing resulting in an equivocation. Such events are outside of the scope of this pallet.
+//! Shall the fork occur on the bridged chain governance intervention will be required to
+//! re-initialize the bridge and track the right fork.
 
 #![cfg_attr(not(feature = "std"), no_std)]
 // Runtime-generated enums
 #![allow(clippy::large_enum_variant)]
 
-use bp_header_chain::{justification::verify_justification, AncestryChecker, HeaderChain};
 use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf};
 use codec::{Decode, Encode};
 use finality_grandpa::voter_set::VoterSet;
-use frame_support::{dispatch::DispatchError, ensure};
+use frame_support::ensure;
 use frame_system::{ensure_signed, RawOrigin};
 #[cfg(feature = "std")]
 use serde::{Deserialize, Serialize};
@@ -71,19 +74,6 @@ pub mod pallet {
 		/// The chain we are bridging to here.
 		type BridgedChain: Chain;
 
-		/// The pallet which we will use as our underlying storage mechanism.
-		type HeaderChain: HeaderChain<<Self::BridgedChain as Chain>::Header, DispatchError>;
-
-		/// The type of ancestry proof used by the pallet.
-		///
-		/// Will be used by the ancestry checker to verify that the header being finalized is
-		/// related to the best finalized header in storage.
-		type AncestryProof: Parameter;
-
-		/// The type through which we will verify that a given header is related to the last
-		/// finalized header in our storage pallet.
-		type AncestryChecker: AncestryChecker<<Self::BridgedChain as Chain>::Header, Self::AncestryProof>;
-
 		/// The upper bound on the number of requests allowed by the pallet.
 		///
 		/// A request refers to an action which writes a header to storage.
@@ -122,7 +112,6 @@ pub mod pallet {
 			origin: OriginFor<T>,
 			finality_target: BridgedHeader<T>,
 			justification: Vec<u8>,
-			ancestry_proof: T::AncestryProof,
 		) -> DispatchResultWithPostInfo {
 			ensure_operational::<T>()?;
 			let _ = ensure_signed(origin)?;
@@ -145,28 +134,11 @@ pub mod pallet {
 			// "travelling back in time" (which could be indicative of something bad, e.g a hard-fork).
 			ensure!(best_finalized.number() < number, <Error<T>>::OldHeader);
 
-			let authority_set = <CurrentAuthoritySet<T>>::get();
-			let voter_set = VoterSet::new(authority_set.authorities).ok_or(<Error<T>>::InvalidAuthoritySet)?;
-			let set_id = authority_set.set_id;
-
-			verify_justification::<BridgedHeader<T>>((hash, *number), set_id, voter_set, &justification).map_err(
-				|e| {
-					log::error!("Received invalid justification for {:?}: {:?}", finality_target, e);
-					<Error<T>>::InvalidJustification
-				},
-			)?;
-
-			let best_finalized = T::HeaderChain::best_finalized();
-			log::trace!("Checking ancestry against best finalized header: {:?}", &best_finalized);
-
-			ensure!(
-				T::AncestryChecker::are_ancestors(&best_finalized, &finality_target, &ancestry_proof),
-				<Error<T>>::InvalidAncestryProof
-			);
-
-			let _ = T::HeaderChain::append_header(finality_target.clone())?;
+			verify_justification::<T>(&justification, hash, *number)?;
 
-			import_header::<T>(hash, finality_target)?;
+			try_enact_authority_change::<T>(&finality_target)?;
+			<BestFinalized<T>>::put(hash);
+			<ImportedHeaders<T>>::insert(hash, finality_target);
 			<RequestCount<T>>::mutate(|count| *count += 1);
 
 			log::info!("Succesfully imported finalized header with hash {:?}!", hash);
@@ -317,13 +289,8 @@ pub mod pallet {
 	pub enum Error<T> {
 		/// The given justification is invalid for the given header.
 		InvalidJustification,
-		/// The given ancestry proof is unable to verify that the child and ancestor headers are
-		/// related.
-		InvalidAncestryProof,
 		/// The authority set from the underlying header chain is invalid.
 		InvalidAuthoritySet,
-		/// Failed to write a header to the underlying header chain.
-		FailedToWriteHeader,
 		/// There are too many requests for the current window to handle.
 		TooManyRequests,
 		/// The header being imported is older than the best finalized header known to the pallet.
@@ -342,46 +309,70 @@ pub mod pallet {
 		StorageRootMismatch,
 	}
 
-	/// Import the given header to the pallet's storage.
+	/// Check the given header for a GRANDPA scheduled authority set change. If a change
+	/// is found it will be enacted immediately.
 	///
-	/// This function will also check if the header schedules and enacts authority set changes,
-	/// updating the current authority set accordingly.
-	///
-	/// Note: This function assumes that the given header has already been proven to be valid and
-	/// finalized. Using this assumption it will write them to storage with minimal checks. That
-	/// means it's of great importance that this function *not* called with any headers whose
-	/// finality has not been checked, otherwise you risk bricking your bridge.
-	pub(crate) fn import_header<T: Config>(
-		hash: BridgedBlockHash<T>,
-		header: BridgedHeader<T>,
+	/// This function does not support forced changes, or scheduled changes with delays
+	/// since these types of changes are indicitive of abnormal behaviour from GRANDPA.
+	pub(crate) fn try_enact_authority_change<T: Config>(
+		header: &BridgedHeader<T>,
 	) -> Result<(), sp_runtime::DispatchError> {
 		// We don't support forced changes - at that point governance intervention is required.
 		ensure!(
-			super::find_forced_change(&header).is_none(),
+			super::find_forced_change(header).is_none(),
 			<Error<T>>::UnsupportedScheduledChange
 		);
 
-		if let Some(change) = super::find_scheduled_change(&header) {
+		if let Some(change) = super::find_scheduled_change(header) {
 			// GRANDPA only includes a `delay` for forced changes, so this isn't valid.
 			ensure!(change.delay == Zero::zero(), <Error<T>>::UnsupportedScheduledChange);
 
+			let current_set_id = <CurrentAuthoritySet<T>>::get().set_id;
 			// TODO [#788]: Stop manually increasing the `set_id` here.
 			let next_authorities = bp_header_chain::AuthoritySet {
 				authorities: change.next_authorities,
-				set_id: <CurrentAuthoritySet<T>>::get().set_id + 1,
+				set_id: current_set_id + 1,
 			};
 
 			// Since our header schedules a change and we know the delay is 0, it must also enact
 			// the change.
-			<CurrentAuthoritySet<T>>::put(next_authorities);
-		};
+			<CurrentAuthoritySet<T>>::put(&next_authorities);
 
-		<BestFinalized<T>>::put(hash);
-		<ImportedHeaders<T>>::insert(hash, header);
+			log::info!(
+				"Transitioned from authority set {} to {}! New authorities are: {:?}",
+				current_set_id,
+				current_set_id + 1,
+				next_authorities,
+			);
+		};
 
 		Ok(())
 	}
 
+	/// Verify a GRANDPA justification (finality proof) for a given header.
+	///
+	/// Will use the GRANDPA current authorities known to the pallet.
+	pub(crate) fn verify_justification<T: Config>(
+		justification: &[u8],
+		hash: BridgedBlockHash<T>,
+		number: BridgedBlockNumber<T>,
+	) -> Result<(), sp_runtime::DispatchError> {
+		use bp_header_chain::justification::verify_justification;
+
+		let authority_set = <CurrentAuthoritySet<T>>::get();
+		let voter_set = VoterSet::new(authority_set.authorities).ok_or(<Error<T>>::InvalidAuthoritySet)?;
+		let set_id = authority_set.set_id;
+
+		Ok(
+			verify_justification::<BridgedHeader<T>>((hash, number), set_id, voter_set, &justification).map_err(
+				|e| {
+					log::error!("Received invalid justification for {:?}: {:?}", hash, e);
+					<Error<T>>::InvalidJustification
+				},
+			)?,
+		)
+	}
+
 	/// Since this writes to storage with no real checks this should only be used in functions that
 	/// were called by a trusted origin.
 	pub(crate) fn initialize_bridge<T: Config>(init_params: super::InitializationData<BridgedHeader<T>>) {
@@ -551,16 +542,14 @@ mod tests {
 		Module::<TestRuntime>::initialize(origin, init_data.clone()).map(|_| init_data)
 	}
 
-	fn submit_finality_proof(child: u8, header: u8) -> frame_support::dispatch::DispatchResultWithPostInfo {
-		let child = test_header(child.into());
+	fn submit_finality_proof(header: u8) -> frame_support::dispatch::DispatchResultWithPostInfo {
 		let header = test_header(header.into());
 
 		let set_id = 1;
 		let grandpa_round = 1;
 		let justification = make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode();
-		let ancestry_proof = vec![child, header.clone()];
 
-		Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof)
+		Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification)
 	}
 
 	fn next_block() {
@@ -705,20 +694,19 @@ mod tests {
 			<IsHalted<TestRuntime>>::put(true);
 
 			assert_noop!(
-				Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), test_header(1), vec![], vec![]),
+				Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), test_header(1), vec![]),
 				Error::<TestRuntime>::Halted,
 			);
 		})
 	}
 
 	#[test]
-	fn succesfully_imports_header_with_valid_finality_and_ancestry_proofs() {
+	fn succesfully_imports_header_with_valid_finality() {
 		run_test(|| {
 			initialize_substrate_bridge();
+			assert_ok!(submit_finality_proof(1));
 
-			assert_ok!(submit_finality_proof(1, 2));
-
-			let header = test_header(2);
+			let header = test_header(1);
 			assert_eq!(<BestFinalized<TestRuntime>>::get(), header.hash());
 			assert!(<ImportedHeaders<TestRuntime>>::contains_key(header.hash()));
 		})
@@ -729,17 +717,15 @@ mod tests {
 		run_test(|| {
 			initialize_substrate_bridge();
 
-			let child = test_header(1);
-			let header = test_header(2);
+			let header = test_header(1);
 
 			let set_id = 2;
 			let grandpa_round = 1;
 			let justification =
 				make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode();
-			let ancestry_proof = vec![child, header.clone()];
 
 			assert_err!(
-				Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof,),
+				Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification,),
 				<Error<TestRuntime>>::InvalidJustification
 			);
 		})
@@ -750,41 +736,16 @@ mod tests {
 		run_test(|| {
 			initialize_substrate_bridge();
 
-			let child = test_header(1);
-			let header = test_header(2);
-
+			let header = test_header(1);
 			let justification = [1u8; 32].encode();
-			let ancestry_proof = vec![child, header.clone()];
 
 			assert_err!(
-				Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof,),
+				Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification,),
 				<Error<TestRuntime>>::InvalidJustification
 			);
 		})
 	}
 
-	#[test]
-	fn does_not_import_header_with_invalid_ancestry_proof() {
-		run_test(|| {
-			initialize_substrate_bridge();
-
-			let header = test_header(2);
-
-			let set_id = 1;
-			let grandpa_round = 1;
-			let justification =
-				make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode();
-
-			// For testing, we've made it so that an empty ancestry proof is invalid
-			let ancestry_proof = vec![];
-
-			assert_err!(
-				Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof,),
-				<Error<TestRuntime>>::InvalidAncestryProof
-			);
-		})
-	}
-
 	#[test]
 	fn disallows_invalid_authority_set() {
 		run_test(|| {
@@ -804,10 +765,9 @@ mod tests {
 
 			let header = test_header(1);
 			let justification = [1u8; 32].encode();
-			let ancestry_proof = vec![];
 
 			assert_err!(
-				Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof,),
+				Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification,),
 				<Error<TestRuntime>>::InvalidAuthoritySet
 			);
 		})
@@ -818,9 +778,9 @@ mod tests {
 		run_test(|| {
 			initialize_substrate_bridge();
 
-			assert_ok!(submit_finality_proof(5, 6));
-			assert_err!(submit_finality_proof(3, 4), Error::<TestRuntime>::OldHeader);
-			assert_ok!(submit_finality_proof(7, 8));
+			assert_ok!(submit_finality_proof(4));
+			assert_err!(submit_finality_proof(3), Error::<TestRuntime>::OldHeader);
+			assert_ok!(submit_finality_proof(5));
 		})
 	}
 
@@ -837,8 +797,18 @@ mod tests {
 			let mut header = test_header(2);
 			header.digest = change_log(0);
 
+			// Create a valid justification for the header
+			let set_id = 1;
+			let grandpa_round = 1;
+			let justification =
+				make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode();
+
 			// Let's import our test header
-			assert_ok!(pallet::import_header::<TestRuntime>(header.hash(), header.clone()));
+			assert_ok!(Module::<TestRuntime>::submit_finality_proof(
+				Origin::signed(1),
+				header.clone(),
+				justification
+			));
 
 			// Make sure that our header is the best finalized
 			assert_eq!(<BestFinalized<TestRuntime>>::get(), header.hash());
@@ -862,9 +832,15 @@ mod tests {
 			let mut header = test_header(2);
 			header.digest = change_log(1);
 
+			// Create a valid justification for the header
+			let set_id = 1;
+			let grandpa_round = 1;
+			let justification =
+				make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode();
+
 			// Should not be allowed to import this header
 			assert_err!(
-				pallet::import_header::<TestRuntime>(header.hash(), header),
+				Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification),
 				<Error<TestRuntime>>::UnsupportedScheduledChange
 			);
 		})
@@ -880,9 +856,15 @@ mod tests {
 			let mut header = test_header(2);
 			header.digest = forced_change_log(0);
 
+			// Create a valid justification for the header
+			let set_id = 1;
+			let grandpa_round = 1;
+			let justification =
+				make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode();
+
 			// Should not be allowed to import this header
 			assert_err!(
-				pallet::import_header::<TestRuntime>(header.hash(), header),
+				Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification),
 				<Error<TestRuntime>>::UnsupportedScheduledChange
 			);
 		})
@@ -925,9 +907,10 @@ mod tests {
 	fn rate_limiter_disallows_imports_once_limit_is_hit_in_single_block() {
 		run_test(|| {
 			initialize_substrate_bridge();
-			assert_ok!(submit_finality_proof(1, 2));
-			assert_ok!(submit_finality_proof(3, 4));
-			assert_err!(submit_finality_proof(5, 6), <Error<TestRuntime>>::TooManyRequests);
+
+			assert_ok!(submit_finality_proof(1));
+			assert_ok!(submit_finality_proof(2));
+			assert_err!(submit_finality_proof(3), <Error<TestRuntime>>::TooManyRequests);
 		})
 	}
 
@@ -935,18 +918,10 @@ mod tests {
 	fn rate_limiter_invalid_requests_do_not_count_towards_request_count() {
 		run_test(|| {
 			let submit_invalid_request = || {
-				let child = test_header(1);
-				let header = test_header(2);
-
+				let header = test_header(1);
 				let invalid_justification = vec![4, 2, 4, 2].encode();
-				let ancestry_proof = vec![child, header.clone()];
-
-				Module::<TestRuntime>::submit_finality_proof(
-					Origin::signed(1),
-					header,
-					invalid_justification,
-					ancestry_proof,
-				)
+
+				Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, invalid_justification)
 			};
 
 			initialize_substrate_bridge();
@@ -957,9 +932,9 @@ mod tests {
 			}
 
 			// Can still submit `MaxRequests` requests afterwards
-			assert_ok!(submit_finality_proof(1, 2));
-			assert_ok!(submit_finality_proof(3, 4));
-			assert_err!(submit_finality_proof(5, 6), <Error<TestRuntime>>::TooManyRequests);
+			assert_ok!(submit_finality_proof(1));
+			assert_ok!(submit_finality_proof(2));
+			assert_err!(submit_finality_proof(3), <Error<TestRuntime>>::TooManyRequests);
 		})
 	}
 
@@ -967,11 +942,11 @@ mod tests {
 	fn rate_limiter_allows_request_after_new_block_has_started() {
 		run_test(|| {
 			initialize_substrate_bridge();
-			assert_ok!(submit_finality_proof(1, 2));
-			assert_ok!(submit_finality_proof(3, 4));
+			assert_ok!(submit_finality_proof(1));
+			assert_ok!(submit_finality_proof(2));
 
 			next_block();
-			assert_ok!(submit_finality_proof(5, 6));
+			assert_ok!(submit_finality_proof(3));
 		})
 	}
 
@@ -979,12 +954,12 @@ mod tests {
 	fn rate_limiter_disallows_imports_once_limit_is_hit_across_different_blocks() {
 		run_test(|| {
 			initialize_substrate_bridge();
-			assert_ok!(submit_finality_proof(1, 2));
-			assert_ok!(submit_finality_proof(3, 4));
+			assert_ok!(submit_finality_proof(1));
+			assert_ok!(submit_finality_proof(2));
 
 			next_block();
-			assert_ok!(submit_finality_proof(5, 6));
-			assert_err!(submit_finality_proof(7, 8), <Error<TestRuntime>>::TooManyRequests);
+			assert_ok!(submit_finality_proof(3));
+			assert_err!(submit_finality_proof(4), <Error<TestRuntime>>::TooManyRequests);
 		})
 	}
 
@@ -992,15 +967,15 @@ mod tests {
 	fn rate_limiter_allows_max_requests_after_long_time_with_no_activity() {
 		run_test(|| {
 			initialize_substrate_bridge();
-			assert_ok!(submit_finality_proof(1, 2));
-			assert_ok!(submit_finality_proof(3, 4));
+			assert_ok!(submit_finality_proof(1));
+			assert_ok!(submit_finality_proof(2));
 
 			next_block();
 			next_block();
 
 			next_block();
-			assert_ok!(submit_finality_proof(5, 6));
-			assert_ok!(submit_finality_proof(7, 8));
+			assert_ok!(submit_finality_proof(5));
+			assert_ok!(submit_finality_proof(7));
 		})
 	}
 }
diff --git a/bridges/modules/finality-verifier/src/mock.rs b/bridges/modules/finality-verifier/src/mock.rs
index dc2fc27394f85272e9f468980e71b8c6f89a8fde..f80a374f3710f3078f42cb7a57a721dfa200e3fa 100644
--- a/bridges/modules/finality-verifier/src/mock.rs
+++ b/bridges/modules/finality-verifier/src/mock.rs
@@ -42,7 +42,6 @@ construct_runtime! {
 		UncheckedExtrinsic = UncheckedExtrinsic,
 	{
 		System: frame_system::{Module, Call, Config, Storage, Event<T>},
-		Bridge: pallet_substrate_bridge::{Module},
 		FinalityVerifier: finality_verifier::{Module},
 	}
 }
@@ -79,19 +78,12 @@ impl frame_system::Config for TestRuntime {
 	type SS58Prefix = ();
 }
 
-impl pallet_substrate_bridge::Config for TestRuntime {
-	type BridgedChain = TestBridgedChain;
-}
-
 parameter_types! {
 	pub const MaxRequests: u32 = 2;
 }
 
 impl finality_verifier::Config for TestRuntime {
 	type BridgedChain = TestBridgedChain;
-	type HeaderChain = pallet_substrate_bridge::Module<Self>;
-	type AncestryProof = Vec<<Self::BridgedChain as Chain>::Header>;
-	type AncestryChecker = Checker<<Self::BridgedChain as Chain>::Header, Self::AncestryProof>;
 	type MaxRequests = MaxRequests;
 }
 
@@ -105,15 +97,6 @@ impl Chain for TestBridgedChain {
 	type Header = <TestRuntime as frame_system::Config>::Header;
 }
 
-#[derive(Debug)]
-pub struct Checker<H, P>(std::marker::PhantomData<(H, P)>);
-
-impl<H> bp_header_chain::AncestryChecker<H, Vec<H>> for Checker<H, Vec<H>> {
-	fn are_ancestors(_ancestor: &H, _child: &H, proof: &Vec<H>) -> bool {
-		!proof.is_empty()
-	}
-}
-
 pub fn run_test<T>(test: impl FnOnce() -> T) -> T {
 	sp_io::TestExternalities::new(Default::default()).execute_with(test)
 }
diff --git a/bridges/primitives/header-chain/src/lib.rs b/bridges/primitives/header-chain/src/lib.rs
index 65181df31685974fcf23fd709434fb69ea8aa440..e9f6cee9c9ab83e9d268e225e31337b002402465 100644
--- a/bridges/primitives/header-chain/src/lib.rs
+++ b/bridges/primitives/header-chain/src/lib.rs
@@ -29,7 +29,6 @@ use serde::{Deserialize, Serialize};
 use sp_finality_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID};
 use sp_runtime::RuntimeDebug;
 use sp_runtime::{generic::OpaqueDigestItemId, traits::Header as HeaderT};
-use sp_std::vec::Vec;
 
 pub mod justification;
 
@@ -95,51 +94,6 @@ impl<H: Default, E> HeaderChain<H, E> for () {
 	}
 }
 
-/// A trait for checking if a given child header is a direct descendant of an ancestor.
-pub trait AncestryChecker<H, P> {
-	/// Is the child header a descendant of the ancestor header?
-	fn are_ancestors(ancestor: &H, child: &H, proof: &P) -> bool;
-}
-
-impl<H, P> AncestryChecker<H, P> for () {
-	fn are_ancestors(_ancestor: &H, _child: &H, _proof: &P) -> bool {
-		true
-	}
-}
-
-/// A simple ancestry checker which verifies ancestry by walking every header between `child` and
-/// `ancestor`.
-pub struct LinearAncestryChecker;
-
-impl<H: HeaderT> AncestryChecker<H, Vec<H>> for LinearAncestryChecker {
-	fn are_ancestors(ancestor: &H, child: &H, proof: &Vec<H>) -> bool {
-		// You can't be your own parent
-		if proof.len() < 2 {
-			return false;
-		}
-
-		// Let's make sure that the given headers are actually in the proof
-		match proof.first() {
-			Some(first) if first == ancestor => {}
-			_ => return false,
-		}
-
-		match proof.last() {
-			Some(last) if last == child => {}
-			_ => return false,
-		}
-
-		// Now we actually check the proof
-		for i in 1..proof.len() {
-			if &proof[i - 1].hash() != proof[i].parent_hash() {
-				return false;
-			}
-		}
-
-		true
-	}
-}
-
 /// Find header digest that schedules next GRANDPA authorities set.
 pub fn find_grandpa_authorities_scheduled_change<H: HeaderT>(
 	header: &H,
@@ -155,68 +109,3 @@ pub fn find_grandpa_authorities_scheduled_change<H: HeaderT>(
 	// the right kind of consensus log.
 	header.digest().convert_first(|l| l.try_to(id).and_then(filter_log))
 }
-
-#[cfg(test)]
-mod tests {
-	use super::*;
-	use bp_test_utils::test_header;
-	use sp_runtime::testing::Header;
-
-	#[test]
-	fn can_verify_ancestry_correctly() {
-		let ancestor: Header = test_header(1);
-		let header2: Header = test_header(2);
-		let header3: Header = test_header(3);
-		let child: Header = test_header(4);
-
-		let ancestry_proof = vec![ancestor.clone(), header2, header3, child.clone()];
-
-		assert!(LinearAncestryChecker::are_ancestors(&ancestor, &child, &ancestry_proof));
-	}
-
-	#[test]
-	fn does_not_verify_invalid_proof() {
-		let ancestor: Header = test_header(1);
-		let header2: Header = test_header(2);
-		let header3: Header = test_header(3);
-		let child: Header = test_header(4);
-
-		let ancestry_proof = vec![ancestor.clone(), header3, header2, child.clone()];
-
-		let invalid = !LinearAncestryChecker::are_ancestors(&ancestor, &child, &ancestry_proof);
-		assert!(invalid);
-	}
-
-	#[test]
-	fn header_is_not_allowed_to_be_its_own_ancestor() {
-		let ancestor: Header = test_header(1);
-		let child: Header = ancestor.clone();
-		let ancestry_proof = vec![ancestor.clone()];
-
-		let invalid = !LinearAncestryChecker::are_ancestors(&ancestor, &child, &ancestry_proof);
-		assert!(invalid);
-	}
-
-	#[test]
-	fn proof_is_considered_invalid_if_child_and_ancestor_do_not_match() {
-		let ancestor: Header = test_header(1);
-		let header2: Header = test_header(2);
-		let header3: Header = test_header(3);
-		let child: Header = test_header(4);
-
-		let ancestry_proof = vec![ancestor, header3.clone(), header2.clone(), child];
-
-		let invalid = !LinearAncestryChecker::are_ancestors(&header2, &header3, &ancestry_proof);
-		assert!(invalid);
-	}
-
-	#[test]
-	fn empty_proof_is_invalid() {
-		let ancestor: Header = test_header(1);
-		let child: Header = ancestor.clone();
-		let ancestry_proof = vec![];
-
-		let invalid = !LinearAncestryChecker::are_ancestors(&ancestor, &child, &ancestry_proof);
-		assert!(invalid);
-	}
-}
diff --git a/bridges/relays/substrate/src/millau_headers_to_rialto.rs b/bridges/relays/substrate/src/millau_headers_to_rialto.rs
index 1ac12d2eebede1f40a915daf15110250f0f81a97..889676d673bfcb76ca5e4797e96e88cd0993683d 100644
--- a/bridges/relays/substrate/src/millau_headers_to_rialto.rs
+++ b/bridges/relays/substrate/src/millau_headers_to_rialto.rs
@@ -43,12 +43,9 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto {
 	) -> Result<Self::SignedTransaction, SubstrateError> {
 		let account_id = self.target_sign.signer.public().as_array_ref().clone().into();
 		let nonce = self.target_client.next_account_index(account_id).await?;
-		let call = rialto_runtime::FinalityBridgeMillauCall::submit_finality_proof(
-			header.into_inner(),
-			proof.into_inner(),
-			(),
-		)
-		.into();
+		let call =
+			rialto_runtime::FinalityBridgeMillauCall::submit_finality_proof(header.into_inner(), proof.into_inner())
+				.into();
 
 		let genesis_hash = *self.target_client.genesis_hash();
 		let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign.signer, nonce, call);
diff --git a/bridges/relays/substrate/src/rialto_headers_to_millau.rs b/bridges/relays/substrate/src/rialto_headers_to_millau.rs
index 27fe697aadf76dc475ab993b375fcc782b3734c2..12b2086728a769450fb97c6c82ecbfb339e62e2c 100644
--- a/bridges/relays/substrate/src/rialto_headers_to_millau.rs
+++ b/bridges/relays/substrate/src/rialto_headers_to_millau.rs
@@ -43,12 +43,9 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau {
 	) -> Result<Self::SignedTransaction, SubstrateError> {
 		let account_id = self.target_sign.signer.public().as_array_ref().clone().into();
 		let nonce = self.target_client.next_account_index(account_id).await?;
-		let call = millau_runtime::FinalityBridgeRialtoCall::submit_finality_proof(
-			header.into_inner(),
-			proof.into_inner(),
-			(),
-		)
-		.into();
+		let call =
+			millau_runtime::FinalityBridgeRialtoCall::submit_finality_proof(header.into_inner(), proof.into_inner())
+				.into();
 
 		let genesis_hash = *self.target_client.genesis_hash();
 		let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, nonce, call);