mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 21:01:02 +00:00
Make finality verifier pallet instantiable (#825)
* make finality verifier pallet instantiable * try to fix benchmarks * fix benchmarks compilation
This commit is contained in:
committed by
Bastian Köcher
parent
715258785f
commit
249a8f73ff
@@ -953,7 +953,7 @@ impl_runtime_apis! {
|
||||
Default::default(),
|
||||
);
|
||||
|
||||
prepare_message_proof::<WithMillauMessageBridge, bp_millau::Hasher, Runtime, _, _, _>(
|
||||
prepare_message_proof::<WithMillauMessageBridge, bp_millau::Hasher, Runtime, (), _, _, _>(
|
||||
params,
|
||||
make_millau_message_key,
|
||||
make_millau_outbound_lane_data_key,
|
||||
@@ -986,7 +986,7 @@ impl_runtime_apis! {
|
||||
};
|
||||
use sp_runtime::traits::Header;
|
||||
|
||||
prepare_message_delivery_proof::<WithMillauMessageBridge, bp_millau::Hasher, Runtime, _, _>(
|
||||
prepare_message_delivery_proof::<WithMillauMessageBridge, bp_millau::Hasher, Runtime, (), _, _>(
|
||||
params,
|
||||
|lane_id| pallet_message_lane::storage_keys::inbound_lane_data_key::<
|
||||
Runtime,
|
||||
|
||||
@@ -62,7 +62,7 @@ pub fn ed25519_sign(target_call: &impl Encode, source_account_id: &impl Encode)
|
||||
}
|
||||
|
||||
/// Prepare proof of messages for the `receive_messages_proof` call.
|
||||
pub fn prepare_message_proof<B, H, R, MM, ML, MH>(
|
||||
pub fn prepare_message_proof<B, H, R, FI, MM, ML, MH>(
|
||||
params: MessageProofParams,
|
||||
make_bridged_message_storage_key: MM,
|
||||
make_bridged_outbound_lane_data_key: ML,
|
||||
@@ -73,7 +73,8 @@ pub fn prepare_message_proof<B, H, R, MM, ML, MH>(
|
||||
where
|
||||
B: MessageBridge,
|
||||
H: Hasher,
|
||||
R: pallet_finality_verifier::Config,
|
||||
R: pallet_finality_verifier::Config<FI>,
|
||||
FI: 'static,
|
||||
<R::BridgedChain as bp_runtime::Chain>::Hash: Into<HashOf<BridgedChain<B>>>,
|
||||
MM: Fn(MessageKey) -> Vec<u8>,
|
||||
ML: Fn(LaneId) -> Vec<u8>,
|
||||
@@ -129,7 +130,7 @@ where
|
||||
// prepare Bridged chain header and insert it into the Substrate pallet
|
||||
let bridged_header = make_bridged_header(root);
|
||||
let bridged_header_hash = bridged_header.hash();
|
||||
pallet_finality_verifier::initialize_for_benchmarks::<R>(bridged_header);
|
||||
pallet_finality_verifier::initialize_for_benchmarks::<R, FI>(bridged_header);
|
||||
|
||||
(
|
||||
FromBridgedChainMessagesProof {
|
||||
@@ -146,7 +147,7 @@ where
|
||||
}
|
||||
|
||||
/// Prepare proof of messages delivery for the `receive_messages_delivery_proof` call.
|
||||
pub fn prepare_message_delivery_proof<B, H, R, ML, MH>(
|
||||
pub fn prepare_message_delivery_proof<B, H, R, FI, ML, MH>(
|
||||
params: MessageDeliveryProofParams<AccountIdOf<ThisChain<B>>>,
|
||||
make_bridged_inbound_lane_data_key: ML,
|
||||
make_bridged_header: MH,
|
||||
@@ -154,7 +155,8 @@ pub fn prepare_message_delivery_proof<B, H, R, ML, MH>(
|
||||
where
|
||||
B: MessageBridge,
|
||||
H: Hasher,
|
||||
R: pallet_finality_verifier::Config,
|
||||
R: pallet_finality_verifier::Config<FI>,
|
||||
FI: 'static,
|
||||
<R::BridgedChain as bp_runtime::Chain>::Hash: Into<HashOf<BridgedChain<B>>>,
|
||||
ML: Fn(LaneId) -> Vec<u8>,
|
||||
MH: Fn(H::Out) -> <R::BridgedChain as bp_runtime::Chain>::Header,
|
||||
@@ -181,7 +183,7 @@ where
|
||||
// prepare Bridged chain header and insert it into the Substrate pallet
|
||||
let bridged_header = make_bridged_header(root);
|
||||
let bridged_header_hash = bridged_header.hash();
|
||||
pallet_finality_verifier::initialize_for_benchmarks::<R>(bridged_header);
|
||||
pallet_finality_verifier::initialize_for_benchmarks::<R, FI>(bridged_header);
|
||||
|
||||
FromBridgedChainMessagesDeliveryProof {
|
||||
bridged_header_hash: bridged_header_hash.into(),
|
||||
|
||||
@@ -55,13 +55,13 @@ mod mock;
|
||||
pub use pallet::*;
|
||||
|
||||
/// Block number of the bridged chain.
|
||||
pub type BridgedBlockNumber<T> = BlockNumberOf<<T as Config>::BridgedChain>;
|
||||
pub type BridgedBlockNumber<T, I> = BlockNumberOf<<T as Config<I>>::BridgedChain>;
|
||||
/// Block hash of the bridged chain.
|
||||
pub type BridgedBlockHash<T> = HashOf<<T as Config>::BridgedChain>;
|
||||
pub type BridgedBlockHash<T, I> = HashOf<<T as Config<I>>::BridgedChain>;
|
||||
/// Hasher of the bridged chain.
|
||||
pub type BridgedBlockHasher<T> = HasherOf<<T as Config>::BridgedChain>;
|
||||
pub type BridgedBlockHasher<T, I> = HasherOf<<T as Config<I>>::BridgedChain>;
|
||||
/// Header of the bridged chain.
|
||||
pub type BridgedHeader<T> = HeaderOf<<T as Config>::BridgedChain>;
|
||||
pub type BridgedHeader<T, I> = HeaderOf<<T as Config<I>>::BridgedChain>;
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
@@ -70,7 +70,7 @@ pub mod pallet {
|
||||
use frame_system::pallet_prelude::*;
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config: frame_system::Config {
|
||||
pub trait Config<I: 'static = ()>: frame_system::Config {
|
||||
/// The chain we are bridging to here.
|
||||
type BridgedChain: Chain;
|
||||
|
||||
@@ -85,12 +85,12 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T>(PhantomData<T>);
|
||||
pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);
|
||||
|
||||
#[pallet::hooks]
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
|
||||
impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pallet<T, I> {
|
||||
fn on_initialize(_n: T::BlockNumber) -> frame_support::weights::Weight {
|
||||
<RequestCount<T>>::mutate(|count| *count = count.saturating_sub(1));
|
||||
<RequestCount<T, I>>::mutate(|count| *count = count.saturating_sub(1));
|
||||
|
||||
(0_u64)
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
@@ -99,7 +99,7 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {
|
||||
impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
/// Verify a target header is finalized according to the given finality proof.
|
||||
///
|
||||
/// It will use the underlying storage pallet to fetch information about the current
|
||||
@@ -110,21 +110,21 @@ pub mod pallet {
|
||||
#[pallet::weight(0)]
|
||||
pub fn submit_finality_proof(
|
||||
origin: OriginFor<T>,
|
||||
finality_target: BridgedHeader<T>,
|
||||
finality_target: BridgedHeader<T, I>,
|
||||
justification: Vec<u8>,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
ensure_operational::<T>()?;
|
||||
ensure_operational::<T, I>()?;
|
||||
let _ = ensure_signed(origin)?;
|
||||
|
||||
ensure!(
|
||||
Self::request_count() < T::MaxRequests::get(),
|
||||
<Error<T>>::TooManyRequests
|
||||
<Error<T, I>>::TooManyRequests
|
||||
);
|
||||
|
||||
let (hash, number) = (finality_target.hash(), finality_target.number());
|
||||
log::trace!("Going to try and finalize header {:?}", finality_target);
|
||||
|
||||
let best_finalized = <ImportedHeaders<T>>::get(<BestFinalized<T>>::get()).expect(
|
||||
let best_finalized = <ImportedHeaders<T, I>>::get(<BestFinalized<T, I>>::get()).expect(
|
||||
"In order to reach this point the bridge must have been initialized. Afterwards,
|
||||
every time `BestFinalized` is updated `ImportedHeaders` is also updated. Therefore
|
||||
`ImportedHeaders` must contain an entry for `BestFinalized`.",
|
||||
@@ -132,14 +132,14 @@ pub mod pallet {
|
||||
|
||||
// We do a quick check here to ensure that our header chain is making progress and isn't
|
||||
// "travelling back in time" (which could be indicative of something bad, e.g a hard-fork).
|
||||
ensure!(best_finalized.number() < number, <Error<T>>::OldHeader);
|
||||
ensure!(best_finalized.number() < number, <Error<T, I>>::OldHeader);
|
||||
|
||||
verify_justification::<T>(&justification, hash, *number)?;
|
||||
verify_justification::<T, I>(&justification, hash, *number)?;
|
||||
|
||||
try_enact_authority_change::<T>(&finality_target)?;
|
||||
<BestFinalized<T>>::put(hash);
|
||||
<ImportedHeaders<T>>::insert(hash, finality_target);
|
||||
<RequestCount<T>>::mutate(|count| *count += 1);
|
||||
try_enact_authority_change::<T, I>(&finality_target)?;
|
||||
<BestFinalized<T, I>>::put(hash);
|
||||
<ImportedHeaders<T, I>>::insert(hash, finality_target);
|
||||
<RequestCount<T, I>>::mutate(|count| *count += 1);
|
||||
|
||||
log::info!("Succesfully imported finalized header with hash {:?}!", hash);
|
||||
|
||||
@@ -158,13 +158,13 @@ pub mod pallet {
|
||||
#[pallet::weight((T::DbWeight::get().reads_writes(2, 5), DispatchClass::Operational))]
|
||||
pub fn initialize(
|
||||
origin: OriginFor<T>,
|
||||
init_data: super::InitializationData<BridgedHeader<T>>,
|
||||
init_data: super::InitializationData<BridgedHeader<T, I>>,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
ensure_owner_or_root::<T>(origin)?;
|
||||
ensure_owner_or_root::<T, I>(origin)?;
|
||||
|
||||
let init_allowed = !<BestFinalized<T>>::exists();
|
||||
ensure!(init_allowed, <Error<T>>::AlreadyInitialized);
|
||||
initialize_bridge::<T>(init_data.clone());
|
||||
let init_allowed = !<BestFinalized<T, I>>::exists();
|
||||
ensure!(init_allowed, <Error<T, I>>::AlreadyInitialized);
|
||||
initialize_bridge::<T, I>(init_data.clone());
|
||||
|
||||
log::info!(
|
||||
"Pallet has been initialized with the following parameters: {:?}",
|
||||
@@ -179,14 +179,14 @@ pub mod pallet {
|
||||
/// May only be called either by root, or by `ModuleOwner`.
|
||||
#[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))]
|
||||
pub fn set_owner(origin: OriginFor<T>, new_owner: Option<T::AccountId>) -> DispatchResultWithPostInfo {
|
||||
ensure_owner_or_root::<T>(origin)?;
|
||||
ensure_owner_or_root::<T, I>(origin)?;
|
||||
match new_owner {
|
||||
Some(new_owner) => {
|
||||
ModuleOwner::<T>::put(&new_owner);
|
||||
ModuleOwner::<T, I>::put(&new_owner);
|
||||
log::info!("Setting pallet Owner to: {:?}", new_owner);
|
||||
}
|
||||
None => {
|
||||
ModuleOwner::<T>::kill();
|
||||
ModuleOwner::<T, I>::kill();
|
||||
log::info!("Removed Owner of pallet.");
|
||||
}
|
||||
}
|
||||
@@ -199,8 +199,8 @@ pub mod pallet {
|
||||
/// May only be called either by root, or by `ModuleOwner`.
|
||||
#[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))]
|
||||
pub fn set_operational(origin: OriginFor<T>, operational: bool) -> DispatchResultWithPostInfo {
|
||||
ensure_owner_or_root::<T>(origin)?;
|
||||
<IsHalted<T>>::put(operational);
|
||||
ensure_owner_or_root::<T, I>(origin)?;
|
||||
<IsHalted<T, I>>::put(operational);
|
||||
|
||||
if operational {
|
||||
log::info!("Resuming pallet operations.");
|
||||
@@ -221,23 +221,25 @@ pub mod pallet {
|
||||
/// that the pallet can always make progress.
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn request_count)]
|
||||
pub(super) type RequestCount<T: Config> = StorageValue<_, u32, ValueQuery>;
|
||||
pub(super) type RequestCount<T: Config<I>, I: 'static = ()> = StorageValue<_, u32, ValueQuery>;
|
||||
|
||||
/// Hash of the header used to bootstrap the pallet.
|
||||
#[pallet::storage]
|
||||
pub(super) type InitialHash<T: Config> = StorageValue<_, BridgedBlockHash<T>, ValueQuery>;
|
||||
pub(super) type InitialHash<T: Config<I>, I: 'static = ()> = StorageValue<_, BridgedBlockHash<T, I>, ValueQuery>;
|
||||
|
||||
/// Hash of the best finalized header.
|
||||
#[pallet::storage]
|
||||
pub(super) type BestFinalized<T: Config> = StorageValue<_, BridgedBlockHash<T>, ValueQuery>;
|
||||
pub(super) type BestFinalized<T: Config<I>, I: 'static = ()> = StorageValue<_, BridgedBlockHash<T, I>, ValueQuery>;
|
||||
|
||||
/// Headers which have been imported into the pallet.
|
||||
#[pallet::storage]
|
||||
pub(super) type ImportedHeaders<T: Config> = StorageMap<_, Identity, BridgedBlockHash<T>, BridgedHeader<T>>;
|
||||
pub(super) type ImportedHeaders<T: Config<I>, I: 'static = ()> =
|
||||
StorageMap<_, Identity, BridgedBlockHash<T, I>, BridgedHeader<T, I>>;
|
||||
|
||||
/// The current GRANDPA Authority set.
|
||||
#[pallet::storage]
|
||||
pub(super) type CurrentAuthoritySet<T: Config> = StorageValue<_, bp_header_chain::AuthoritySet, ValueQuery>;
|
||||
pub(super) type CurrentAuthoritySet<T: Config<I>, I: 'static = ()> =
|
||||
StorageValue<_, bp_header_chain::AuthoritySet, ValueQuery>;
|
||||
|
||||
/// Optional pallet owner.
|
||||
///
|
||||
@@ -246,20 +248,20 @@ pub mod pallet {
|
||||
/// runtime methods may still be used to do that (i.e. democracy::referendum to update halt
|
||||
/// flag directly or call the `halt_operations`).
|
||||
#[pallet::storage]
|
||||
pub(super) type ModuleOwner<T: Config> = StorageValue<_, T::AccountId, OptionQuery>;
|
||||
pub(super) type ModuleOwner<T: Config<I>, I: 'static = ()> = StorageValue<_, T::AccountId, OptionQuery>;
|
||||
|
||||
/// If true, all pallet transactions are failed immediately.
|
||||
#[pallet::storage]
|
||||
pub(super) type IsHalted<T: Config> = StorageValue<_, bool, ValueQuery>;
|
||||
pub(super) type IsHalted<T: Config<I>, I: 'static = ()> = StorageValue<_, bool, ValueQuery>;
|
||||
|
||||
#[pallet::genesis_config]
|
||||
pub struct GenesisConfig<T: Config> {
|
||||
pub struct GenesisConfig<T: Config<I>, I: 'static = ()> {
|
||||
owner: Option<T::AccountId>,
|
||||
init_data: Option<super::InitializationData<BridgedHeader<T>>>,
|
||||
init_data: Option<super::InitializationData<BridgedHeader<T, I>>>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: Config> Default for GenesisConfig<T> {
|
||||
impl<T: Config<I>, I: 'static> Default for GenesisConfig<T, I> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
owner: None,
|
||||
@@ -269,24 +271,24 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
#[pallet::genesis_build]
|
||||
impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
|
||||
impl<T: Config<I>, I: 'static> GenesisBuild<T, I> for GenesisConfig<T, I> {
|
||||
fn build(&self) {
|
||||
if let Some(ref owner) = self.owner {
|
||||
<ModuleOwner<T>>::put(owner);
|
||||
<ModuleOwner<T, I>>::put(owner);
|
||||
}
|
||||
|
||||
if let Some(init_data) = self.init_data.clone() {
|
||||
initialize_bridge::<T>(init_data);
|
||||
initialize_bridge::<T, I>(init_data);
|
||||
} else {
|
||||
// Since the bridge hasn't been initialized we shouldn't allow anyone to perform
|
||||
// transactions.
|
||||
<IsHalted<T>>::put(true);
|
||||
<IsHalted<T, I>>::put(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
pub enum Error<T, I = ()> {
|
||||
/// The given justification is invalid for the given header.
|
||||
InvalidJustification,
|
||||
/// The authority set from the underlying header chain is invalid.
|
||||
@@ -314,20 +316,20 @@ pub mod pallet {
|
||||
///
|
||||
/// 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>,
|
||||
pub(crate) fn try_enact_authority_change<T: Config<I>, I: 'static>(
|
||||
header: &BridgedHeader<T, I>,
|
||||
) -> 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(),
|
||||
<Error<T>>::UnsupportedScheduledChange
|
||||
<Error<T, I>>::UnsupportedScheduledChange
|
||||
);
|
||||
|
||||
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);
|
||||
ensure!(change.delay == Zero::zero(), <Error<T, I>>::UnsupportedScheduledChange);
|
||||
|
||||
let current_set_id = <CurrentAuthoritySet<T>>::get().set_id;
|
||||
let current_set_id = <CurrentAuthoritySet<T, I>>::get().set_id;
|
||||
// TODO [#788]: Stop manually increasing the `set_id` here.
|
||||
let next_authorities = bp_header_chain::AuthoritySet {
|
||||
authorities: change.next_authorities,
|
||||
@@ -336,7 +338,7 @@ pub mod pallet {
|
||||
|
||||
// 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, I>>::put(&next_authorities);
|
||||
|
||||
log::info!(
|
||||
"Transitioned from authority set {} to {}! New authorities are: {:?}",
|
||||
@@ -352,22 +354,22 @@ pub mod pallet {
|
||||
/// 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>(
|
||||
pub(crate) fn verify_justification<T: Config<I>, I: 'static>(
|
||||
justification: &[u8],
|
||||
hash: BridgedBlockHash<T>,
|
||||
number: BridgedBlockNumber<T>,
|
||||
hash: BridgedBlockHash<T, I>,
|
||||
number: BridgedBlockNumber<T, I>,
|
||||
) -> 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 authority_set = <CurrentAuthoritySet<T, I>>::get();
|
||||
let voter_set = VoterSet::new(authority_set.authorities).ok_or(<Error<T, I>>::InvalidAuthoritySet)?;
|
||||
let set_id = authority_set.set_id;
|
||||
|
||||
Ok(
|
||||
verify_justification::<BridgedHeader<T>>((hash, number), set_id, voter_set, &justification).map_err(
|
||||
verify_justification::<BridgedHeader<T, I>>((hash, number), set_id, voter_set, &justification).map_err(
|
||||
|e| {
|
||||
log::error!("Received invalid justification for {:?}: {:?}", hash, e);
|
||||
<Error<T>>::InvalidJustification
|
||||
<Error<T, I>>::InvalidJustification
|
||||
},
|
||||
)?,
|
||||
)
|
||||
@@ -375,7 +377,9 @@ pub mod pallet {
|
||||
|
||||
/// 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>>) {
|
||||
pub(crate) fn initialize_bridge<T: Config<I>, I: 'static>(
|
||||
init_params: super::InitializationData<BridgedHeader<T, I>>,
|
||||
) {
|
||||
let super::InitializationData {
|
||||
header,
|
||||
authority_list,
|
||||
@@ -384,44 +388,44 @@ pub mod pallet {
|
||||
} = init_params;
|
||||
|
||||
let initial_hash = header.hash();
|
||||
<InitialHash<T>>::put(initial_hash);
|
||||
<BestFinalized<T>>::put(initial_hash);
|
||||
<ImportedHeaders<T>>::insert(initial_hash, header);
|
||||
<InitialHash<T, I>>::put(initial_hash);
|
||||
<BestFinalized<T, I>>::put(initial_hash);
|
||||
<ImportedHeaders<T, I>>::insert(initial_hash, header);
|
||||
|
||||
let authority_set = bp_header_chain::AuthoritySet::new(authority_list, set_id);
|
||||
<CurrentAuthoritySet<T>>::put(authority_set);
|
||||
<CurrentAuthoritySet<T, I>>::put(authority_set);
|
||||
|
||||
<IsHalted<T>>::put(is_halted);
|
||||
<IsHalted<T, I>>::put(is_halted);
|
||||
}
|
||||
|
||||
/// Ensure that the origin is either root, or `ModuleOwner`.
|
||||
fn ensure_owner_or_root<T: Config>(origin: T::Origin) -> Result<(), BadOrigin> {
|
||||
fn ensure_owner_or_root<T: Config<I>, I: 'static>(origin: T::Origin) -> Result<(), BadOrigin> {
|
||||
match origin.into() {
|
||||
Ok(RawOrigin::Root) => Ok(()),
|
||||
Ok(RawOrigin::Signed(ref signer)) if Some(signer) == <ModuleOwner<T>>::get().as_ref() => Ok(()),
|
||||
Ok(RawOrigin::Signed(ref signer)) if Some(signer) == <ModuleOwner<T, I>>::get().as_ref() => Ok(()),
|
||||
_ => Err(BadOrigin),
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensure that the pallet is in operational mode (not halted).
|
||||
fn ensure_operational<T: Config>() -> Result<(), Error<T>> {
|
||||
if <IsHalted<T>>::get() {
|
||||
Err(<Error<T>>::Halted)
|
||||
fn ensure_operational<T: Config<I>, I: 'static>() -> Result<(), Error<T, I>> {
|
||||
if <IsHalted<T, I>>::get() {
|
||||
Err(<Error<T, I>>::Halted)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
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() -> BridgedHeader<T> {
|
||||
let hash = <BestFinalized<T>>::get();
|
||||
<ImportedHeaders<T>>::get(hash).unwrap_or_else(|| {
|
||||
<BridgedHeader<T>>::new(
|
||||
pub fn best_finalized() -> BridgedHeader<T, I> {
|
||||
let hash = <BestFinalized<T, I>>::get();
|
||||
<ImportedHeaders<T, I>>::get(hash).unwrap_or_else(|| {
|
||||
<BridgedHeader<T, I>>::new(
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
@@ -432,21 +436,21 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
|
||||
/// Check if a particular header is known to the bridge pallet.
|
||||
pub fn is_known_header(hash: BridgedBlockHash<T>) -> bool {
|
||||
<ImportedHeaders<T>>::contains_key(hash)
|
||||
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>,
|
||||
hash: BridgedBlockHash<T, I>,
|
||||
storage_proof: sp_trie::StorageProof,
|
||||
parse: impl FnOnce(bp_runtime::StorageProofChecker<BridgedBlockHasher<T>>) -> R,
|
||||
parse: impl FnOnce(bp_runtime::StorageProofChecker<BridgedBlockHasher<T, I>>) -> R,
|
||||
) -> Result<R, sp_runtime::DispatchError> {
|
||||
let header = <ImportedHeaders<T>>::get(hash).ok_or(Error::<T>::UnknownHeader)?;
|
||||
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>::StorageRootMismatch)?;
|
||||
.map_err(|_| Error::<T, I>::StorageRootMismatch)?;
|
||||
|
||||
Ok(parse(storage_proof_checker))
|
||||
}
|
||||
@@ -504,8 +508,8 @@ pub(crate) fn find_forced_change<H: HeaderT>(
|
||||
|
||||
/// (Re)initialize bridge with given header for using it in external benchmarks.
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub fn initialize_for_benchmarks<T: Config>(header: BridgedHeader<T>) {
|
||||
initialize_bridge::<T>(InitializationData {
|
||||
pub fn initialize_for_benchmarks<T: Config<I>, I: 'static>(header: BridgedHeader<T, I>) {
|
||||
initialize_bridge::<T, I>(InitializationData {
|
||||
header,
|
||||
authority_list: Vec::new(), // we don't verify any proofs in external benchmarks
|
||||
set_id: 0,
|
||||
@@ -603,7 +607,7 @@ mod tests {
|
||||
run_test(|| {
|
||||
assert_eq!(
|
||||
BestFinalized::<TestRuntime>::get(),
|
||||
BridgedBlockHash::<TestRuntime>::default()
|
||||
BridgedBlockHash::<TestRuntime, ()>::default()
|
||||
);
|
||||
assert_eq!(Module::<TestRuntime>::best_finalized(), test_header(0));
|
||||
|
||||
|
||||
@@ -26,9 +26,9 @@ use sp_runtime::{
|
||||
};
|
||||
|
||||
pub type AccountId = u64;
|
||||
pub type TestHeader = crate::BridgedHeader<TestRuntime>;
|
||||
pub type TestNumber = crate::BridgedBlockNumber<TestRuntime>;
|
||||
pub type TestHash = crate::BridgedBlockHash<TestRuntime>;
|
||||
pub type TestHeader = crate::BridgedHeader<TestRuntime, ()>;
|
||||
pub type TestNumber = crate::BridgedBlockNumber<TestRuntime, ()>;
|
||||
pub type TestHash = crate::BridgedBlockHash<TestRuntime, ()>;
|
||||
|
||||
type Block = frame_system::mocking::MockBlock<TestRuntime>;
|
||||
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<TestRuntime>;
|
||||
|
||||
Reference in New Issue
Block a user