mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 22:11:02 +00:00
remove duplicate parachain heads exension (#1444)
* remove duplicate parachain heads exension * fix benchmarks compilation * actually fix it
This commit is contained in:
committed by
Bastian Köcher
parent
db2bc11476
commit
53780cfd1a
@@ -565,6 +565,11 @@ pallet_bridge_grandpa::declare_bridge_reject_obsolete_grandpa_header! {
|
|||||||
Call::BridgeWestendGrandpa => WestendGrandpaInstance
|
Call::BridgeWestendGrandpa => WestendGrandpaInstance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pallet_bridge_parachains::declare_bridge_reject_obsolete_parachain_header! {
|
||||||
|
Runtime,
|
||||||
|
Call::BridgeRialtoParachains => WithRialtoParachainsInstance
|
||||||
|
}
|
||||||
|
|
||||||
/// The address format for describing accounts.
|
/// The address format for describing accounts.
|
||||||
pub type Address = AccountId;
|
pub type Address = AccountId;
|
||||||
/// Block header type as expected by this runtime.
|
/// Block header type as expected by this runtime.
|
||||||
@@ -586,6 +591,7 @@ pub type SignedExtra = (
|
|||||||
frame_system::CheckWeight<Runtime>,
|
frame_system::CheckWeight<Runtime>,
|
||||||
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
|
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
|
||||||
BridgeRejectObsoleteGrandpaHeader,
|
BridgeRejectObsoleteGrandpaHeader,
|
||||||
|
BridgeRejectObsoleteParachainHeader,
|
||||||
);
|
);
|
||||||
/// The payload being signed in transactions.
|
/// The payload being signed in transactions.
|
||||||
pub type SignedPayload = generic::SignedPayload<Call, SignedExtra>;
|
pub type SignedPayload = generic::SignedPayload<Call, SignedExtra>;
|
||||||
@@ -994,7 +1000,11 @@ impl_runtime_apis! {
|
|||||||
parachains: &[bp_polkadot_core::parachains::ParaId],
|
parachains: &[bp_polkadot_core::parachains::ParaId],
|
||||||
parachain_head_size: u32,
|
parachain_head_size: u32,
|
||||||
proof_size: bp_runtime::StorageProofSize,
|
proof_size: bp_runtime::StorageProofSize,
|
||||||
) -> (pallet_bridge_parachains::RelayBlockHash, bp_polkadot_core::parachains::ParaHeadsProof) {
|
) -> (
|
||||||
|
pallet_bridge_parachains::RelayBlockNumber,
|
||||||
|
pallet_bridge_parachains::RelayBlockHash,
|
||||||
|
bp_polkadot_core::parachains::ParaHeadsProof,
|
||||||
|
) {
|
||||||
bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof::<Runtime, WithRialtoParachainsInstance>(
|
bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof::<Runtime, WithRialtoParachainsInstance>(
|
||||||
parachains,
|
parachains,
|
||||||
parachain_head_size,
|
parachain_head_size,
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ where
|
|||||||
// finally - prepare storage proof and update environment
|
// finally - prepare storage proof and update environment
|
||||||
let (state_root, storage_proof) =
|
let (state_root, storage_proof) =
|
||||||
prepare_messages_storage_proof::<B, BHH>(¶ms, message_payload);
|
prepare_messages_storage_proof::<B, BHH>(¶ms, message_payload);
|
||||||
let bridged_header_hash = insert_header_to_grandpa_pallet::<R, FI>(state_root);
|
let (_, bridged_header_hash) = insert_header_to_grandpa_pallet::<R, FI>(state_root);
|
||||||
|
|
||||||
(
|
(
|
||||||
FromBridgedChainMessagesProof {
|
FromBridgedChainMessagesProof {
|
||||||
@@ -132,7 +132,7 @@ where
|
|||||||
let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect();
|
let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect();
|
||||||
|
|
||||||
// finally insert header with given state root to our storage
|
// finally insert header with given state root to our storage
|
||||||
let bridged_header_hash = insert_header_to_grandpa_pallet::<R, FI>(root);
|
let (_, bridged_header_hash) = insert_header_to_grandpa_pallet::<R, FI>(root);
|
||||||
|
|
||||||
FromBridgedChainMessagesDeliveryProof {
|
FromBridgedChainMessagesDeliveryProof {
|
||||||
bridged_header_hash: bridged_header_hash.into(),
|
bridged_header_hash: bridged_header_hash.into(),
|
||||||
@@ -207,14 +207,15 @@ where
|
|||||||
/// Insert header to the bridge GRANDPA pallet.
|
/// Insert header to the bridge GRANDPA pallet.
|
||||||
pub(crate) fn insert_header_to_grandpa_pallet<R, GI>(
|
pub(crate) fn insert_header_to_grandpa_pallet<R, GI>(
|
||||||
state_root: bp_runtime::HashOf<R::BridgedChain>,
|
state_root: bp_runtime::HashOf<R::BridgedChain>,
|
||||||
) -> bp_runtime::HashOf<R::BridgedChain>
|
) -> (bp_runtime::BlockNumberOf<R::BridgedChain>, bp_runtime::HashOf<R::BridgedChain>)
|
||||||
where
|
where
|
||||||
R: pallet_bridge_grandpa::Config<GI>,
|
R: pallet_bridge_grandpa::Config<GI>,
|
||||||
GI: 'static,
|
GI: 'static,
|
||||||
R::BridgedChain: bp_runtime::Chain,
|
R::BridgedChain: bp_runtime::Chain,
|
||||||
{
|
{
|
||||||
|
let bridged_block_number = Zero::zero();
|
||||||
let bridged_header = bp_runtime::HeaderOf::<R::BridgedChain>::new(
|
let bridged_header = bp_runtime::HeaderOf::<R::BridgedChain>::new(
|
||||||
Zero::zero(),
|
bridged_block_number,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
state_root,
|
state_root,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
@@ -222,7 +223,7 @@ where
|
|||||||
);
|
);
|
||||||
let bridged_header_hash = bridged_header.hash();
|
let bridged_header_hash = bridged_header.hash();
|
||||||
pallet_bridge_grandpa::initialize_for_benchmarks::<R, GI>(bridged_header);
|
pallet_bridge_grandpa::initialize_for_benchmarks::<R, GI>(bridged_header);
|
||||||
bridged_header_hash
|
(bridged_block_number, bridged_header_hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Populate trie with dummy keys+values until trie has at least given size.
|
/// Populate trie with dummy keys+values until trie has at least given size.
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use bp_polkadot_core::parachains::{ParaHead, ParaHeadsProof, ParaId};
|
|||||||
use bp_runtime::StorageProofSize;
|
use bp_runtime::StorageProofSize;
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use frame_support::traits::Get;
|
use frame_support::traits::Get;
|
||||||
use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher};
|
use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber};
|
||||||
use sp_std::prelude::*;
|
use sp_std::prelude::*;
|
||||||
use sp_trie::{record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut};
|
use sp_trie::{record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut};
|
||||||
|
|
||||||
@@ -37,13 +37,13 @@ pub fn prepare_parachain_heads_proof<R, PI>(
|
|||||||
parachains: &[ParaId],
|
parachains: &[ParaId],
|
||||||
parachain_head_size: u32,
|
parachain_head_size: u32,
|
||||||
size: StorageProofSize,
|
size: StorageProofSize,
|
||||||
) -> (RelayBlockHash, ParaHeadsProof)
|
) -> (RelayBlockNumber, RelayBlockHash, ParaHeadsProof)
|
||||||
where
|
where
|
||||||
R: pallet_bridge_parachains::Config<PI>
|
R: pallet_bridge_parachains::Config<PI>
|
||||||
+ pallet_bridge_grandpa::Config<R::BridgesGrandpaPalletInstance>,
|
+ pallet_bridge_grandpa::Config<R::BridgesGrandpaPalletInstance>,
|
||||||
PI: 'static,
|
PI: 'static,
|
||||||
<R as pallet_bridge_grandpa::Config<R::BridgesGrandpaPalletInstance>>::BridgedChain:
|
<R as pallet_bridge_grandpa::Config<R::BridgesGrandpaPalletInstance>>::BridgedChain:
|
||||||
bp_runtime::Chain<Hash = RelayBlockHash>,
|
bp_runtime::Chain<BlockNumber = RelayBlockNumber, Hash = RelayBlockHash>,
|
||||||
{
|
{
|
||||||
let parachain_head = ParaHead(vec![0u8; parachain_head_size as usize]);
|
let parachain_head = ParaHead(vec![0u8; parachain_head_size as usize]);
|
||||||
|
|
||||||
@@ -73,8 +73,8 @@ where
|
|||||||
.expect("record_all_keys should not fail in benchmarks");
|
.expect("record_all_keys should not fail in benchmarks");
|
||||||
let proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect();
|
let proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect();
|
||||||
|
|
||||||
let relay_block_hash =
|
let (relay_block_number, relay_block_hash) =
|
||||||
insert_header_to_grandpa_pallet::<R, R::BridgesGrandpaPalletInstance>(state_root);
|
insert_header_to_grandpa_pallet::<R, R::BridgesGrandpaPalletInstance>(state_root);
|
||||||
|
|
||||||
(relay_block_hash, ParaHeadsProof(proof))
|
(relay_block_number, relay_block_hash, ParaHeadsProof(proof))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,11 @@
|
|||||||
/// Call::BridgeWestendGrandpa => WestendGrandpaInstance,
|
/// Call::BridgeWestendGrandpa => WestendGrandpaInstance,
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// The goal of this extension is to avoid "mining" transactions that provide
|
||||||
|
/// outdated bridged chain headers. Without that extension, even honest relayers
|
||||||
|
/// may lose their funds if there are multiple relays running and submitting the
|
||||||
|
/// same information.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! declare_bridge_reject_obsolete_grandpa_header {
|
macro_rules! declare_bridge_reject_obsolete_grandpa_header {
|
||||||
($runtime:ident, $($call:path => $instance:ty),*) => {
|
($runtime:ident, $($call:path => $instance:ty),*) => {
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ pub trait Config<I: 'static>: crate::Config<I> {
|
|||||||
parachains: &[ParaId],
|
parachains: &[ParaId],
|
||||||
parachain_head_size: u32,
|
parachain_head_size: u32,
|
||||||
proof_size: StorageProofSize,
|
proof_size: StorageProofSize,
|
||||||
) -> (RelayBlockHash, ParaHeadsProof);
|
) -> (RelayBlockNumber, RelayBlockHash, ParaHeadsProof);
|
||||||
}
|
}
|
||||||
|
|
||||||
benchmarks_instance_pallet! {
|
benchmarks_instance_pallet! {
|
||||||
@@ -57,12 +57,13 @@ benchmarks_instance_pallet! {
|
|||||||
|
|
||||||
let sender = account("sender", 0, 0);
|
let sender = account("sender", 0, 0);
|
||||||
let parachains = (1..=p).map(ParaId).collect::<Vec<_>>();
|
let parachains = (1..=p).map(ParaId).collect::<Vec<_>>();
|
||||||
let (relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof(
|
let (relay_block_number, relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof(
|
||||||
¶chains,
|
¶chains,
|
||||||
DEFAULT_PARACHAIN_HEAD_SIZE,
|
DEFAULT_PARACHAIN_HEAD_SIZE,
|
||||||
StorageProofSize::Minimal(0),
|
StorageProofSize::Minimal(0),
|
||||||
);
|
);
|
||||||
}: submit_parachain_heads(RawOrigin::Signed(sender), relay_block_hash, parachains.clone(), parachain_heads_proof)
|
let at_relay_block = (relay_block_number, relay_block_hash);
|
||||||
|
}: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains.clone(), parachain_heads_proof)
|
||||||
verify {
|
verify {
|
||||||
for parachain in parachains {
|
for parachain in parachains {
|
||||||
assert!(crate::Pallet::<T, I>::best_parachain_head(parachain).is_some());
|
assert!(crate::Pallet::<T, I>::best_parachain_head(parachain).is_some());
|
||||||
@@ -73,13 +74,13 @@ benchmarks_instance_pallet! {
|
|||||||
submit_parachain_heads_with_1kb_proof {
|
submit_parachain_heads_with_1kb_proof {
|
||||||
let sender = account("sender", 0, 0);
|
let sender = account("sender", 0, 0);
|
||||||
let parachains = vec![ParaId(1)];
|
let parachains = vec![ParaId(1)];
|
||||||
let (relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof(
|
let (relay_block_number, relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof(
|
||||||
¶chains,
|
¶chains,
|
||||||
DEFAULT_PARACHAIN_HEAD_SIZE,
|
DEFAULT_PARACHAIN_HEAD_SIZE,
|
||||||
StorageProofSize::HasExtraNodes(1024),
|
StorageProofSize::HasExtraNodes(1024),
|
||||||
);
|
);
|
||||||
|
let at_relay_block = (relay_block_number, relay_block_hash);
|
||||||
}: submit_parachain_heads(RawOrigin::Signed(sender), relay_block_hash, parachains.clone(), parachain_heads_proof)
|
}: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains.clone(), parachain_heads_proof)
|
||||||
verify {
|
verify {
|
||||||
for parachain in parachains {
|
for parachain in parachains {
|
||||||
assert!(crate::Pallet::<T, I>::best_parachain_head(parachain).is_some());
|
assert!(crate::Pallet::<T, I>::best_parachain_head(parachain).is_some());
|
||||||
@@ -90,13 +91,13 @@ benchmarks_instance_pallet! {
|
|||||||
submit_parachain_heads_with_16kb_proof {
|
submit_parachain_heads_with_16kb_proof {
|
||||||
let sender = account("sender", 0, 0);
|
let sender = account("sender", 0, 0);
|
||||||
let parachains = vec![ParaId(1)];
|
let parachains = vec![ParaId(1)];
|
||||||
let (relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof(
|
let (relay_block_number, relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof(
|
||||||
¶chains,
|
¶chains,
|
||||||
DEFAULT_PARACHAIN_HEAD_SIZE,
|
DEFAULT_PARACHAIN_HEAD_SIZE,
|
||||||
StorageProofSize::HasExtraNodes(16 * 1024),
|
StorageProofSize::HasExtraNodes(16 * 1024),
|
||||||
);
|
);
|
||||||
|
let at_relay_block = (relay_block_number, relay_block_hash);
|
||||||
}: submit_parachain_heads(RawOrigin::Signed(sender), relay_block_hash, parachains.clone(), parachain_heads_proof)
|
}: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains.clone(), parachain_heads_proof)
|
||||||
verify {
|
verify {
|
||||||
for parachain in parachains {
|
for parachain in parachains {
|
||||||
assert!(crate::Pallet::<T, I>::best_parachain_head(parachain).is_some());
|
assert!(crate::Pallet::<T, I>::best_parachain_head(parachain).is_some());
|
||||||
|
|||||||
@@ -0,0 +1,195 @@
|
|||||||
|
// Copyright 2021 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity Bridges Common.
|
||||||
|
|
||||||
|
// Parity Bridges Common is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity Bridges Common is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
/// Declares a runtime-specific `BridgeRejectObsoleteParachainHeader` signed extension.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
///
|
||||||
|
/// ```nocompile
|
||||||
|
/// pallet_bridge_grandpa::declare_bridge_reject_obsolete_parachain_header!{
|
||||||
|
/// Runtime,
|
||||||
|
/// Call::BridgeRialtoParachains => RialtoGrandpaInstance,
|
||||||
|
/// Call::BridgeWestendParachains => WestendGrandpaInstance,
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// The goal of this extension is to avoid "mining" transactions that provide
|
||||||
|
/// outdated bridged parachain heads. Without that extension, even honest relayers
|
||||||
|
/// may lose their funds if there are multiple relays running and submitting the
|
||||||
|
/// same information.
|
||||||
|
///
|
||||||
|
/// This extension only works with transactions that are updating single parachain
|
||||||
|
/// head. We can't use unbounded validation - it may take too long and either break
|
||||||
|
/// block production, or "eat" significant portion of block production time literally
|
||||||
|
/// for nothing. In addition, the single-parachain-head-per-transaction is how the
|
||||||
|
/// pallet will be used in our environment.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! declare_bridge_reject_obsolete_parachain_header {
|
||||||
|
($runtime:ident, $($call:path => $instance:ty),*) => {
|
||||||
|
/// Transaction-with-obsolete-bridged-parachain-header check that will reject transaction if
|
||||||
|
/// it submits obsolete bridged parachain header.
|
||||||
|
#[derive(Clone, codec::Decode, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)]
|
||||||
|
pub struct BridgeRejectObsoleteParachainHeader;
|
||||||
|
|
||||||
|
impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteParachainHeader {
|
||||||
|
const IDENTIFIER: &'static str = "BridgeRejectObsoleteParachainHeader";
|
||||||
|
type AccountId = <$runtime as frame_system::Config>::AccountId;
|
||||||
|
type Call = <$runtime as frame_system::Config>::Call;
|
||||||
|
type AdditionalSigned = ();
|
||||||
|
type Pre = ();
|
||||||
|
|
||||||
|
fn additional_signed(&self) -> sp_std::result::Result<
|
||||||
|
(),
|
||||||
|
sp_runtime::transaction_validity::TransactionValidityError,
|
||||||
|
> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(
|
||||||
|
&self,
|
||||||
|
_who: &Self::AccountId,
|
||||||
|
call: &Self::Call,
|
||||||
|
_info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
|
||||||
|
_len: usize,
|
||||||
|
) -> sp_runtime::transaction_validity::TransactionValidity {
|
||||||
|
match *call {
|
||||||
|
$(
|
||||||
|
$call($crate::Call::<$runtime, $instance>::submit_parachain_heads {
|
||||||
|
ref at_relay_block,
|
||||||
|
ref parachains,
|
||||||
|
..
|
||||||
|
}) if parachains.len() == 1 => {
|
||||||
|
let parachain = parachains.get(0).expect("verified by match condition; qed");
|
||||||
|
|
||||||
|
let bundled_relay_block_number = at_relay_block.0;
|
||||||
|
|
||||||
|
let best_parachain_head = $crate::BestParaHeads::<$runtime, $instance>::get(parachain);
|
||||||
|
match best_parachain_head {
|
||||||
|
Some(best_parachain_head) if best_parachain_head.at_relay_block_number
|
||||||
|
>= bundled_relay_block_number =>
|
||||||
|
sp_runtime::transaction_validity::InvalidTransaction::Stale.into(),
|
||||||
|
_ => Ok(sp_runtime::transaction_validity::ValidTransaction::default()),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)*
|
||||||
|
_ => Ok(sp_runtime::transaction_validity::ValidTransaction::default()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pre_dispatch(
|
||||||
|
self,
|
||||||
|
who: &Self::AccountId,
|
||||||
|
call: &Self::Call,
|
||||||
|
info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
|
||||||
|
len: usize,
|
||||||
|
) -> Result<Self::Pre, sp_runtime::transaction_validity::TransactionValidityError> {
|
||||||
|
self.validate(who, call, info, len).map(drop)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn post_dispatch(
|
||||||
|
_maybe_pre: Option<Self::Pre>,
|
||||||
|
_info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
|
||||||
|
_post_info: &sp_runtime::traits::PostDispatchInfoOf<Self::Call>,
|
||||||
|
_len: usize,
|
||||||
|
_result: &sp_runtime::DispatchResult,
|
||||||
|
) -> Result<(), sp_runtime::transaction_validity::TransactionValidityError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::{
|
||||||
|
mock::{run_test, Call, TestRuntime},
|
||||||
|
BestParaHead, BestParaHeads, RelayBlockNumber,
|
||||||
|
};
|
||||||
|
use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId};
|
||||||
|
use frame_support::weights::{DispatchClass, DispatchInfo, Pays};
|
||||||
|
use sp_runtime::traits::SignedExtension;
|
||||||
|
|
||||||
|
declare_bridge_reject_obsolete_parachain_header! {
|
||||||
|
TestRuntime,
|
||||||
|
Call::Parachains => ()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_submit_parachain_heads(num: RelayBlockNumber, parachains: Vec<ParaId>) -> bool {
|
||||||
|
BridgeRejectObsoleteParachainHeader
|
||||||
|
.validate(
|
||||||
|
&42,
|
||||||
|
&Call::Parachains(crate::Call::<TestRuntime, ()>::submit_parachain_heads {
|
||||||
|
at_relay_block: (num, Default::default()),
|
||||||
|
parachains,
|
||||||
|
parachain_heads_proof: ParaHeadsProof(Vec::new()),
|
||||||
|
}),
|
||||||
|
&DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: Pays::Yes },
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sync_to_relay_header_10() {
|
||||||
|
BestParaHeads::<TestRuntime, ()>::insert(
|
||||||
|
ParaId(1),
|
||||||
|
BestParaHead {
|
||||||
|
at_relay_block_number: 10,
|
||||||
|
head_hash: Default::default(),
|
||||||
|
next_imported_hash_position: 0,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extension_rejects_obsolete_header() {
|
||||||
|
run_test(|| {
|
||||||
|
// when current best finalized is #10 and we're trying to import header#5 => tx is
|
||||||
|
// rejected
|
||||||
|
sync_to_relay_header_10();
|
||||||
|
assert!(!validate_submit_parachain_heads(5, vec![ParaId(1)]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extension_rejects_same_header() {
|
||||||
|
run_test(|| {
|
||||||
|
// when current best finalized is #10 and we're trying to import header#10 => tx is
|
||||||
|
// rejected
|
||||||
|
sync_to_relay_header_10();
|
||||||
|
assert!(!validate_submit_parachain_heads(10, vec![ParaId(1)]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extension_accepts_new_header() {
|
||||||
|
run_test(|| {
|
||||||
|
// when current best finalized is #10 and we're trying to import header#15 => tx is
|
||||||
|
// accepted
|
||||||
|
sync_to_relay_header_10();
|
||||||
|
assert!(validate_submit_parachain_heads(15, vec![ParaId(1)]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extension_accepts_if_more_than_one_parachain_is_submitted() {
|
||||||
|
run_test(|| {
|
||||||
|
// when current best finalized is #10 and we're trying to import header#5, but another
|
||||||
|
// parachain head is also supplied => tx is accepted
|
||||||
|
sync_to_relay_header_10();
|
||||||
|
assert!(validate_submit_parachain_heads(5, vec![ParaId(1), ParaId(2)]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,6 +44,7 @@ pub mod weights_ext;
|
|||||||
#[cfg(feature = "runtime-benchmarks")]
|
#[cfg(feature = "runtime-benchmarks")]
|
||||||
pub mod benchmarking;
|
pub mod benchmarking;
|
||||||
|
|
||||||
|
mod extension;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod mock;
|
mod mock;
|
||||||
|
|
||||||
@@ -84,8 +85,10 @@ pub mod pallet {
|
|||||||
|
|
||||||
#[pallet::error]
|
#[pallet::error]
|
||||||
pub enum Error<T, I = ()> {
|
pub enum Error<T, I = ()> {
|
||||||
/// Relay chain block is unknown to us.
|
/// Relay chain block hash is unknown to us.
|
||||||
UnknownRelayChainBlock,
|
UnknownRelayChainBlock,
|
||||||
|
/// The number of stored relay block is different from what the relayer has provided.
|
||||||
|
InvalidRelayChainBlockNumber,
|
||||||
/// Invalid storage proof has been passed.
|
/// Invalid storage proof has been passed.
|
||||||
InvalidStorageProof,
|
InvalidStorageProof,
|
||||||
/// Given parachain head is unknown.
|
/// Given parachain head is unknown.
|
||||||
@@ -175,17 +178,21 @@ pub mod pallet {
|
|||||||
))]
|
))]
|
||||||
pub fn submit_parachain_heads(
|
pub fn submit_parachain_heads(
|
||||||
_origin: OriginFor<T>,
|
_origin: OriginFor<T>,
|
||||||
relay_block_hash: RelayBlockHash,
|
at_relay_block: (RelayBlockNumber, RelayBlockHash),
|
||||||
parachains: Vec<ParaId>,
|
parachains: Vec<ParaId>,
|
||||||
parachain_heads_proof: ParaHeadsProof,
|
parachain_heads_proof: ParaHeadsProof,
|
||||||
) -> DispatchResultWithPostInfo {
|
) -> DispatchResultWithPostInfo {
|
||||||
// we'll need relay chain header to verify that parachains heads are always increasing.
|
// we'll need relay chain header to verify that parachains heads are always increasing.
|
||||||
|
let (relay_block_number, relay_block_hash) = at_relay_block;
|
||||||
let relay_block = pallet_bridge_grandpa::ImportedHeaders::<
|
let relay_block = pallet_bridge_grandpa::ImportedHeaders::<
|
||||||
T,
|
T,
|
||||||
T::BridgesGrandpaPalletInstance,
|
T::BridgesGrandpaPalletInstance,
|
||||||
>::get(relay_block_hash)
|
>::get(relay_block_hash)
|
||||||
.ok_or(Error::<T, I>::UnknownRelayChainBlock)?;
|
.ok_or(Error::<T, I>::UnknownRelayChainBlock)?;
|
||||||
let relay_block_number = *relay_block.number();
|
ensure!(
|
||||||
|
*relay_block.number() == relay_block_number,
|
||||||
|
Error::<T, I>::InvalidRelayChainBlockNumber,
|
||||||
|
);
|
||||||
|
|
||||||
// now parse storage proof and read parachain heads
|
// now parse storage proof and read parachain heads
|
||||||
let mut actual_weight = WeightInfoOf::<T, I>::submit_parachain_heads_weight(
|
let mut actual_weight = WeightInfoOf::<T, I>::submit_parachain_heads_weight(
|
||||||
@@ -484,7 +491,7 @@ mod tests {
|
|||||||
) -> DispatchResultWithPostInfo {
|
) -> DispatchResultWithPostInfo {
|
||||||
Pallet::<TestRuntime>::submit_parachain_heads(
|
Pallet::<TestRuntime>::submit_parachain_heads(
|
||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
test_relay_header(relay_chain_block, relay_state_root).hash(),
|
(relay_chain_block, test_relay_header(relay_chain_block, relay_state_root).hash()),
|
||||||
vec![ParaId(1)],
|
vec![ParaId(1)],
|
||||||
proof,
|
proof,
|
||||||
)
|
)
|
||||||
@@ -510,7 +517,7 @@ mod tests {
|
|||||||
// we're trying to update heads of parachains 1, 2 and 3
|
// we're trying to update heads of parachains 1, 2 and 3
|
||||||
assert_ok!(Pallet::<TestRuntime>::submit_parachain_heads(
|
assert_ok!(Pallet::<TestRuntime>::submit_parachain_heads(
|
||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
test_relay_header(0, state_root).hash(),
|
(0, test_relay_header(0, state_root).hash()),
|
||||||
vec![ParaId(1), ParaId(2), ParaId(3)],
|
vec![ParaId(1), ParaId(2), ParaId(3)],
|
||||||
proof,
|
proof,
|
||||||
),);
|
),);
|
||||||
@@ -602,7 +609,7 @@ mod tests {
|
|||||||
initialize(state_root);
|
initialize(state_root);
|
||||||
assert_ok!(Pallet::<TestRuntime>::submit_parachain_heads(
|
assert_ok!(Pallet::<TestRuntime>::submit_parachain_heads(
|
||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
test_relay_header(0, state_root).hash(),
|
(0, test_relay_header(0, state_root).hash()),
|
||||||
vec![ParaId(1), ParaId(UNTRACKED_PARACHAIN_ID), ParaId(2)],
|
vec![ParaId(1), ParaId(UNTRACKED_PARACHAIN_ID), ParaId(2)],
|
||||||
proof,
|
proof,
|
||||||
));
|
));
|
||||||
@@ -776,7 +783,7 @@ mod tests {
|
|||||||
proceed(20, state_root_10_at_20);
|
proceed(20, state_root_10_at_20);
|
||||||
assert_ok!(Pallet::<TestRuntime>::submit_parachain_heads(
|
assert_ok!(Pallet::<TestRuntime>::submit_parachain_heads(
|
||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
test_relay_header(20, state_root_10_at_20).hash(),
|
(20, test_relay_header(20, state_root_10_at_20).hash()),
|
||||||
vec![ParaId(1)],
|
vec![ParaId(1)],
|
||||||
proof_10_at_20,
|
proof_10_at_20,
|
||||||
),);
|
),);
|
||||||
@@ -792,7 +799,7 @@ mod tests {
|
|||||||
proceed(30, state_root_10_at_30);
|
proceed(30, state_root_10_at_30);
|
||||||
assert_ok!(Pallet::<TestRuntime>::submit_parachain_heads(
|
assert_ok!(Pallet::<TestRuntime>::submit_parachain_heads(
|
||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
test_relay_header(30, state_root_10_at_30).hash(),
|
(30, test_relay_header(30, state_root_10_at_30).hash()),
|
||||||
vec![ParaId(1)],
|
vec![ParaId(1)],
|
||||||
proof_10_at_30,
|
proof_10_at_30,
|
||||||
),);
|
),);
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ construct_runtime! {
|
|||||||
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
|
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
|
||||||
Grandpa1: pallet_bridge_grandpa::<Instance1>::{Pallet},
|
Grandpa1: pallet_bridge_grandpa::<Instance1>::{Pallet},
|
||||||
Grandpa2: pallet_bridge_grandpa::<Instance2>::{Pallet},
|
Grandpa2: pallet_bridge_grandpa::<Instance2>::{Pallet},
|
||||||
Parachains: pallet_bridge_parachains::{Pallet},
|
Parachains: pallet_bridge_parachains::{Call, Pallet},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ impl TransactionSignScheme for Millau {
|
|||||||
frame_system::CheckWeight::<millau_runtime::Runtime>::new(),
|
frame_system::CheckWeight::<millau_runtime::Runtime>::new(),
|
||||||
pallet_transaction_payment::ChargeTransactionPayment::<millau_runtime::Runtime>::from(param.unsigned.tip),
|
pallet_transaction_payment::ChargeTransactionPayment::<millau_runtime::Runtime>::from(param.unsigned.tip),
|
||||||
millau_runtime::BridgeRejectObsoleteGrandpaHeader,
|
millau_runtime::BridgeRejectObsoleteGrandpaHeader,
|
||||||
|
millau_runtime::BridgeRejectObsoleteParachainHeader,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(),
|
(),
|
||||||
@@ -127,6 +128,7 @@ impl TransactionSignScheme for Millau {
|
|||||||
(),
|
(),
|
||||||
(),
|
(),
|
||||||
(),
|
(),
|
||||||
|
(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload));
|
let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload));
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ use pallet_bridge_parachains::{
|
|||||||
RelayBlockHasher, RelayBlockNumber,
|
RelayBlockHasher, RelayBlockNumber,
|
||||||
};
|
};
|
||||||
use parachains_relay::ParachainsPipeline;
|
use parachains_relay::ParachainsPipeline;
|
||||||
use relay_substrate_client::{CallOf, Chain, HashOf, RelayChain, TransactionSignScheme};
|
use relay_substrate_client::{CallOf, Chain, HeaderIdOf, RelayChain, TransactionSignScheme};
|
||||||
use std::{fmt::Debug, marker::PhantomData};
|
use std::{fmt::Debug, marker::PhantomData};
|
||||||
|
|
||||||
pub mod source;
|
pub mod source;
|
||||||
@@ -70,7 +70,7 @@ pub trait SubmitParachainHeadsCallBuilder<P: SubstrateParachainsPipeline>:
|
|||||||
/// Given parachains and their heads proof, build call of `submit_parachain_heads`
|
/// Given parachains and their heads proof, build call of `submit_parachain_heads`
|
||||||
/// function of bridge parachains module at the target chain.
|
/// function of bridge parachains module at the target chain.
|
||||||
fn build_submit_parachain_heads_call(
|
fn build_submit_parachain_heads_call(
|
||||||
relay_block_hash: HashOf<P::SourceRelayChain>,
|
at_relay_block: HeaderIdOf<P::SourceRelayChain>,
|
||||||
parachains: Vec<ParaId>,
|
parachains: Vec<ParaId>,
|
||||||
parachain_heads_proof: ParaHeadsProof,
|
parachain_heads_proof: ParaHeadsProof,
|
||||||
) -> CallOf<P::TargetChain>;
|
) -> CallOf<P::TargetChain>;
|
||||||
@@ -85,7 +85,7 @@ pub struct DirectSubmitParachainHeadsCallBuilder<P, R, I> {
|
|||||||
impl<P, R, I> SubmitParachainHeadsCallBuilder<P> for DirectSubmitParachainHeadsCallBuilder<P, R, I>
|
impl<P, R, I> SubmitParachainHeadsCallBuilder<P> for DirectSubmitParachainHeadsCallBuilder<P, R, I>
|
||||||
where
|
where
|
||||||
P: SubstrateParachainsPipeline,
|
P: SubstrateParachainsPipeline,
|
||||||
P::SourceRelayChain: Chain<Hash = RelayBlockHash>,
|
P::SourceRelayChain: Chain<Hash = RelayBlockHash, BlockNumber = RelayBlockNumber>,
|
||||||
R: BridgeParachainsConfig<I> + Send + Sync,
|
R: BridgeParachainsConfig<I> + Send + Sync,
|
||||||
I: 'static + Send + Sync,
|
I: 'static + Send + Sync,
|
||||||
R::BridgedChain: bp_runtime::Chain<
|
R::BridgedChain: bp_runtime::Chain<
|
||||||
@@ -96,12 +96,12 @@ where
|
|||||||
CallOf<P::TargetChain>: From<BridgeParachainsCall<R, I>>,
|
CallOf<P::TargetChain>: From<BridgeParachainsCall<R, I>>,
|
||||||
{
|
{
|
||||||
fn build_submit_parachain_heads_call(
|
fn build_submit_parachain_heads_call(
|
||||||
relay_block_hash: HashOf<P::SourceRelayChain>,
|
at_relay_block: HeaderIdOf<P::SourceRelayChain>,
|
||||||
parachains: Vec<ParaId>,
|
parachains: Vec<ParaId>,
|
||||||
parachain_heads_proof: ParaHeadsProof,
|
parachain_heads_proof: ParaHeadsProof,
|
||||||
) -> CallOf<P::TargetChain> {
|
) -> CallOf<P::TargetChain> {
|
||||||
BridgeParachainsCall::<R, I>::submit_parachain_heads {
|
BridgeParachainsCall::<R, I>::submit_parachain_heads {
|
||||||
relay_block_hash,
|
at_relay_block: (at_relay_block.0, at_relay_block.1),
|
||||||
parachains,
|
parachains,
|
||||||
parachain_heads_proof,
|
parachain_heads_proof,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ where
|
|||||||
let transaction_params = self.transaction_params.clone();
|
let transaction_params = self.transaction_params.clone();
|
||||||
let (spec_version, transaction_version) = self.client.simple_runtime_version().await?;
|
let (spec_version, transaction_version) = self.client.simple_runtime_version().await?;
|
||||||
let call = P::SubmitParachainHeadsCallBuilder::build_submit_parachain_heads_call(
|
let call = P::SubmitParachainHeadsCallBuilder::build_submit_parachain_heads_call(
|
||||||
at_relay_block.1,
|
at_relay_block,
|
||||||
updated_parachains,
|
updated_parachains,
|
||||||
proof,
|
proof,
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user