optimize justification before submit (#1887)

* optimize justification before submit

* fmt

* spelling

* clippy

* fmt again

* aaand compilation

* clippy
This commit is contained in:
Svyatoslav Nikolsky
2023-02-20 11:57:54 +03:00
committed by Bastian Köcher
parent bb078b8226
commit 1d6e8a9a26
7 changed files with 290 additions and 8 deletions
@@ -22,7 +22,7 @@ use bp_header_chain::{
justification::{verify_justification, GrandpaJustification},
ConsensusLogReader, FinalityProof, GrandpaConsensusLogReader,
};
use bp_runtime::{BasicOperatingMode, OperatingMode};
use bp_runtime::{BasicOperatingMode, HeaderIdProvider, OperatingMode};
use codec::{Decode, Encode};
use finality_grandpa::voter_set::VoterSet;
use num_traits::{One, Zero};
@@ -87,6 +87,13 @@ pub trait Engine<C: Chain>: Send {
client.subscribe_finality_justifications::<Self::FinalityClient>().await
}
/// Optimize finality proof before sending it to the target node.
async fn optimize_proof<TargetChain: Chain>(
target_client: &Client<TargetChain>,
header: &C::Header,
proof: Self::FinalityProof,
) -> Result<Self::FinalityProof, SubstrateError>;
/// Prepare initialization data for the finality bridge pallet.
async fn prepare_initialization_data(
client: Client<C>,
@@ -139,6 +146,48 @@ impl<C: ChainWithGrandpa> Engine<C> for Grandpa<C> {
bp_header_chain::storage_keys::pallet_operating_mode_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME)
}
async fn optimize_proof<TargetChain: Chain>(
target_client: &Client<TargetChain>,
header: &C::Header,
proof: Self::FinalityProof,
) -> Result<Self::FinalityProof, SubstrateError> {
let current_authority_set_key = bp_header_chain::storage_keys::current_authority_set_key(
C::WITH_CHAIN_GRANDPA_PALLET_NAME,
);
let (authority_set, authority_set_id): (
sp_finality_grandpa::AuthorityList,
sp_finality_grandpa::SetId,
) = target_client
.storage_value(current_authority_set_key, None)
.await?
.map(Ok)
.unwrap_or(Err(SubstrateError::Custom(format!(
"{} `CurrentAuthoritySet` is missing from the {} storage",
C::NAME,
TargetChain::NAME,
))))?;
let authority_set =
finality_grandpa::voter_set::VoterSet::new(authority_set).expect("TODO");
// we're risking with race here - we have decided to submit justification some time ago and
// actual authorities set (which we have read now) may have changed, so this
// `optimize_justification` may fail. But if target chain is configured properly, it'll fail
// anyway, after we submit transaction and failing earlier is better. So - it is fine
bp_header_chain::justification::optimize_justification(
(header.hash(), *header.number()),
authority_set_id,
&authority_set,
proof,
)
.map_err(|e| {
SubstrateError::Custom(format!(
"Failed to optimize {} GRANDPA jutification for header {:?}: {:?}",
C::NAME,
header.id(),
e,
))
})
}
/// Prepare initialization data for the GRANDPA verifier pallet.
async fn prepare_initialization_data(
source_client: Client<C>,
@@ -111,6 +111,10 @@ where
header: SyncHeader<HeaderOf<P::SourceChain>>,
proof: SubstrateFinalityProof<P>,
) -> Result<Self::TransactionTracker, Error> {
// runtime module at target chain may require optimized finality proof
let proof = P::FinalityEngine::optimize_proof(&self.client, &header, proof).await?;
// now we may submit optimized finality proof
let transaction_params = self.transaction_params.clone();
let call =
P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof);