mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 23:51:05 +00:00
Use GrandpaJustification instead of Vec<u8> in Pallet API (#847)
* Stop passing raw encoded justifications to pallet API By having the API accept a struct-ified justification we are able to better utilize the justifications fields for weight calculations. * Update relayer code to use decoded justifications * Add justification to `expect()` statement * Fix some imports * Make justification wrapper contain decoded justification * Rename some fields * Get rid of warnings * Appease Clippy * Only decode justification once at init time * Remove unnecessary method * Remove justification wrapper This became kinda unnecessary since we could implement the FinalityProof trait on GrandpaJustification directly.
This commit is contained in:
committed by
Bastian Köcher
parent
904b9f4da5
commit
67cdca8aa4
@@ -36,6 +36,7 @@
|
|||||||
// Runtime-generated enums
|
// Runtime-generated enums
|
||||||
#![allow(clippy::large_enum_variant)]
|
#![allow(clippy::large_enum_variant)]
|
||||||
|
|
||||||
|
use bp_header_chain::justification::GrandpaJustification;
|
||||||
use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf};
|
use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf};
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use finality_grandpa::voter_set::VoterSet;
|
use finality_grandpa::voter_set::VoterSet;
|
||||||
@@ -46,7 +47,6 @@ use serde::{Deserialize, Serialize};
|
|||||||
use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID};
|
use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID};
|
||||||
use sp_runtime::traits::{BadOrigin, Header as HeaderT, Zero};
|
use sp_runtime::traits::{BadOrigin, Header as HeaderT, Zero};
|
||||||
use sp_runtime::RuntimeDebug;
|
use sp_runtime::RuntimeDebug;
|
||||||
use sp_std::vec::Vec;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod mock;
|
mod mock;
|
||||||
@@ -111,7 +111,7 @@ pub mod pallet {
|
|||||||
pub fn submit_finality_proof(
|
pub fn submit_finality_proof(
|
||||||
origin: OriginFor<T>,
|
origin: OriginFor<T>,
|
||||||
finality_target: BridgedHeader<T, I>,
|
finality_target: BridgedHeader<T, I>,
|
||||||
justification: Vec<u8>,
|
justification: GrandpaJustification<BridgedHeader<T, I>>,
|
||||||
) -> DispatchResultWithPostInfo {
|
) -> DispatchResultWithPostInfo {
|
||||||
ensure_operational::<T, I>()?;
|
ensure_operational::<T, I>()?;
|
||||||
let _ = ensure_signed(origin)?;
|
let _ = ensure_signed(origin)?;
|
||||||
@@ -359,7 +359,7 @@ pub mod pallet {
|
|||||||
///
|
///
|
||||||
/// Will use the GRANDPA current authorities known to the pallet.
|
/// Will use the GRANDPA current authorities known to the pallet.
|
||||||
pub(crate) fn verify_justification<T: Config<I>, I: 'static>(
|
pub(crate) fn verify_justification<T: Config<I>, I: 'static>(
|
||||||
justification: &[u8],
|
justification: &GrandpaJustification<BridgedHeader<T, I>>,
|
||||||
hash: BridgedBlockHash<T, I>,
|
hash: BridgedBlockHash<T, I>,
|
||||||
number: BridgedBlockNumber<T, I>,
|
number: BridgedBlockNumber<T, I>,
|
||||||
) -> Result<(), sp_runtime::DispatchError> {
|
) -> Result<(), sp_runtime::DispatchError> {
|
||||||
@@ -515,7 +515,7 @@ pub(crate) fn find_forced_change<H: HeaderT>(
|
|||||||
pub fn initialize_for_benchmarks<T: Config<I>, I: 'static>(header: BridgedHeader<T, I>) {
|
pub fn initialize_for_benchmarks<T: Config<I>, I: 'static>(header: BridgedHeader<T, I>) {
|
||||||
initialize_bridge::<T, I>(InitializationData {
|
initialize_bridge::<T, I>(InitializationData {
|
||||||
header,
|
header,
|
||||||
authority_list: Vec::new(), // we don't verify any proofs in external benchmarks
|
authority_list: sp_std::vec::Vec::new(), // we don't verify any proofs in external benchmarks
|
||||||
set_id: 0,
|
set_id: 0,
|
||||||
is_halted: false,
|
is_halted: false,
|
||||||
});
|
});
|
||||||
@@ -555,7 +555,7 @@ mod tests {
|
|||||||
|
|
||||||
fn submit_finality_proof(header: u8) -> frame_support::dispatch::DispatchResultWithPostInfo {
|
fn submit_finality_proof(header: u8) -> frame_support::dispatch::DispatchResultWithPostInfo {
|
||||||
let header = test_header(header.into());
|
let header = test_header(header.into());
|
||||||
let justification = make_default_justification(&header).encode();
|
let justification = make_default_justification(&header);
|
||||||
|
|
||||||
Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification)
|
Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification)
|
||||||
}
|
}
|
||||||
@@ -701,10 +701,7 @@ mod tests {
|
|||||||
run_test(|| {
|
run_test(|| {
|
||||||
<IsHalted<TestRuntime>>::put(true);
|
<IsHalted<TestRuntime>>::put(true);
|
||||||
|
|
||||||
assert_noop!(
|
assert_noop!(submit_finality_proof(1), Error::<TestRuntime>::Halted,);
|
||||||
Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), test_header(1), vec![]),
|
|
||||||
Error::<TestRuntime>::Halted,
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,7 +728,7 @@ mod tests {
|
|||||||
set_id: 2,
|
set_id: 2,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let justification = make_justification_for_header(params).encode();
|
let justification = make_justification_for_header(params);
|
||||||
|
|
||||||
assert_err!(
|
assert_err!(
|
||||||
Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification,),
|
Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification,),
|
||||||
@@ -746,7 +743,8 @@ mod tests {
|
|||||||
initialize_substrate_bridge();
|
initialize_substrate_bridge();
|
||||||
|
|
||||||
let header = test_header(1);
|
let header = test_header(1);
|
||||||
let justification = [1u8; 32].encode();
|
let mut justification = make_default_justification(&header);
|
||||||
|
justification.round = 42;
|
||||||
|
|
||||||
assert_err!(
|
assert_err!(
|
||||||
Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification,),
|
Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification,),
|
||||||
@@ -771,7 +769,7 @@ mod tests {
|
|||||||
assert_ok!(Module::<TestRuntime>::initialize(Origin::root(), init_data));
|
assert_ok!(Module::<TestRuntime>::initialize(Origin::root(), init_data));
|
||||||
|
|
||||||
let header = test_header(1);
|
let header = test_header(1);
|
||||||
let justification = [1u8; 32].encode();
|
let justification = make_default_justification(&header);
|
||||||
|
|
||||||
assert_err!(
|
assert_err!(
|
||||||
Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification,),
|
Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, justification,),
|
||||||
@@ -805,7 +803,7 @@ mod tests {
|
|||||||
header.digest = change_log(0);
|
header.digest = change_log(0);
|
||||||
|
|
||||||
// Create a valid justification for the header
|
// Create a valid justification for the header
|
||||||
let justification = make_default_justification(&header).encode();
|
let justification = make_default_justification(&header);
|
||||||
|
|
||||||
// Let's import our test header
|
// Let's import our test header
|
||||||
assert_ok!(Module::<TestRuntime>::submit_finality_proof(
|
assert_ok!(Module::<TestRuntime>::submit_finality_proof(
|
||||||
@@ -837,7 +835,7 @@ mod tests {
|
|||||||
header.digest = change_log(1);
|
header.digest = change_log(1);
|
||||||
|
|
||||||
// Create a valid justification for the header
|
// Create a valid justification for the header
|
||||||
let justification = make_default_justification(&header).encode();
|
let justification = make_default_justification(&header);
|
||||||
|
|
||||||
// Should not be allowed to import this header
|
// Should not be allowed to import this header
|
||||||
assert_err!(
|
assert_err!(
|
||||||
@@ -858,7 +856,7 @@ mod tests {
|
|||||||
header.digest = forced_change_log(0);
|
header.digest = forced_change_log(0);
|
||||||
|
|
||||||
// Create a valid justification for the header
|
// Create a valid justification for the header
|
||||||
let justification = make_default_justification(&header).encode();
|
let justification = make_default_justification(&header);
|
||||||
|
|
||||||
// Should not be allowed to import this header
|
// Should not be allowed to import this header
|
||||||
assert_err!(
|
assert_err!(
|
||||||
@@ -917,7 +915,8 @@ mod tests {
|
|||||||
run_test(|| {
|
run_test(|| {
|
||||||
let submit_invalid_request = || {
|
let submit_invalid_request = || {
|
||||||
let header = test_header(1);
|
let header = test_header(1);
|
||||||
let invalid_justification = vec![4, 2, 4, 2].encode();
|
let mut invalid_justification = make_default_justification(&header);
|
||||||
|
invalid_justification.round = 42;
|
||||||
|
|
||||||
Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, invalid_justification)
|
Module::<TestRuntime>::submit_finality_proof(Origin::signed(1), header, invalid_justification)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -215,6 +215,8 @@ where
|
|||||||
/// proof. If the header enacts an authority set change the change will be applied once the
|
/// proof. If the header enacts an authority set change the change will be applied once the
|
||||||
/// header has been finalized.
|
/// header has been finalized.
|
||||||
pub fn import_finality_proof(&mut self, hash: H::Hash, proof: FinalityProof) -> Result<(), FinalizationError> {
|
pub fn import_finality_proof(&mut self, hash: H::Hash, proof: FinalityProof) -> Result<(), FinalizationError> {
|
||||||
|
use codec::Decode;
|
||||||
|
|
||||||
// Make sure that we've previously imported this header
|
// Make sure that we've previously imported this header
|
||||||
let header = self
|
let header = self
|
||||||
.storage
|
.storage
|
||||||
@@ -233,11 +235,15 @@ where
|
|||||||
"We verified the correctness of the authority list during header import,
|
"We verified the correctness of the authority list during header import,
|
||||||
before writing them to storage. This must always be valid.",
|
before writing them to storage. This must always be valid.",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let justification = bp_header_chain::justification::GrandpaJustification::<H>::decode(&mut proof.0.as_slice())
|
||||||
|
.map_err(|_| FinalizationError::InvalidJustification)?;
|
||||||
|
|
||||||
verify_justification::<H>(
|
verify_justification::<H>(
|
||||||
(hash, *header.number()),
|
(hash, *header.number()),
|
||||||
current_authority_set.set_id,
|
current_authority_set.set_id,
|
||||||
&voter_set,
|
&voter_set,
|
||||||
&proof.0,
|
&justification,
|
||||||
)
|
)
|
||||||
.map_err(|_| FinalizationError::InvalidJustification)?;
|
.map_err(|_| FinalizationError::InvalidJustification)?;
|
||||||
log::trace!("Received valid justification for {:?}", header);
|
log::trace!("Received valid justification for {:?}", header);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use frame_support::RuntimeDebug;
|
|||||||
use sp_finality_grandpa::{AuthorityId, AuthoritySignature, SetId};
|
use sp_finality_grandpa::{AuthorityId, AuthoritySignature, SetId};
|
||||||
use sp_runtime::traits::Header as HeaderT;
|
use sp_runtime::traits::Header as HeaderT;
|
||||||
use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet};
|
use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet};
|
||||||
use sp_std::prelude::Vec;
|
use sp_std::prelude::*;
|
||||||
|
|
||||||
/// Justification verification error.
|
/// Justification verification error.
|
||||||
#[derive(RuntimeDebug, PartialEq)]
|
#[derive(RuntimeDebug, PartialEq)]
|
||||||
@@ -58,15 +58,11 @@ pub fn verify_justification<Header: HeaderT>(
|
|||||||
finalized_target: (Header::Hash, Header::Number),
|
finalized_target: (Header::Hash, Header::Number),
|
||||||
authorities_set_id: SetId,
|
authorities_set_id: SetId,
|
||||||
authorities_set: &VoterSet<AuthorityId>,
|
authorities_set: &VoterSet<AuthorityId>,
|
||||||
raw_justification: &[u8],
|
justification: &GrandpaJustification<Header>,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
Header::Number: finality_grandpa::BlockNumberOps,
|
Header::Number: finality_grandpa::BlockNumberOps,
|
||||||
{
|
{
|
||||||
// Decode justification first
|
|
||||||
let justification =
|
|
||||||
GrandpaJustification::<Header>::decode(&mut &*raw_justification).map_err(|_| Error::JustificationDecode)?;
|
|
||||||
|
|
||||||
// Ensure that it is justification for the expected header
|
// Ensure that it is justification for the expected header
|
||||||
if (justification.commit.target_hash, justification.commit.target_number) != finalized_target {
|
if (justification.commit.target_hash, justification.commit.target_number) != finalized_target {
|
||||||
return Err(Error::InvalidJustificationTarget);
|
return Err(Error::InvalidJustificationTarget);
|
||||||
@@ -130,7 +126,7 @@ where
|
|||||||
///
|
///
|
||||||
/// This particular proof is used to prove that headers on a bridged chain
|
/// This particular proof is used to prove that headers on a bridged chain
|
||||||
/// (so not our chain) have been finalized correctly.
|
/// (so not our chain) have been finalized correctly.
|
||||||
#[derive(Encode, Decode, RuntimeDebug)]
|
#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)]
|
||||||
pub struct GrandpaJustification<Header: HeaderT> {
|
pub struct GrandpaJustification<Header: HeaderT> {
|
||||||
/// The round (voting period) this justification is valid for.
|
/// The round (voting period) this justification is valid for.
|
||||||
pub round: u64,
|
pub round: u64,
|
||||||
@@ -140,6 +136,12 @@ pub struct GrandpaJustification<Header: HeaderT> {
|
|||||||
pub votes_ancestries: Vec<Header>,
|
pub votes_ancestries: Vec<Header>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<H: HeaderT> crate::FinalityProof<H::Number> for GrandpaJustification<H> {
|
||||||
|
fn target_header_number(&self) -> H::Number {
|
||||||
|
self.commit.target_number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A utility trait implementing `finality_grandpa::Chain` using a given set of headers.
|
/// A utility trait implementing `finality_grandpa::Chain` using a given set of headers.
|
||||||
#[derive(RuntimeDebug)]
|
#[derive(RuntimeDebug)]
|
||||||
struct AncestryChain<Header: HeaderT> {
|
struct AncestryChain<Header: HeaderT> {
|
||||||
|
|||||||
@@ -94,6 +94,12 @@ impl<H: Default, E> HeaderChain<H, E> for () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Abstract finality proof that is justifying block finality.
|
||||||
|
pub trait FinalityProof<Number>: Clone + Send + Sync + Debug {
|
||||||
|
/// Return number of header that this proof is generated for.
|
||||||
|
fn target_header_number(&self) -> Number;
|
||||||
|
}
|
||||||
|
|
||||||
/// Find header digest that schedules next GRANDPA authorities set.
|
/// Find header digest that schedules next GRANDPA authorities set.
|
||||||
pub fn find_grandpa_authorities_scheduled_change<H: HeaderT>(
|
pub fn find_grandpa_authorities_scheduled_change<H: HeaderT>(
|
||||||
header: &H,
|
header: &H,
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
use bp_header_chain::justification::{verify_justification, Error};
|
use bp_header_chain::justification::{verify_justification, Error};
|
||||||
use bp_test_utils::*;
|
use bp_test_utils::*;
|
||||||
use codec::Encode;
|
|
||||||
|
|
||||||
type TestHeader = sp_runtime::testing::Header;
|
type TestHeader = sp_runtime::testing::Header;
|
||||||
|
|
||||||
@@ -38,7 +37,7 @@ fn valid_justification_accepted() {
|
|||||||
header_id::<TestHeader>(1),
|
header_id::<TestHeader>(1),
|
||||||
TEST_GRANDPA_SET_ID,
|
TEST_GRANDPA_SET_ID,
|
||||||
&voter_set(),
|
&voter_set(),
|
||||||
&make_justification_for_header::<TestHeader>(params).encode()
|
&make_justification_for_header::<TestHeader>(params)
|
||||||
),
|
),
|
||||||
Ok(()),
|
Ok(()),
|
||||||
);
|
);
|
||||||
@@ -60,7 +59,7 @@ fn valid_justification_accepted_with_single_fork() {
|
|||||||
header_id::<TestHeader>(1),
|
header_id::<TestHeader>(1),
|
||||||
TEST_GRANDPA_SET_ID,
|
TEST_GRANDPA_SET_ID,
|
||||||
&voter_set(),
|
&voter_set(),
|
||||||
&make_justification_for_header::<TestHeader>(params).encode()
|
&make_justification_for_header::<TestHeader>(params)
|
||||||
),
|
),
|
||||||
Ok(()),
|
Ok(()),
|
||||||
);
|
);
|
||||||
@@ -94,20 +93,12 @@ fn valid_justification_accepted_with_arbitrary_number_of_authorities() {
|
|||||||
header_id::<TestHeader>(1),
|
header_id::<TestHeader>(1),
|
||||||
TEST_GRANDPA_SET_ID,
|
TEST_GRANDPA_SET_ID,
|
||||||
&voter_set,
|
&voter_set,
|
||||||
&make_justification_for_header::<TestHeader>(params).encode()
|
&make_justification_for_header::<TestHeader>(params)
|
||||||
),
|
),
|
||||||
Ok(()),
|
Ok(()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn justification_with_invalid_encoding_rejected() {
|
|
||||||
assert_eq!(
|
|
||||||
verify_justification::<TestHeader>(header_id::<TestHeader>(1), TEST_GRANDPA_SET_ID, &voter_set(), &[],),
|
|
||||||
Err(Error::JustificationDecode),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn justification_with_invalid_target_rejected() {
|
fn justification_with_invalid_target_rejected() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -115,7 +106,7 @@ fn justification_with_invalid_target_rejected() {
|
|||||||
header_id::<TestHeader>(2),
|
header_id::<TestHeader>(2),
|
||||||
TEST_GRANDPA_SET_ID,
|
TEST_GRANDPA_SET_ID,
|
||||||
&voter_set(),
|
&voter_set(),
|
||||||
&make_default_justification::<TestHeader>(&test_header(1)).encode(),
|
&make_default_justification::<TestHeader>(&test_header(1)),
|
||||||
),
|
),
|
||||||
Err(Error::InvalidJustificationTarget),
|
Err(Error::InvalidJustificationTarget),
|
||||||
);
|
);
|
||||||
@@ -131,7 +122,7 @@ fn justification_with_invalid_commit_rejected() {
|
|||||||
header_id::<TestHeader>(1),
|
header_id::<TestHeader>(1),
|
||||||
TEST_GRANDPA_SET_ID,
|
TEST_GRANDPA_SET_ID,
|
||||||
&voter_set(),
|
&voter_set(),
|
||||||
&justification.encode(),
|
&justification,
|
||||||
),
|
),
|
||||||
Err(Error::InvalidJustificationCommit),
|
Err(Error::InvalidJustificationCommit),
|
||||||
);
|
);
|
||||||
@@ -147,7 +138,7 @@ fn justification_with_invalid_authority_signature_rejected() {
|
|||||||
header_id::<TestHeader>(1),
|
header_id::<TestHeader>(1),
|
||||||
TEST_GRANDPA_SET_ID,
|
TEST_GRANDPA_SET_ID,
|
||||||
&voter_set(),
|
&voter_set(),
|
||||||
&justification.encode(),
|
&justification,
|
||||||
),
|
),
|
||||||
Err(Error::InvalidAuthoritySignature),
|
Err(Error::InvalidAuthoritySignature),
|
||||||
);
|
);
|
||||||
@@ -163,7 +154,7 @@ fn justification_with_invalid_precommit_ancestry() {
|
|||||||
header_id::<TestHeader>(1),
|
header_id::<TestHeader>(1),
|
||||||
TEST_GRANDPA_SET_ID,
|
TEST_GRANDPA_SET_ID,
|
||||||
&voter_set(),
|
&voter_set(),
|
||||||
&justification.encode(),
|
&justification,
|
||||||
),
|
),
|
||||||
Err(Error::InvalidPrecommitAncestries),
|
Err(Error::InvalidPrecommitAncestries),
|
||||||
);
|
);
|
||||||
@@ -186,7 +177,7 @@ fn justification_is_invalid_if_we_dont_meet_threshold() {
|
|||||||
header_id::<TestHeader>(1),
|
header_id::<TestHeader>(1),
|
||||||
TEST_GRANDPA_SET_ID,
|
TEST_GRANDPA_SET_ID,
|
||||||
&voter_set(),
|
&voter_set(),
|
||||||
&make_justification_for_header::<TestHeader>(params).encode()
|
&make_justification_for_header::<TestHeader>(params)
|
||||||
),
|
),
|
||||||
Err(Error::InvalidJustificationCommit),
|
Err(Error::InvalidJustificationCommit),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
//! Logic for checking Substrate storage proofs.
|
//! Logic for checking Substrate storage proofs.
|
||||||
|
|
||||||
use hash_db::{HashDB, Hasher, EMPTY_PREFIX};
|
use hash_db::{HashDB, Hasher, EMPTY_PREFIX};
|
||||||
use sp_core::H256;
|
|
||||||
use sp_runtime::RuntimeDebug;
|
use sp_runtime::RuntimeDebug;
|
||||||
use sp_std::vec::Vec;
|
use sp_std::vec::Vec;
|
||||||
use sp_trie::{read_trie_value, Layout, MemoryDB, StorageProof};
|
use sp_trie::{read_trie_value, Layout, MemoryDB, StorageProof};
|
||||||
@@ -67,7 +66,7 @@ pub enum Error {
|
|||||||
///
|
///
|
||||||
/// NOTE: This should only be used for **testing**.
|
/// NOTE: This should only be used for **testing**.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn craft_valid_storage_proof() -> (H256, StorageProof) {
|
pub fn craft_valid_storage_proof() -> (sp_core::H256, StorageProof) {
|
||||||
use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend};
|
use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend};
|
||||||
|
|
||||||
// construct storage proof
|
// construct storage proof
|
||||||
@@ -106,7 +105,7 @@ pub mod tests {
|
|||||||
|
|
||||||
// checking proof against invalid commitment fails
|
// checking proof against invalid commitment fails
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
<StorageProofChecker<sp_core::Blake2Hasher>>::new(H256::random(), proof).err(),
|
<StorageProofChecker<sp_core::Blake2Hasher>>::new(sp_core::H256::random(), proof).err(),
|
||||||
Some(Error::StorageRootMismatch)
|
Some(Error::StorageRootMismatch)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,9 @@
|
|||||||
|
|
||||||
use crate::finality_target::SubstrateFinalityTarget;
|
use crate::finality_target::SubstrateFinalityTarget;
|
||||||
|
|
||||||
|
use bp_header_chain::justification::GrandpaJustification;
|
||||||
use finality_relay::{FinalitySyncParams, FinalitySyncPipeline};
|
use finality_relay::{FinalitySyncParams, FinalitySyncPipeline};
|
||||||
use relay_substrate_client::{
|
use relay_substrate_client::{finality_source::FinalitySource, BlockNumberOf, Chain, Client, HashOf, SyncHeader};
|
||||||
finality_source::{FinalitySource, Justification},
|
|
||||||
BlockNumberOf, Chain, Client, HashOf, SyncHeader,
|
|
||||||
};
|
|
||||||
use relay_utils::BlockNumberBase;
|
use relay_utils::BlockNumberBase;
|
||||||
use sp_core::Bytes;
|
use sp_core::Bytes;
|
||||||
use std::{fmt::Debug, marker::PhantomData, time::Duration};
|
use std::{fmt::Debug, marker::PhantomData, time::Duration};
|
||||||
@@ -101,7 +99,7 @@ where
|
|||||||
type Hash = HashOf<SourceChain>;
|
type Hash = HashOf<SourceChain>;
|
||||||
type Number = BlockNumberOf<SourceChain>;
|
type Number = BlockNumberOf<SourceChain>;
|
||||||
type Header = SyncHeader<SourceChain::Header>;
|
type Header = SyncHeader<SourceChain::Header>;
|
||||||
type FinalityProof = Justification<SourceChain::BlockNumber>;
|
type FinalityProof = GrandpaJustification<SourceChain::Header>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run Substrate-to-Substrate finality sync.
|
/// Run Substrate-to-Substrate finality sync.
|
||||||
@@ -116,7 +114,7 @@ where
|
|||||||
Hash = HashOf<SourceChain>,
|
Hash = HashOf<SourceChain>,
|
||||||
Number = BlockNumberOf<SourceChain>,
|
Number = BlockNumberOf<SourceChain>,
|
||||||
Header = SyncHeader<SourceChain::Header>,
|
Header = SyncHeader<SourceChain::Header>,
|
||||||
FinalityProof = Justification<SourceChain::BlockNumber>,
|
FinalityProof = GrandpaJustification<SourceChain::Header>,
|
||||||
TargetChain = TargetChain,
|
TargetChain = TargetChain,
|
||||||
>,
|
>,
|
||||||
SourceChain: Clone + Chain,
|
SourceChain: Clone + Chain,
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
use bp_header_chain::{
|
use bp_header_chain::{
|
||||||
find_grandpa_authorities_scheduled_change,
|
find_grandpa_authorities_scheduled_change,
|
||||||
justification::{decode_justification_target, verify_justification},
|
justification::{verify_justification, GrandpaJustification},
|
||||||
};
|
};
|
||||||
use codec::Decode;
|
use codec::Decode;
|
||||||
use finality_grandpa::voter_set::VoterSet;
|
use finality_grandpa::voter_set::VoterSet;
|
||||||
@@ -116,9 +116,12 @@ async fn prepare_initialization_data<SourceChain: Chain>(
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Read initial header.
|
// Read initial header.
|
||||||
|
let justification: GrandpaJustification<SourceChain::Header> = Decode::decode(&mut &justification.0[..])
|
||||||
|
.map_err(|err| format!("Failed to decode {} justification: {:?}", SourceChain::NAME, err))?;
|
||||||
|
|
||||||
let (initial_header_hash, initial_header_number) =
|
let (initial_header_hash, initial_header_number) =
|
||||||
decode_justification_target::<SourceChain::Header>(&justification.0)
|
(justification.commit.target_hash, justification.commit.target_number);
|
||||||
.map_err(|err| format!("Failed to decode {} justification: {:?}", SourceChain::NAME, err))?;
|
|
||||||
let initial_header = source_header(&source_client, initial_header_hash).await?;
|
let initial_header = source_header(&source_client, initial_header_hash).await?;
|
||||||
log::trace!(target: "bridge", "Selected {} initial header: {}/{}",
|
log::trace!(target: "bridge", "Selected {} initial header: {}/{}",
|
||||||
SourceChain::NAME,
|
SourceChain::NAME,
|
||||||
@@ -176,9 +179,10 @@ async fn prepare_initialization_data<SourceChain: Chain>(
|
|||||||
(initial_header_hash, initial_header_number),
|
(initial_header_hash, initial_header_number),
|
||||||
initial_authorities_set_id,
|
initial_authorities_set_id,
|
||||||
&authorities_for_verification,
|
&authorities_for_verification,
|
||||||
&justification.0,
|
&justification,
|
||||||
)
|
)
|
||||||
.is_ok();
|
.is_ok();
|
||||||
|
|
||||||
if is_valid_set_id {
|
if is_valid_set_id {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,11 @@
|
|||||||
|
|
||||||
use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
|
use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
|
||||||
|
|
||||||
|
use bp_header_chain::justification::GrandpaJustification;
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use relay_millau_client::{Millau, SyncHeader as MillauSyncHeader};
|
use relay_millau_client::{Millau, SyncHeader as MillauSyncHeader};
|
||||||
use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams};
|
use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams};
|
||||||
use relay_substrate_client::{finality_source::Justification, Chain, TransactionSignScheme};
|
use relay_substrate_client::{Chain, TransactionSignScheme};
|
||||||
use sp_core::{Bytes, Pair};
|
use sp_core::{Bytes, Pair};
|
||||||
|
|
||||||
/// Millau-to-Rialto finality sync pipeline.
|
/// Millau-to-Rialto finality sync pipeline.
|
||||||
@@ -40,11 +41,9 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto {
|
|||||||
&self,
|
&self,
|
||||||
transaction_nonce: <Rialto as Chain>::Index,
|
transaction_nonce: <Rialto as Chain>::Index,
|
||||||
header: MillauSyncHeader,
|
header: MillauSyncHeader,
|
||||||
proof: Justification<bp_millau::BlockNumber>,
|
proof: GrandpaJustification<bp_millau::Header>,
|
||||||
) -> Bytes {
|
) -> Bytes {
|
||||||
let call =
|
let call = rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof(header.into_inner(), proof).into();
|
||||||
rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof(header.into_inner(), proof.into_inner())
|
|
||||||
.into();
|
|
||||||
|
|
||||||
let genesis_hash = *self.target_client.genesis_hash();
|
let genesis_hash = *self.target_client.genesis_hash();
|
||||||
let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call);
|
let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call);
|
||||||
|
|||||||
@@ -18,10 +18,11 @@
|
|||||||
|
|
||||||
use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
|
use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
|
||||||
|
|
||||||
|
use bp_header_chain::justification::GrandpaJustification;
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use relay_millau_client::{Millau, SigningParams as MillauSigningParams};
|
use relay_millau_client::{Millau, SigningParams as MillauSigningParams};
|
||||||
use relay_rialto_client::{Rialto, SyncHeader as RialtoSyncHeader};
|
use relay_rialto_client::{Rialto, SyncHeader as RialtoSyncHeader};
|
||||||
use relay_substrate_client::{finality_source::Justification, Chain, TransactionSignScheme};
|
use relay_substrate_client::{Chain, TransactionSignScheme};
|
||||||
use sp_core::{Bytes, Pair};
|
use sp_core::{Bytes, Pair};
|
||||||
|
|
||||||
/// Rialto-to-Millau finality sync pipeline.
|
/// Rialto-to-Millau finality sync pipeline.
|
||||||
@@ -40,12 +41,12 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau {
|
|||||||
&self,
|
&self,
|
||||||
transaction_nonce: <Millau as Chain>::Index,
|
transaction_nonce: <Millau as Chain>::Index,
|
||||||
header: RialtoSyncHeader,
|
header: RialtoSyncHeader,
|
||||||
proof: Justification<bp_rialto::BlockNumber>,
|
proof: GrandpaJustification<bp_rialto::Header>,
|
||||||
) -> Bytes {
|
) -> Bytes {
|
||||||
let call = millau_runtime::BridgeGrandpaRialtoCall::<
|
let call = millau_runtime::BridgeGrandpaRialtoCall::<
|
||||||
millau_runtime::Runtime,
|
millau_runtime::Runtime,
|
||||||
millau_runtime::RialtoGrandpaInstance,
|
millau_runtime::RialtoGrandpaInstance,
|
||||||
>::submit_finality_proof(header.into_inner(), proof.into_inner())
|
>::submit_finality_proof(header.into_inner(), proof)
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let genesis_hash = *self.target_client.genesis_hash();
|
let genesis_hash = *self.target_client.genesis_hash();
|
||||||
|
|||||||
@@ -18,9 +18,10 @@
|
|||||||
|
|
||||||
use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
|
use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
|
||||||
|
|
||||||
|
use bp_header_chain::justification::GrandpaJustification;
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use relay_millau_client::{Millau, SigningParams as MillauSigningParams};
|
use relay_millau_client::{Millau, SigningParams as MillauSigningParams};
|
||||||
use relay_substrate_client::{finality_source::Justification, Chain, TransactionSignScheme};
|
use relay_substrate_client::{Chain, TransactionSignScheme};
|
||||||
use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend};
|
use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend};
|
||||||
use sp_core::{Bytes, Pair};
|
use sp_core::{Bytes, Pair};
|
||||||
|
|
||||||
@@ -40,12 +41,12 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau {
|
|||||||
&self,
|
&self,
|
||||||
transaction_nonce: <Millau as Chain>::Index,
|
transaction_nonce: <Millau as Chain>::Index,
|
||||||
header: WestendSyncHeader,
|
header: WestendSyncHeader,
|
||||||
proof: Justification<bp_westend::BlockNumber>,
|
proof: GrandpaJustification<bp_westend::Header>,
|
||||||
) -> Bytes {
|
) -> Bytes {
|
||||||
let call = millau_runtime::BridgeGrandpaWestendCall::<
|
let call = millau_runtime::BridgeGrandpaWestendCall::<
|
||||||
millau_runtime::Runtime,
|
millau_runtime::Runtime,
|
||||||
millau_runtime::WestendGrandpaInstance,
|
millau_runtime::WestendGrandpaInstance,
|
||||||
>::submit_finality_proof(header.into_inner(), proof.into_inner())
|
>::submit_finality_proof(header.into_inner(), proof)
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let genesis_hash = *self.target_client.genesis_hash();
|
let genesis_hash = *self.target_client.genesis_hash();
|
||||||
|
|||||||
@@ -22,35 +22,14 @@ use crate::error::Error;
|
|||||||
use crate::sync_header::SyncHeader;
|
use crate::sync_header::SyncHeader;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use bp_header_chain::justification::decode_justification_target;
|
use bp_header_chain::justification::GrandpaJustification;
|
||||||
use finality_relay::{FinalityProof, FinalitySyncPipeline, SourceClient, SourceHeader};
|
use codec::Decode;
|
||||||
|
use finality_relay::{FinalitySyncPipeline, SourceClient, SourceHeader};
|
||||||
use futures::stream::{unfold, Stream, StreamExt};
|
use futures::stream::{unfold, Stream, StreamExt};
|
||||||
use relay_utils::relay_loop::Client as RelayClient;
|
use relay_utils::relay_loop::Client as RelayClient;
|
||||||
use sp_runtime::traits::Header as HeaderT;
|
use sp_runtime::traits::Header as HeaderT;
|
||||||
use std::{marker::PhantomData, pin::Pin};
|
use std::{marker::PhantomData, pin::Pin};
|
||||||
|
|
||||||
/// Wrapped raw Justification.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Justification<Number> {
|
|
||||||
/// Header number decoded from the [`raw_justification`].
|
|
||||||
target_header_number: Number,
|
|
||||||
/// Raw, encoded justification bytes.
|
|
||||||
raw_justification: sp_runtime::Justification,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Number> Justification<Number> {
|
|
||||||
/// Extract raw justification.
|
|
||||||
pub fn into_inner(self) -> sp_runtime::Justification {
|
|
||||||
self.raw_justification
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Number: relay_utils::BlockNumberBase> FinalityProof<Number> for Justification<Number> {
|
|
||||||
fn target_header_number(&self) -> Number {
|
|
||||||
self.target_header_number
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Substrate node as finality source.
|
/// Substrate node as finality source.
|
||||||
pub struct FinalitySource<C: Chain, P> {
|
pub struct FinalitySource<C: Chain, P> {
|
||||||
client: Client<C>,
|
client: Client<C>,
|
||||||
@@ -94,11 +73,11 @@ where
|
|||||||
Hash = C::Hash,
|
Hash = C::Hash,
|
||||||
Number = C::BlockNumber,
|
Number = C::BlockNumber,
|
||||||
Header = SyncHeader<C::Header>,
|
Header = SyncHeader<C::Header>,
|
||||||
FinalityProof = Justification<C::BlockNumber>,
|
FinalityProof = GrandpaJustification<C::Header>,
|
||||||
>,
|
>,
|
||||||
P::Header: SourceHeader<C::BlockNumber>,
|
P::Header: SourceHeader<C::BlockNumber>,
|
||||||
{
|
{
|
||||||
type FinalityProofsStream = Pin<Box<dyn Stream<Item = Justification<C::BlockNumber>> + Send>>;
|
type FinalityProofsStream = Pin<Box<dyn Stream<Item = GrandpaJustification<C::Header>> + Send>>;
|
||||||
|
|
||||||
async fn best_finalized_block_number(&self) -> Result<P::Number, Error> {
|
async fn best_finalized_block_number(&self) -> Result<P::Number, Error> {
|
||||||
// we **CAN** continue to relay finality proofs if source node is out of sync, because
|
// we **CAN** continue to relay finality proofs if source node is out of sync, because
|
||||||
@@ -114,16 +93,14 @@ where
|
|||||||
) -> Result<(P::Header, Option<P::FinalityProof>), Error> {
|
) -> Result<(P::Header, Option<P::FinalityProof>), Error> {
|
||||||
let header_hash = self.client.block_hash_by_number(number).await?;
|
let header_hash = self.client.block_hash_by_number(number).await?;
|
||||||
let signed_block = self.client.get_block(Some(header_hash)).await?;
|
let signed_block = self.client.get_block(Some(header_hash)).await?;
|
||||||
Ok((
|
|
||||||
signed_block.header().into(),
|
let justification = signed_block
|
||||||
signed_block
|
.justification()
|
||||||
.justification()
|
.map(|raw_justification| GrandpaJustification::<C::Header>::decode(&mut raw_justification.as_slice()))
|
||||||
.cloned()
|
.transpose()
|
||||||
.map(|raw_justification| Justification {
|
.map_err(Error::ResponseParseFailed)?;
|
||||||
target_header_number: number,
|
|
||||||
raw_justification,
|
Ok((signed_block.header().into(), justification))
|
||||||
}),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn finality_proofs(&self) -> Result<Self::FinalityProofsStream, Error> {
|
async fn finality_proofs(&self) -> Result<Self::FinalityProofsStream, Error> {
|
||||||
@@ -132,9 +109,11 @@ where
|
|||||||
move |mut subscription| async move {
|
move |mut subscription| async move {
|
||||||
loop {
|
loop {
|
||||||
let next_justification = subscription.next().await?;
|
let next_justification = subscription.next().await?;
|
||||||
let decoded_target = decode_justification_target::<C::Header>(&next_justification.0);
|
let decoded_justification =
|
||||||
let target_header_number = match decoded_target {
|
GrandpaJustification::<C::Header>::decode(&mut &next_justification.0[..]);
|
||||||
Ok((_, number)) => number,
|
|
||||||
|
let justification = match decoded_justification {
|
||||||
|
Ok(j) => j,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::error!(
|
log::error!(
|
||||||
target: "bridge",
|
target: "bridge",
|
||||||
@@ -147,13 +126,7 @@ where
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return Some((
|
return Some((justification, subscription));
|
||||||
Justification {
|
|
||||||
target_header_number,
|
|
||||||
raw_justification: next_justification.0,
|
|
||||||
},
|
|
||||||
subscription,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ description = "Finality proofs relay"
|
|||||||
async-std = "1.6.5"
|
async-std = "1.6.5"
|
||||||
async-trait = "0.1.40"
|
async-trait = "0.1.40"
|
||||||
backoff = "0.2"
|
backoff = "0.2"
|
||||||
|
bp-header-chain = { path = "../../primitives/header-chain" }
|
||||||
futures = "0.3.5"
|
futures = "0.3.5"
|
||||||
headers-relay = { path = "../headers" }
|
headers-relay = { path = "../headers" }
|
||||||
log = "0.4.11"
|
log = "0.4.11"
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
pub use crate::finality_loop::{run, FinalitySyncParams, SourceClient, TargetClient};
|
pub use crate::finality_loop::{run, FinalitySyncParams, SourceClient, TargetClient};
|
||||||
|
|
||||||
|
use bp_header_chain::FinalityProof;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
mod finality_loop;
|
mod finality_loop;
|
||||||
@@ -50,9 +51,3 @@ pub trait SourceHeader<Number>: Clone + Debug + PartialEq + Send + Sync {
|
|||||||
/// Returns true if this header needs to be submitted to target node.
|
/// Returns true if this header needs to be submitted to target node.
|
||||||
fn is_mandatory(&self) -> bool;
|
fn is_mandatory(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Abstract finality proof that is justifying block finality.
|
|
||||||
pub trait FinalityProof<Number>: Clone + Send + Sync + Debug {
|
|
||||||
/// Return number of header that this proof is generated for.
|
|
||||||
fn target_header_number(&self) -> Number;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user