From 2779e80680265cb59c4e0b88858f32a4a2270f45 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 6 Feb 2024 11:36:09 +0300 Subject: [PATCH] Pass finality proof verification context to the call builder (#2823) * pass verification context to the build_submit_finality_proof_call * current_set_id -> context --- relays/lib-substrate-relay/src/finality/mod.rs | 16 +++++++++++----- .../lib-substrate-relay/src/finality/target.rs | 10 ++++++---- .../src/finality_base/engine.rs | 14 +++++++++----- .../lib-substrate-relay/src/on_demand/headers.rs | 14 ++++++++++---- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/relays/lib-substrate-relay/src/finality/mod.rs b/relays/lib-substrate-relay/src/finality/mod.rs index 753648d34e..77adb4c153 100644 --- a/relays/lib-substrate-relay/src/finality/mod.rs +++ b/relays/lib-substrate-relay/src/finality/mod.rs @@ -24,7 +24,7 @@ use crate::{ }; use async_trait::async_trait; -use bp_header_chain::justification::GrandpaJustification; +use bp_header_chain::justification::{GrandpaJustification, JustificationVerificationContext}; use finality_relay::{FinalityPipeline, FinalitySyncPipeline}; use pallet_bridge_grandpa::{Call as BridgeGrandpaCall, Config as BridgeGrandpaConfig}; use relay_substrate_client::{ @@ -111,11 +111,12 @@ impl FinalitySyncPipeline for FinalitySyncPipe /// Different ways of building `submit_finality_proof` calls. pub trait SubmitFinalityProofCallBuilder { - /// Given source chain header and its finality proofs, build call of `submit_finality_proof` - /// function of bridge GRANDPA module at the target chain. + /// Given source chain header, its finality proof and the current authority set id, build call + /// of `submit_finality_proof` function of bridge GRANDPA module at the target chain. fn build_submit_finality_proof_call( header: SyncHeader>, proof: SubstrateFinalityProof

, + context: <

::FinalityEngine as Engine>::FinalityVerificationContext, ) -> CallOf; } @@ -133,12 +134,16 @@ where I: 'static, R::BridgedChain: bp_runtime::Chain

>, CallOf: From>, - P::FinalityEngine: - Engine>>, + P::FinalityEngine: Engine< + P::SourceChain, + FinalityProof = GrandpaJustification>, + FinalityVerificationContext = JustificationVerificationContext, + >, { fn build_submit_finality_proof_call( header: SyncHeader>, proof: GrandpaJustification>, + _context: JustificationVerificationContext, ) -> CallOf { BridgeGrandpaCall::::submit_finality_proof { finality_target: Box::new(header.into_inner()), @@ -172,6 +177,7 @@ macro_rules! generate_submit_finality_proof_call_builder { <$pipeline as $crate::finality_base::SubstrateFinalityPipeline>::SourceChain > >, + _context: bp_header_chain::justification::JustificationVerificationContext, ) -> relay_substrate_client::CallOf< <$pipeline as $crate::finality_base::SubstrateFinalityPipeline>::TargetChain > { diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index 38db0ee2fb..48c011f832 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -113,13 +113,15 @@ impl> header: SyncHeader>, mut proof: SubstrateFinalityProof

, ) -> Result { - // runtime module at target chain may require optimized finality proof - P::FinalityEngine::optimize_proof(&self.client, &header, &mut proof).await?; + // verify and runtime module at target chain may require optimized finality proof + let context = + P::FinalityEngine::verify_and_optimize_proof(&self.client, &header, &mut proof).await?; // now we may submit optimized finality proof let mortality = self.transaction_params.mortality; - let call = - P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); + let call = P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call( + header, proof, context, + ); self.client .submit_and_watch_signed_extrinsic( &self.transaction_params.signer, diff --git a/relays/lib-substrate-relay/src/finality_base/engine.rs b/relays/lib-substrate-relay/src/finality_base/engine.rs index b18cd0715a..f02a4f7096 100644 --- a/relays/lib-substrate-relay/src/finality_base/engine.rs +++ b/relays/lib-substrate-relay/src/finality_base/engine.rs @@ -118,12 +118,15 @@ pub trait Engine: Send { source_client: &impl Client, ) -> Result, SubstrateError>; - /// Optimize finality proof before sending it to the target node. - async fn optimize_proof( + /// Verify and optimize finality proof before sending it to the target node. + /// + /// Apart from optimization, we expect this method to perform all required checks + /// that the `header` and `proof` are valid at the current state of the target chain. + async fn verify_and_optimize_proof( target_client: &impl Client, header: &C::Header, proof: &mut Self::FinalityProof, - ) -> Result<(), SubstrateError>; + ) -> Result; /// Checks whether the given `header` and its finality `proof` fit the maximal expected /// call size limit. If result is `MaxExpectedCallSizeCheck::Exceeds { .. }`, this @@ -217,11 +220,11 @@ impl Engine for Grandpa { source_client.subscribe_grandpa_finality_justifications().await } - async fn optimize_proof( + async fn verify_and_optimize_proof( target_client: &impl Client, header: &C::Header, proof: &mut Self::FinalityProof, - ) -> Result<(), SubstrateError> { + ) -> Result { let verification_context = Grandpa::::finality_verification_context( target_client, target_client.best_header_hash().await?, @@ -236,6 +239,7 @@ impl Engine for Grandpa { &verification_context, proof, ) + .map(|_| verification_context) .map_err(|e| { SubstrateError::Custom(format!( "Failed to optimize {} GRANDPA justification for header {:?}: {:?}", diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index fbab3c8a77..768ce4cb6e 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -155,8 +155,13 @@ impl< finality_source.prove_block_finality(current_required_header).await?; let header_id = header.id(); - // optimize justification before including it into the call - P::FinalityEngine::optimize_proof(&self.target_client, &header, &mut proof).await?; + // verify and optimize justification before including it into the call + let context = P::FinalityEngine::verify_and_optimize_proof( + &self.target_client, + &header, + &mut proof, + ) + .await?; // now we have the header and its proof, but we want to minimize our losses, so let's // check if we'll get the full refund for submitting this header @@ -194,8 +199,9 @@ impl< ); // and then craft the submit-proof call - let call = - P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); + let call = P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call( + header, proof, context, + ); return Ok((header_id, vec![call])); }