Skip to content
This repository has been archived by the owner on Feb 29, 2024. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Guantong committed Jan 5, 2023
1 parent 382ab4b commit 4c5865d
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 48 deletions.
34 changes: 11 additions & 23 deletions modules/grandpa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ mod storage_types;
// crates.io
use finality_grandpa::voter_set::VoterSet;
// darwinia-network
use bp_header_chain::{justification::GrandpaJustification, InitializationData};
use bp_header_chain::{justification::GrandpaJustification, HeaderChain, InitializationData};
use bp_runtime::{
BlockNumberOf, BoundedStorageValue, Chain, HashOf, HasherOf, HeaderOf, OwnedBridgeModule,
};
Expand All @@ -67,6 +67,8 @@ use sp_std::{boxed::Box, convert::TryInto};
/// The target that will be used when publishing logs related to this pallet.
pub const LOG_TARGET: &str = "runtime::bridge-grandpa";

/// Bridged chain from the pallet configuration.
pub type BridgedChain<T, I> = <T as Config<I>>::BridgedChain;
/// Block number of the bridged chain.
pub type BridgedBlockNumber<T, I> = BlockNumberOf<<T as Config<I>>::BridgedChain>;
/// Block hash of the bridged chain.
Expand Down Expand Up @@ -385,8 +387,6 @@ pub mod pallet {
TooManyRequests,
/// The header being imported is older than the best finalized header known to the pallet.
OldHeader,
/// The header is unknown to the pallet.
UnknownHeader,
/// The scheduled authority set change found in the header is unsupported by the pallet.
///
/// This is the case for non-standard (e.g forced) authority set changes.
Expand All @@ -395,8 +395,6 @@ pub mod pallet {
NotInitialized,
/// The pallet has already been initialized.
AlreadyInitialized,
/// The storage proof doesn't contains storage root. So it is invalid for given header.
StorageRootMismatch,
/// Too many authorities in the set.
TooManyAuthoritiesInSet,
/// Too large header.
Expand Down Expand Up @@ -584,9 +582,6 @@ pub use pallet::*;

impl<T: Config<I>, I: 'static> Pallet<T, I> {
/// Get the best finalized header the pallet knows of.
///
/// Returns a dummy header if there is no best header. This can only happen
/// if the pallet has not been initialized yet.
pub fn best_finalized() -> Option<BridgedHeader<T, I>> {
let (_, hash) = <BestFinalized<T, I>>::get()?;
<ImportedHeaders<T, I>>::get(hash).map(|h| h.into_inner())
Expand All @@ -596,21 +591,14 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
pub fn is_known_header(hash: BridgedBlockHash<T, I>) -> bool {
<ImportedHeaders<T, I>>::contains_key(hash)
}
}

/// Verify that the passed storage proof is valid, given it is crafted using
/// known finalized header. If the proof is valid, then the `parse` callback
/// is called and the function returns its result.
pub fn parse_finalized_storage_proof<R>(
hash: BridgedBlockHash<T, I>,
storage_proof: sp_trie::StorageProof,
parse: impl FnOnce(bp_runtime::StorageProofChecker<BridgedBlockHasher<T, I>>) -> R,
) -> Result<R, sp_runtime::DispatchError> {
let header = <ImportedHeaders<T, I>>::get(hash).ok_or(Error::<T, I>::UnknownHeader)?;
let storage_proof_checker =
bp_runtime::StorageProofChecker::new(*header.state_root(), storage_proof)
.map_err(|_| Error::<T, I>::StorageRootMismatch)?;

Ok(parse(storage_proof_checker))
/// Bridge GRANDPA pallet as header chain.
pub type GrandpaChainHeaders<T, I> = Pallet<T, I>;

impl<T: Config<I>, I: 'static> HeaderChain<BridgedChain<T, I>> for GrandpaChainHeaders<T, I> {
fn finalized_header(hash: HashOf<BridgedChain<T, I>>) -> Option<HeaderOf<BridgedChain<T, I>>> {
ImportedHeaders::<T, I>::get(hash).map(|h| h.into_inner())
}
}

Expand Down Expand Up @@ -1122,7 +1110,7 @@ mod tests {
sp_trie::StorageProof::new(vec![]),
|_| (),
),
Error::<TestRuntime>::UnknownHeader,
bp_header_chain::HeaderChainError::UnknownHeader,
);
});
}
Expand Down
2 changes: 2 additions & 0 deletions modules/parachains/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ codec = { package = "parity-scale-codec", version = "3.1", default-features
scale-info = { version = "2.1", default-features = false, features = ["derive"] }
serde = { version = "1.0.101", optional = true }
# darwinia-network
bp-header-chain = { default-features = false, path = "../../primitives/parachains" }
bp-parachains = { default-features = false, path = "../../primitives/parachains" }
bp-polkadot-core = { default-features = false, path = "../../primitives/polkadot-core" }
bp-runtime = { default-features = false, path = "../../primitives/runtime" }
Expand Down Expand Up @@ -39,6 +40,7 @@ std = [
"scale-info/std",
"serde",
# darwinia-network
"bp-header-chain/std",
"bp-parachains/std",
"bp-polkadot-core/std",
"bp-runtime/std",
Expand Down
40 changes: 17 additions & 23 deletions modules/parachains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,13 @@ pub use weights_ext::WeightInfoExt;

mod extension;

// crates.io
use codec::Decode;
// darwinia-network
use bp_header_chain::HeaderChain;
use bp_parachains::{parachain_head_storage_key_at_source, ParaInfo};
use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaHead, ParaHeadsProof, ParaId};
use bp_runtime::StorageProofError;
use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId};
use bp_runtime::{HashOf, HeaderOf, Parachain, StorageProofError};
// paritytech
use frame_support::{dispatch::PostDispatchInfo, traits::Contains};
use sp_runtime::traits::Header as HeaderT;
Expand Down Expand Up @@ -411,27 +414,6 @@ pub mod pallet {
ImportedParaHeads::<T, I>::get(parachain, hash).map(|h| h.into_inner())
}

/// Verify that the passed storage proof is valid, given it is crafted using
/// known finalized header. If the proof is valid, then the `parse` callback
/// is called and the function returns its result.
pub fn parse_finalized_storage_proof<R>(
parachain: ParaId,
hash: ParaHash,
storage_proof: sp_trie::StorageProof,
decode_state_root: impl FnOnce(ParaHead) -> Option<ParaHash>,
parse: impl FnOnce(bp_runtime::StorageProofChecker<ParaHasher>) -> R,
) -> Result<R, sp_runtime::DispatchError> {
let para_head =
Self::parachain_head(parachain, hash).ok_or(Error::<T, I>::UnknownParaHead)?;
let state_root =
decode_state_root(para_head).ok_or(Error::<T, I>::FailedToExtractStateRoot)?;
let storage_proof_checker =
bp_runtime::StorageProofChecker::new(state_root, storage_proof)
.map_err(|_| Error::<T, I>::StorageRootMismatch)?;

Ok(parse(storage_proof_checker))
}

/// Read parachain head from storage proof.
fn read_parachain_head(
storage: &bp_runtime::StorageProofChecker<RelayBlockHasher>,
Expand Down Expand Up @@ -619,6 +601,18 @@ pub mod pallet {
}
pub use pallet::*;

/// Single parachain header chain adapter.
pub struct ParachainHeaders<T, I, C>(PhantomData<(T, I, C)>);

impl<T: Config<I>, I: 'static, C: Parachain<Hash = ParaHash>> HeaderChain<C>
for ParachainHeaders<T, I, C>
{
fn finalized_header(hash: HashOf<C>) -> Option<HeaderOf<C>> {
Pallet::<T, I>::parachain_head(ParaId(C::PARACHAIN_ID), hash)
.and_then(|head| Decode::decode(&mut &head.0[..]).ok())
}
}

#[cfg(test)]
mod tests {
// crates.io
Expand Down
2 changes: 2 additions & 0 deletions primitives/header-chain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ sp-core = { default-features = false, git = "https://github.com/pari
sp-finality-grandpa = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.33" }
sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.33" }
sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.33" }
sp-trie = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.33" }

[dev-dependencies]
# crates.io
Expand All @@ -43,4 +44,5 @@ std = [
"sp-finality-grandpa/std",
"sp-runtime/std",
"sp-std/std",
"sp-trie/std",
]
42 changes: 41 additions & 1 deletion primitives/header-chain/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,50 @@ use scale_info::TypeInfo;
#[cfg(feature = "std")]
use serde::{Deserialize, Serialize};
// darwinia-network
use bp_runtime::BasicOperatingMode;
use bp_runtime::{BasicOperatingMode, Chain, HashOf, HasherOf, HeaderOf, StorageProofChecker};
// paritytech
use frame_support::PalletError;
use sp_finality_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID};
use sp_runtime::{traits::Header as HeaderT, Digest, RuntimeDebug};
use sp_std::boxed::Box;
use sp_trie::StorageProof;

/// Header chain error.
#[derive(Clone, Copy, Decode, Encode, Eq, PalletError, PartialEq, RuntimeDebug, TypeInfo)]
pub enum HeaderChainError {
/// Header with given hash is missing from the chain.
UnknownHeader,
/// The storage proof doesn't contains storage root.
StorageRootMismatch,
}

impl From<HeaderChainError> for &'static str {
fn from(err: HeaderChainError) -> &'static str {
match err {
HeaderChainError::UnknownHeader => "UnknownHeader",
HeaderChainError::StorageRootMismatch => "StorageRootMismatch",
}
}
}

/// Substrate header chain, abstracted from the way it is stored.
pub trait HeaderChain<C: Chain> {
/// Returns finalized header by its hash.
fn finalized_header(hash: HashOf<C>) -> Option<HeaderOf<C>>;
/// Parse storage proof using finalized header.
fn parse_finalized_storage_proof<R>(
hash: HashOf<C>,
storage_proof: StorageProof,
parse: impl FnOnce(StorageProofChecker<HasherOf<C>>) -> R,
) -> Result<R, HeaderChainError> {
let header = Self::finalized_header(hash).ok_or(HeaderChainError::UnknownHeader)?;
let storage_proof_checker =
bp_runtime::StorageProofChecker::new(*header.state_root(), storage_proof)
.map_err(|_| HeaderChainError::StorageRootMismatch)?;

Ok(parse(storage_proof_checker))
}
}

/// A type that can be used as a parameter in a dispatchable function.
///
Expand Down Expand Up @@ -82,6 +121,7 @@ pub struct InitializationData<H: HeaderT> {

/// A trait that provides helper methods for querying the consensus log.
pub trait ConsensusLogReader {
/// Returns true if digest contains item that schedules authorities set change.
fn schedules_authorities_change(digest: &Digest) -> bool;
}

Expand Down
6 changes: 6 additions & 0 deletions primitives/runtime/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ use sp_std::{fmt::Debug, hash::Hash, prelude::*, str::FromStr};
// darwinia-network
use crate::HeaderIdProvider;

/// Minimal parachain representation that may be used from no_std environment.
pub trait Parachain: Chain {
/// Parachain identifier.
const PARACHAIN_ID: u32;
}

/// Block number used by the chain.
pub type BlockNumberOf<C> = <C as Chain>::BlockNumber;

Expand Down
2 changes: 1 addition & 1 deletion primitives/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ mod storage_types;

pub use chain::{
AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, EncodedOrDecodedCall, HashOf,
HasherOf, HeaderOf, IndexOf, SignatureOf, TransactionEraOf,
HasherOf, HeaderOf, IndexOf, Parachain, SignatureOf, TransactionEraOf,
};
pub use frame_support::storage::storage_prefix as storage_value_final_key;
#[cfg(feature = "std")]
Expand Down

0 comments on commit 4c5865d

Please sign in to comment.