mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-25 21:07:56 +00:00
@@ -16,6 +16,7 @@
|
||||
|
||||
//! Common types/functions that may be used by runtimes of all bridged chains.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use crate::messages_call_ext::MessagesCallSubType;
|
||||
|
||||
@@ -24,7 +24,7 @@ pub use bp_runtime::{RangeInclusiveExt, UnderlyingChainOf, UnderlyingChainProvid
|
||||
|
||||
use bp_header_chain::HeaderChain;
|
||||
use bp_messages::{
|
||||
source_chain::{LaneMessageVerifier, TargetHeaderChain},
|
||||
source_chain::TargetHeaderChain,
|
||||
target_chain::{ProvedLaneMessages, ProvedMessages, SourceHeaderChain},
|
||||
InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData,
|
||||
VerificationError,
|
||||
@@ -120,42 +120,6 @@ pub mod source {
|
||||
pub type ParsedMessagesDeliveryProofFromBridgedChain<B> =
|
||||
(LaneId, InboundLaneData<AccountIdOf<ThisChain<B>>>);
|
||||
|
||||
/// Message verifier that is doing all basic checks.
|
||||
///
|
||||
/// This verifier assumes following:
|
||||
///
|
||||
/// - all message lanes are equivalent, so all checks are the same;
|
||||
///
|
||||
/// Following checks are made:
|
||||
///
|
||||
/// - message is rejected if its lane is currently blocked;
|
||||
/// - message is rejected if there are too many pending (undelivered) messages at the outbound
|
||||
/// lane;
|
||||
/// - check that the sender has rights to dispatch the call on target chain using provided
|
||||
/// dispatch origin;
|
||||
/// - check that the sender has paid enough funds for both message delivery and dispatch.
|
||||
#[derive(RuntimeDebug)]
|
||||
pub struct FromThisChainMessageVerifier<B>(PhantomData<B>);
|
||||
|
||||
impl<B> LaneMessageVerifier<FromThisChainMessagePayload> for FromThisChainMessageVerifier<B>
|
||||
where
|
||||
B: MessageBridge,
|
||||
{
|
||||
fn verify_message(
|
||||
_lane: &LaneId,
|
||||
_lane_outbound_data: &OutboundLaneData,
|
||||
_payload: &FromThisChainMessagePayload,
|
||||
) -> Result<(), VerificationError> {
|
||||
// IMPORTANT: any error that is returned here is fatal for the bridge, because
|
||||
// this code is executed at the bridge hub and message sender actually lives
|
||||
// at some sibling parachain. So we are failing **after** the message has been
|
||||
// sent and we can't report it back to sender (unless error report mechanism is
|
||||
// embedded into message and its dispatcher).
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Return maximal message size of This -> Bridged chain message.
|
||||
pub fn maximal_message_size<B: MessageBridge>() -> u32 {
|
||||
super::target::maximal_incoming_message_size(
|
||||
@@ -185,8 +149,7 @@ pub mod source {
|
||||
/// Do basic Bridged-chain specific verification of This -> Bridged chain message.
|
||||
///
|
||||
/// Ok result from this function means that the delivery transaction with this message
|
||||
/// may be 'mined' by the target chain. But the lane may have its own checks (e.g. fee
|
||||
/// check) that would reject message (see `FromThisChainMessageVerifier`).
|
||||
/// may be 'mined' by the target chain.
|
||||
pub fn verify_chain_message<B: MessageBridge>(
|
||||
payload: &FromThisChainMessagePayload,
|
||||
) -> Result<(), VerificationError> {
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
// 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/>.
|
||||
|
||||
//! Signed extension for the `pallet-bridge-messages` that is able to reject obsolete
|
||||
//! (and some other invalid) transactions.
|
||||
|
||||
use crate::messages::{
|
||||
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
|
||||
};
|
||||
@@ -116,7 +119,9 @@ impl ReceiveMessagesDeliveryProofInfo {
|
||||
/// which tries to update a single lane.
|
||||
#[derive(PartialEq, RuntimeDebug)]
|
||||
pub enum CallInfo {
|
||||
/// Messages delivery call info.
|
||||
ReceiveMessagesProof(ReceiveMessagesProofInfo),
|
||||
/// Messages delivery confirmation call info.
|
||||
ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo),
|
||||
}
|
||||
|
||||
@@ -132,7 +137,7 @@ impl CallInfo {
|
||||
|
||||
/// Helper struct that provides methods for working with a call supported by `CallInfo`.
|
||||
pub struct CallHelper<T: Config<I>, I: 'static> {
|
||||
pub _phantom_data: sp_std::marker::PhantomData<(T, I)>,
|
||||
_phantom_data: sp_std::marker::PhantomData<(T, I)>,
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> CallHelper<T, I> {
|
||||
|
||||
@@ -40,11 +40,14 @@ use sp_std::{fmt::Debug, marker::PhantomData};
|
||||
use xcm::prelude::*;
|
||||
use xcm_builder::{DispatchBlob, DispatchBlobError};
|
||||
|
||||
/// Message dispatch result type for single message
|
||||
/// Message dispatch result type for single message.
|
||||
#[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)]
|
||||
pub enum XcmBlobMessageDispatchResult {
|
||||
/// We've been unable to decode message payload.
|
||||
InvalidPayload,
|
||||
/// Message has been dispatched.
|
||||
Dispatched,
|
||||
/// Message has **NOT** been dispatched because of given error.
|
||||
NotDispatched(#[codec(skip)] Option<DispatchBlobError>),
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
use crate::messages::{
|
||||
source::{
|
||||
FromThisChainMaximalOutboundPayloadSize, FromThisChainMessagePayload,
|
||||
FromThisChainMessageVerifier, TargetHeaderChainAdapter,
|
||||
TargetHeaderChainAdapter,
|
||||
},
|
||||
target::{FromBridgedChainMessagePayload, SourceHeaderChainAdapter},
|
||||
BridgedChainWithMessages, HashOf, MessageBridge, ThisChainWithMessages,
|
||||
@@ -213,7 +213,6 @@ impl pallet_bridge_messages::Config for TestRuntime {
|
||||
type DeliveryPayments = ();
|
||||
|
||||
type TargetHeaderChain = TargetHeaderChainAdapter<OnThisChainBridge>;
|
||||
type LaneMessageVerifier = FromThisChainMessageVerifier<OnThisChainBridge>;
|
||||
type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter<
|
||||
TestRuntime,
|
||||
(),
|
||||
@@ -315,6 +314,8 @@ impl From<BridgedChainOrigin>
|
||||
pub struct ThisUnderlyingChain;
|
||||
|
||||
impl Chain for ThisUnderlyingChain {
|
||||
const ID: ChainId = *b"tuch";
|
||||
|
||||
type BlockNumber = ThisChainBlockNumber;
|
||||
type Hash = ThisChainHash;
|
||||
type Hasher = ThisChainHasher;
|
||||
@@ -355,6 +356,8 @@ pub struct BridgedUnderlyingParachain;
|
||||
pub struct BridgedChainCall;
|
||||
|
||||
impl Chain for BridgedUnderlyingChain {
|
||||
const ID: ChainId = *b"buch";
|
||||
|
||||
type BlockNumber = BridgedChainBlockNumber;
|
||||
type Hash = BridgedChainHash;
|
||||
type Hasher = BridgedChainHasher;
|
||||
@@ -381,6 +384,8 @@ impl ChainWithGrandpa for BridgedUnderlyingChain {
|
||||
}
|
||||
|
||||
impl Chain for BridgedUnderlyingParachain {
|
||||
const ID: ChainId = *b"bupc";
|
||||
|
||||
type BlockNumber = BridgedChainBlockNumber;
|
||||
type Hash = BridgedChainHash;
|
||||
type Hasher = BridgedChainHasher;
|
||||
|
||||
@@ -84,5 +84,5 @@ where
|
||||
let (relay_block_number, relay_block_hash) =
|
||||
insert_header_to_grandpa_pallet::<R, R::BridgesGrandpaPalletInstance>(state_root);
|
||||
|
||||
(relay_block_number, relay_block_hash, ParaHeadsProof(proof), parachain_heads)
|
||||
(relay_block_number, relay_block_hash, ParaHeadsProof { storage_proof: proof }, parachain_heads)
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ where
|
||||
|
||||
/// Refund calculator.
|
||||
pub trait RefundCalculator {
|
||||
// The underlying integer type in which the refund is calculated.
|
||||
/// The underlying integer type in which the refund is calculated.
|
||||
type Balance;
|
||||
|
||||
/// Compute refund for given transaction.
|
||||
@@ -986,7 +986,7 @@ mod tests {
|
||||
ParaId(TestParachain::get()),
|
||||
[parachain_head_at_relay_header_number as u8; 32].into(),
|
||||
)],
|
||||
parachain_heads_proof: ParaHeadsProof(vec![]),
|
||||
parachain_heads_proof: ParaHeadsProof { storage_proof: vec![] },
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1732,7 +1732,7 @@ mod tests {
|
||||
(ParaId(TestParachain::get()), [1u8; 32].into()),
|
||||
(ParaId(TestParachain::get() + 1), [1u8; 32].into()),
|
||||
],
|
||||
parachain_heads_proof: ParaHeadsProof(vec![]),
|
||||
parachain_heads_proof: ParaHeadsProof { storage_proof: vec![] },
|
||||
}),
|
||||
message_delivery_call(200),
|
||||
],
|
||||
|
||||
@@ -32,9 +32,8 @@
|
||||
//! Shall the fork occur on the bridged chain governance intervention will be required to
|
||||
//! re-initialize the bridge and track the right fork.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
// Runtime-generated enums
|
||||
#![allow(clippy::large_enum_variant)]
|
||||
|
||||
pub use storage_types::StoredAuthoritySet;
|
||||
|
||||
@@ -408,7 +407,9 @@ pub mod pallet {
|
||||
pub enum Event<T: Config<I>, I: 'static = ()> {
|
||||
/// Best finalized chain header has been updated to the header with given number and hash.
|
||||
UpdatedBestFinalizedHeader {
|
||||
/// Number of the new best finalized header.
|
||||
number: BridgedBlockNumber<T, I>,
|
||||
/// Hash of the new best finalized header.
|
||||
hash: BridgedBlockHash<T, I>,
|
||||
/// The Grandpa info associated to the new best finalized header.
|
||||
grandpa_info: StoredHeaderGrandpaInfo<BridgedHeader<T, I>>,
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#![allow(clippy::from_over_into)]
|
||||
|
||||
use bp_header_chain::ChainWithGrandpa;
|
||||
use bp_runtime::Chain;
|
||||
use bp_runtime::{Chain, ChainId};
|
||||
use frame_support::{
|
||||
construct_runtime, derive_impl, parameter_types, traits::Hooks, weights::Weight,
|
||||
};
|
||||
@@ -64,7 +64,9 @@ impl grandpa::Config for TestRuntime {
|
||||
pub struct TestBridgedChain;
|
||||
|
||||
impl Chain for TestBridgedChain {
|
||||
type BlockNumber = TestNumber;
|
||||
const ID: ChainId = *b"tbch";
|
||||
|
||||
type BlockNumber = frame_system::pallet_prelude::BlockNumberFor<TestRuntime>;
|
||||
type Hash = <TestRuntime as frame_system::Config>::Hash;
|
||||
type Hasher = <TestRuntime as frame_system::Config>::Hashing;
|
||||
type Header = TestHeader;
|
||||
|
||||
@@ -116,26 +116,12 @@ maximal possible transaction size of the chain and so on. And when the relayer s
|
||||
implementation must be able to parse and verify the proof of messages delivery. Normally, you would reuse the same
|
||||
(configurable) type on all chains that are sending messages to the same bridged chain.
|
||||
|
||||
The `pallet_bridge_messages::Config::LaneMessageVerifier` defines a single callback to verify outbound messages. The
|
||||
simplest callback may just accept all messages. But in this case you'll need to answer many questions first. Who will
|
||||
pay for the delivery and confirmation transaction? Are we sure that someone will ever deliver this message to the
|
||||
bridged chain? Are we sure that we don't bloat our runtime storage by accepting this message? What if the message is
|
||||
improperly encoded or has some fields set to invalid values? Answering all those (and similar) questions would lead to
|
||||
correct implementation.
|
||||
|
||||
There's another thing to consider when implementing type for use in
|
||||
`pallet_bridge_messages::Config::LaneMessageVerifier`. It is whether we treat all message lanes identically, or they'll
|
||||
have different sets of verification rules? For example, you may reserve lane#1 for messages coming from some
|
||||
'wrapped-token' pallet - then you may verify in your implementation that the origin is associated with this pallet.
|
||||
Lane#2 may be reserved for 'system' messages and you may charge zero fee for such messages. You may have some rate
|
||||
limiting for messages sent over the lane#3. Or you may just verify the same rules set for all outbound messages - it is
|
||||
all up to the `pallet_bridge_messages::Config::LaneMessageVerifier` implementation.
|
||||
|
||||
The last type is the `pallet_bridge_messages::Config::DeliveryConfirmationPayments`. When confirmation transaction is
|
||||
received, we call the `pay_reward()` method, passing the range of delivered messages. You may use the
|
||||
[`pallet-bridge-relayers`](../relayers/) pallet and its
|
||||
[`DeliveryConfirmationPaymentsAdapter`](../relayers/src/payment_adapter.rs) adapter as a possible implementation. It
|
||||
allows you to pay fixed reward for relaying the message and some of its portion for confirming delivery.
|
||||
The last type is the `pallet_bridge_messages::Config::DeliveryConfirmationPayments`. When confirmation
|
||||
transaction is received, we call the `pay_reward()` method, passing the range of delivered messages.
|
||||
You may use the [`pallet-bridge-relayers`](../relayers/) pallet and its
|
||||
[`DeliveryConfirmationPaymentsAdapter`](../relayers/src/payment_adapter.rs) adapter as a possible
|
||||
implementation. It allows you to pay fixed reward for relaying the message and some of its portion
|
||||
for confirming delivery.
|
||||
|
||||
### I have a Messages Module in my Runtime, but I Want to Reject all Outbound Messages. What shall I do?
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ use codec::Decode;
|
||||
use frame_benchmarking::{account, benchmarks_instance_pallet};
|
||||
use frame_support::weights::Weight;
|
||||
use frame_system::RawOrigin;
|
||||
use sp_runtime::traits::TrailingZeroInput;
|
||||
use sp_runtime::{traits::TrailingZeroInput, BoundedVec};
|
||||
use sp_std::{ops::RangeInclusive, prelude::*};
|
||||
|
||||
const SEED: u32 = 0;
|
||||
@@ -443,7 +443,7 @@ benchmarks_instance_pallet! {
|
||||
|
||||
fn send_regular_message<T: Config<I>, I: 'static>() {
|
||||
let mut outbound_lane = outbound_lane::<T, I>(T::bench_lane_id());
|
||||
outbound_lane.send_message(vec![]).expect("We craft valid messages");
|
||||
outbound_lane.send_message(BoundedVec::try_from(vec![]).expect("We craft valid messages"));
|
||||
}
|
||||
|
||||
fn receive_messages<T: Config<I>, I: 'static>(nonce: MessageNonce) {
|
||||
|
||||
+110
-121
@@ -33,9 +33,8 @@
|
||||
//! If this test fails with your weights, then either weights are computed incorrectly,
|
||||
//! or some benchmarks assumptions are broken for your runtime.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
// Generated by `decl_event!`
|
||||
#![allow(clippy::unused_unit)]
|
||||
|
||||
pub use inbound_lane::StoredInboundLaneData;
|
||||
pub use outbound_lane::StoredMessagePayload;
|
||||
@@ -53,8 +52,7 @@ use crate::{
|
||||
|
||||
use bp_messages::{
|
||||
source_chain::{
|
||||
DeliveryConfirmationPayments, LaneMessageVerifier, OnMessagesDelivered,
|
||||
SendMessageArtifacts, TargetHeaderChain,
|
||||
DeliveryConfirmationPayments, OnMessagesDelivered, SendMessageArtifacts, TargetHeaderChain,
|
||||
},
|
||||
target_chain::{
|
||||
DeliveryPayments, DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages,
|
||||
@@ -155,8 +153,6 @@ pub mod pallet {
|
||||
|
||||
/// Target header chain.
|
||||
type TargetHeaderChain: TargetHeaderChain<Self::OutboundPayload, Self::AccountId>;
|
||||
/// Message payload verifier.
|
||||
type LaneMessageVerifier: LaneMessageVerifier<Self::OutboundPayload>;
|
||||
/// Delivery confirmation payments.
|
||||
type DeliveryConfirmationPayments: DeliveryConfirmationPayments<Self::AccountId>;
|
||||
/// Delivery confirmation callback.
|
||||
@@ -517,16 +513,28 @@ pub mod pallet {
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event<T: Config<I>, I: 'static = ()> {
|
||||
/// Message has been accepted and is waiting to be delivered.
|
||||
MessageAccepted { lane_id: LaneId, nonce: MessageNonce },
|
||||
MessageAccepted {
|
||||
/// Lane, which has accepted the message.
|
||||
lane_id: LaneId,
|
||||
/// Nonce of accepted message.
|
||||
nonce: MessageNonce,
|
||||
},
|
||||
/// Messages have been received from the bridged chain.
|
||||
MessagesReceived(
|
||||
/// Result of received messages dispatch.
|
||||
Vec<ReceivedMessages<<T::MessageDispatch as MessageDispatch>::DispatchLevelResult>>,
|
||||
),
|
||||
/// Messages in the inclusive range have been delivered to the bridged chain.
|
||||
MessagesDelivered { lane_id: LaneId, messages: DeliveredMessages },
|
||||
MessagesDelivered {
|
||||
/// Lane for which the delivery has been confirmed.
|
||||
lane_id: LaneId,
|
||||
/// Delivered messages.
|
||||
messages: DeliveredMessages,
|
||||
},
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub enum Error<T, I = ()> {
|
||||
/// Pallet is not in Normal operating mode.
|
||||
NotOperatingNormally,
|
||||
@@ -536,8 +544,6 @@ pub mod pallet {
|
||||
MessageDispatchInactive,
|
||||
/// Message has been treated as invalid by chain verifier.
|
||||
MessageRejectedByChainVerifier(VerificationError),
|
||||
/// Message has been treated as invalid by lane verifier.
|
||||
MessageRejectedByLaneVerifier(VerificationError),
|
||||
/// Message has been treated as invalid by the pallet logic.
|
||||
MessageRejectedByPallet(VerificationError),
|
||||
/// Submitter has failed to pay fee for delivering and dispatching messages.
|
||||
@@ -683,80 +689,72 @@ pub mod pallet {
|
||||
}
|
||||
}
|
||||
|
||||
/// Structure, containing a validated message payload and all the info required
|
||||
/// to send it on the bridge.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct SendMessageArgs<T: Config<I>, I: 'static> {
|
||||
lane_id: LaneId,
|
||||
payload: StoredMessagePayload<T, I>,
|
||||
}
|
||||
|
||||
impl<T, I> bp_messages::source_chain::MessagesBridge<T::OutboundPayload> for Pallet<T, I>
|
||||
where
|
||||
T: Config<I>,
|
||||
I: 'static,
|
||||
{
|
||||
type Error = sp_runtime::DispatchErrorWithPostInfo<PostDispatchInfo>;
|
||||
type Error = Error<T, I>;
|
||||
type SendMessageArgs = SendMessageArgs<T, I>;
|
||||
|
||||
fn send_message(
|
||||
fn validate_message(
|
||||
lane: LaneId,
|
||||
message: T::OutboundPayload,
|
||||
) -> Result<SendMessageArtifacts, Self::Error> {
|
||||
crate::send_message::<T, I>(lane, message)
|
||||
message: &T::OutboundPayload,
|
||||
) -> Result<SendMessageArgs<T, I>, Self::Error> {
|
||||
ensure_normal_operating_mode::<T, I>()?;
|
||||
|
||||
// let's check if outbound lane is active
|
||||
ensure!(T::ActiveOutboundLanes::get().contains(&lane), Error::<T, I>::InactiveOutboundLane);
|
||||
|
||||
// let's first check if message can be delivered to target chain
|
||||
T::TargetHeaderChain::verify_message(message).map_err(|err| {
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"Message to lane {:?} is rejected by target chain: {:?}",
|
||||
lane,
|
||||
err,
|
||||
);
|
||||
|
||||
Error::<T, I>::MessageRejectedByChainVerifier(err)
|
||||
})?;
|
||||
|
||||
Ok(SendMessageArgs {
|
||||
lane_id: lane,
|
||||
payload: StoredMessagePayload::<T, I>::try_from(message.encode()).map_err(|_| {
|
||||
Error::<T, I>::MessageRejectedByPallet(VerificationError::MessageTooLarge)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Function that actually sends message.
|
||||
fn send_message<T: Config<I>, I: 'static>(
|
||||
lane_id: LaneId,
|
||||
payload: T::OutboundPayload,
|
||||
) -> sp_std::result::Result<
|
||||
SendMessageArtifacts,
|
||||
sp_runtime::DispatchErrorWithPostInfo<PostDispatchInfo>,
|
||||
> {
|
||||
ensure_normal_operating_mode::<T, I>()?;
|
||||
fn send_message(args: SendMessageArgs<T, I>) -> SendMessageArtifacts {
|
||||
// save message in outbound storage and emit event
|
||||
let mut lane = outbound_lane::<T, I>(args.lane_id);
|
||||
let message_len = args.payload.len();
|
||||
let nonce = lane.send_message(args.payload);
|
||||
|
||||
// let's check if outbound lane is active
|
||||
ensure!(T::ActiveOutboundLanes::get().contains(&lane_id), Error::<T, I>::InactiveOutboundLane,);
|
||||
// return number of messages in the queue to let sender know about its state
|
||||
let enqueued_messages = lane.data().queued_messages().saturating_len();
|
||||
|
||||
// let's first check if message can be delivered to target chain
|
||||
T::TargetHeaderChain::verify_message(&payload).map_err(|err| {
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"Message to lane {:?} is rejected by target chain: {:?}",
|
||||
lane_id,
|
||||
err,
|
||||
"Accepted message {} to lane {:?}. Message size: {:?}",
|
||||
nonce,
|
||||
args.lane_id,
|
||||
message_len,
|
||||
);
|
||||
|
||||
Error::<T, I>::MessageRejectedByChainVerifier(err)
|
||||
})?;
|
||||
Pallet::<T, I>::deposit_event(Event::MessageAccepted { lane_id: args.lane_id, nonce });
|
||||
|
||||
// now let's enforce any additional lane rules
|
||||
let mut lane = outbound_lane::<T, I>(lane_id);
|
||||
T::LaneMessageVerifier::verify_message(&lane_id, &lane.data(), &payload).map_err(|err| {
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"Message to lane {:?} is rejected by lane verifier: {:?}",
|
||||
lane_id,
|
||||
err,
|
||||
);
|
||||
|
||||
Error::<T, I>::MessageRejectedByLaneVerifier(err)
|
||||
})?;
|
||||
|
||||
// finally, save message in outbound storage and emit event
|
||||
let encoded_payload = payload.encode();
|
||||
let encoded_payload_len = encoded_payload.len();
|
||||
let nonce = lane
|
||||
.send_message(encoded_payload)
|
||||
.map_err(Error::<T, I>::MessageRejectedByPallet)?;
|
||||
|
||||
// return number of messages in the queue to let sender know about its state
|
||||
let enqueued_messages = lane.data().queued_messages().saturating_len();
|
||||
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"Accepted message {} to lane {:?}. Message size: {:?}",
|
||||
nonce,
|
||||
lane_id,
|
||||
encoded_payload_len,
|
||||
);
|
||||
|
||||
Pallet::<T, I>::deposit_event(Event::MessageAccepted { lane_id, nonce });
|
||||
|
||||
Ok(SendMessageArtifacts { nonce, enqueued_messages })
|
||||
SendMessageArtifacts { nonce, enqueued_messages }
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensure that the pallet is in normal operational mode.
|
||||
@@ -857,6 +855,8 @@ struct RuntimeOutboundLaneStorage<T, I = ()> {
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorage<T, I> {
|
||||
type StoredMessagePayload = StoredMessagePayload<T, I>;
|
||||
|
||||
fn id(&self) -> LaneId {
|
||||
self.lane_id
|
||||
}
|
||||
@@ -870,22 +870,15 @@ impl<T: Config<I>, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorag
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn message(&self, nonce: &MessageNonce) -> Option<MessagePayload> {
|
||||
fn message(&self, nonce: &MessageNonce) -> Option<Self::StoredMessagePayload> {
|
||||
OutboundMessages::<T, I>::get(MessageKey { lane_id: self.lane_id, nonce: *nonce })
|
||||
.map(Into::into)
|
||||
}
|
||||
|
||||
fn save_message(
|
||||
&mut self,
|
||||
nonce: MessageNonce,
|
||||
message_payload: MessagePayload,
|
||||
) -> Result<(), VerificationError> {
|
||||
fn save_message(&mut self, nonce: MessageNonce, message_payload: Self::StoredMessagePayload) {
|
||||
OutboundMessages::<T, I>::insert(
|
||||
MessageKey { lane_id: self.lane_id, nonce },
|
||||
StoredMessagePayload::<T, I>::try_from(message_payload)
|
||||
.map_err(|_| VerificationError::MessageTooLarge)?,
|
||||
message_payload,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_message(&mut self, nonce: &MessageNonce) {
|
||||
@@ -932,7 +925,10 @@ mod tests {
|
||||
},
|
||||
outbound_lane::ReceivalConfirmationError,
|
||||
};
|
||||
use bp_messages::{BridgeMessagesCall, UnrewardedRelayer, UnrewardedRelayersState};
|
||||
use bp_messages::{
|
||||
source_chain::MessagesBridge, BridgeMessagesCall, UnrewardedRelayer,
|
||||
UnrewardedRelayersState,
|
||||
};
|
||||
use bp_test_utils::generate_owned_bridge_module_tests;
|
||||
use frame_support::{
|
||||
assert_noop, assert_ok,
|
||||
@@ -949,14 +945,15 @@ mod tests {
|
||||
System::<TestRuntime>::reset_events();
|
||||
}
|
||||
|
||||
fn send_regular_message() {
|
||||
fn send_regular_message(lane_id: LaneId) {
|
||||
get_ready_for_events();
|
||||
|
||||
let outbound_lane = outbound_lane::<TestRuntime, ()>(TEST_LANE_ID);
|
||||
let outbound_lane = outbound_lane::<TestRuntime, ()>(lane_id);
|
||||
let message_nonce = outbound_lane.data().latest_generated_nonce + 1;
|
||||
let prev_enqueud_messages = outbound_lane.data().queued_messages().saturating_len();
|
||||
let artifacts = send_message::<TestRuntime, ()>(TEST_LANE_ID, REGULAR_PAYLOAD)
|
||||
.expect("send_message has failed");
|
||||
let valid_message = Pallet::<TestRuntime, ()>::validate_message(lane_id, ®ULAR_PAYLOAD)
|
||||
.expect("validate_message has failed");
|
||||
let artifacts = Pallet::<TestRuntime, ()>::send_message(valid_message);
|
||||
assert_eq!(artifacts.enqueued_messages, prev_enqueud_messages + 1);
|
||||
|
||||
// check event with assigned nonce
|
||||
@@ -965,7 +962,7 @@ mod tests {
|
||||
vec![EventRecord {
|
||||
phase: Phase::Initialization,
|
||||
event: TestEvent::Messages(Event::MessageAccepted {
|
||||
lane_id: TEST_LANE_ID,
|
||||
lane_id,
|
||||
nonce: message_nonce
|
||||
}),
|
||||
topics: vec![],
|
||||
@@ -1016,14 +1013,14 @@ mod tests {
|
||||
fn pallet_rejects_transactions_if_halted() {
|
||||
run_test(|| {
|
||||
// send message first to be able to check that delivery_proof fails later
|
||||
send_regular_message();
|
||||
send_regular_message(TEST_LANE_ID);
|
||||
|
||||
PalletOperatingMode::<TestRuntime, ()>::put(MessagesOperatingMode::Basic(
|
||||
BasicOperatingMode::Halted,
|
||||
));
|
||||
|
||||
assert_noop!(
|
||||
send_message::<TestRuntime, ()>(TEST_LANE_ID, REGULAR_PAYLOAD,),
|
||||
Pallet::<TestRuntime, ()>::validate_message(TEST_LANE_ID, ®ULAR_PAYLOAD),
|
||||
Error::<TestRuntime, ()>::NotOperatingNormally,
|
||||
);
|
||||
|
||||
@@ -1066,14 +1063,14 @@ mod tests {
|
||||
fn pallet_rejects_new_messages_in_rejecting_outbound_messages_operating_mode() {
|
||||
run_test(|| {
|
||||
// send message first to be able to check that delivery_proof fails later
|
||||
send_regular_message();
|
||||
send_regular_message(TEST_LANE_ID);
|
||||
|
||||
PalletOperatingMode::<TestRuntime, ()>::put(
|
||||
MessagesOperatingMode::RejectingOutboundMessages,
|
||||
);
|
||||
|
||||
assert_noop!(
|
||||
send_message::<TestRuntime, ()>(TEST_LANE_ID, REGULAR_PAYLOAD,),
|
||||
Pallet::<TestRuntime, ()>::validate_message(TEST_LANE_ID, ®ULAR_PAYLOAD),
|
||||
Error::<TestRuntime, ()>::NotOperatingNormally,
|
||||
);
|
||||
|
||||
@@ -1109,7 +1106,7 @@ mod tests {
|
||||
#[test]
|
||||
fn send_message_works() {
|
||||
run_test(|| {
|
||||
send_regular_message();
|
||||
send_regular_message(TEST_LANE_ID);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1123,7 +1120,7 @@ mod tests {
|
||||
.extra
|
||||
.extend_from_slice(&[0u8; MAX_OUTBOUND_PAYLOAD_SIZE as usize]);
|
||||
assert_noop!(
|
||||
send_message::<TestRuntime, ()>(TEST_LANE_ID, message_payload.clone(),),
|
||||
Pallet::<TestRuntime, ()>::validate_message(TEST_LANE_ID, &message_payload.clone(),),
|
||||
Error::<TestRuntime, ()>::MessageRejectedByPallet(
|
||||
VerificationError::MessageTooLarge
|
||||
),
|
||||
@@ -1134,7 +1131,11 @@ mod tests {
|
||||
message_payload.extra.pop();
|
||||
}
|
||||
assert_eq!(message_payload.encoded_size() as u32, MAX_OUTBOUND_PAYLOAD_SIZE);
|
||||
assert_ok!(send_message::<TestRuntime, ()>(TEST_LANE_ID, message_payload,),);
|
||||
|
||||
let valid_message =
|
||||
Pallet::<TestRuntime, ()>::validate_message(TEST_LANE_ID, &message_payload)
|
||||
.expect("validate_message has failed");
|
||||
Pallet::<TestRuntime, ()>::send_message(valid_message);
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1143,7 +1144,10 @@ mod tests {
|
||||
run_test(|| {
|
||||
// messages with this payload are rejected by target chain verifier
|
||||
assert_noop!(
|
||||
send_message::<TestRuntime, ()>(TEST_LANE_ID, PAYLOAD_REJECTED_BY_TARGET_CHAIN,),
|
||||
Pallet::<TestRuntime, ()>::validate_message(
|
||||
TEST_LANE_ID,
|
||||
&PAYLOAD_REJECTED_BY_TARGET_CHAIN,
|
||||
),
|
||||
Error::<TestRuntime, ()>::MessageRejectedByChainVerifier(VerificationError::Other(
|
||||
mock::TEST_ERROR
|
||||
)),
|
||||
@@ -1151,21 +1155,6 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lane_verifier_rejects_invalid_message_in_send_message() {
|
||||
run_test(|| {
|
||||
// messages with zero fee are rejected by lane verifier
|
||||
let mut message = REGULAR_PAYLOAD;
|
||||
message.reject_by_lane_verifier = true;
|
||||
assert_noop!(
|
||||
send_message::<TestRuntime, ()>(TEST_LANE_ID, message,),
|
||||
Error::<TestRuntime, ()>::MessageRejectedByLaneVerifier(VerificationError::Other(
|
||||
mock::TEST_ERROR
|
||||
)),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn receive_messages_proof_works() {
|
||||
run_test(|| {
|
||||
@@ -1318,7 +1307,7 @@ mod tests {
|
||||
#[test]
|
||||
fn receive_messages_delivery_proof_works() {
|
||||
run_test(|| {
|
||||
send_regular_message();
|
||||
send_regular_message(TEST_LANE_ID);
|
||||
receive_messages_delivery_proof();
|
||||
|
||||
assert_eq!(
|
||||
@@ -1331,8 +1320,8 @@ mod tests {
|
||||
#[test]
|
||||
fn receive_messages_delivery_proof_rewards_relayers() {
|
||||
run_test(|| {
|
||||
assert_ok!(send_message::<TestRuntime, ()>(TEST_LANE_ID, REGULAR_PAYLOAD,));
|
||||
assert_ok!(send_message::<TestRuntime, ()>(TEST_LANE_ID, REGULAR_PAYLOAD,));
|
||||
send_regular_message(TEST_LANE_ID);
|
||||
send_regular_message(TEST_LANE_ID);
|
||||
|
||||
// this reports delivery of message 1 => reward is paid to TEST_RELAYER_A
|
||||
let single_message_delivery_proof = TestMessagesDeliveryProof(Ok((
|
||||
@@ -1718,9 +1707,9 @@ mod tests {
|
||||
#[test]
|
||||
fn messages_delivered_callbacks_are_called() {
|
||||
run_test(|| {
|
||||
send_regular_message();
|
||||
send_regular_message();
|
||||
send_regular_message();
|
||||
send_regular_message(TEST_LANE_ID);
|
||||
send_regular_message(TEST_LANE_ID);
|
||||
send_regular_message(TEST_LANE_ID);
|
||||
|
||||
// messages 1+2 are confirmed in 1 tx, message 3 in a separate tx
|
||||
// dispatch of message 2 has failed
|
||||
@@ -1779,7 +1768,7 @@ mod tests {
|
||||
) {
|
||||
run_test(|| {
|
||||
// send message first to be able to check that delivery_proof fails later
|
||||
send_regular_message();
|
||||
send_regular_message(TEST_LANE_ID);
|
||||
|
||||
// 1) InboundLaneData declares that the `last_confirmed_nonce` is 1;
|
||||
// 2) InboundLaneData has no entries => `InboundLaneData::last_delivered_nonce()`
|
||||
@@ -1846,10 +1835,10 @@ mod tests {
|
||||
#[test]
|
||||
fn on_idle_callback_respects_remaining_weight() {
|
||||
run_test(|| {
|
||||
send_regular_message();
|
||||
send_regular_message();
|
||||
send_regular_message();
|
||||
send_regular_message();
|
||||
send_regular_message(TEST_LANE_ID);
|
||||
send_regular_message(TEST_LANE_ID);
|
||||
send_regular_message(TEST_LANE_ID);
|
||||
send_regular_message(TEST_LANE_ID);
|
||||
|
||||
assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
|
||||
RuntimeOrigin::signed(1),
|
||||
@@ -1928,10 +1917,10 @@ mod tests {
|
||||
fn on_idle_callback_is_rotating_lanes_to_prune() {
|
||||
run_test(|| {
|
||||
// send + receive confirmation for lane 1
|
||||
send_regular_message();
|
||||
send_regular_message(TEST_LANE_ID);
|
||||
receive_messages_delivery_proof();
|
||||
// send + receive confirmation for lane 2
|
||||
assert_ok!(send_message::<TestRuntime, ()>(TEST_LANE_ID_2, REGULAR_PAYLOAD,));
|
||||
send_regular_message(TEST_LANE_ID_2);
|
||||
assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
|
||||
RuntimeOrigin::signed(1),
|
||||
TestMessagesDeliveryProof(Ok((
|
||||
@@ -2007,7 +1996,7 @@ mod tests {
|
||||
fn outbound_message_from_unconfigured_lane_is_rejected() {
|
||||
run_test(|| {
|
||||
assert_noop!(
|
||||
send_message::<TestRuntime, ()>(TEST_LANE_ID_3, REGULAR_PAYLOAD,),
|
||||
Pallet::<TestRuntime, ()>::validate_message(TEST_LANE_ID_3, ®ULAR_PAYLOAD,),
|
||||
Error::<TestRuntime, ()>::InactiveOutboundLane,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -17,19 +17,17 @@
|
||||
// From construct_runtime macro
|
||||
#![allow(clippy::from_over_into)]
|
||||
|
||||
use crate::Config;
|
||||
use crate::{Config, StoredMessagePayload};
|
||||
|
||||
use bp_messages::{
|
||||
calc_relayers_rewards,
|
||||
source_chain::{
|
||||
DeliveryConfirmationPayments, LaneMessageVerifier, OnMessagesDelivered, TargetHeaderChain,
|
||||
},
|
||||
source_chain::{DeliveryConfirmationPayments, OnMessagesDelivered, TargetHeaderChain},
|
||||
target_chain::{
|
||||
DeliveryPayments, DispatchMessage, DispatchMessageData, MessageDispatch,
|
||||
ProvedLaneMessages, ProvedMessages, SourceHeaderChain,
|
||||
},
|
||||
DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload,
|
||||
OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState, VerificationError,
|
||||
DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, MessageNonce,
|
||||
UnrewardedRelayer, UnrewardedRelayersState, VerificationError,
|
||||
};
|
||||
use bp_runtime::{messages::MessageDispatchResult, Size};
|
||||
use codec::{Decode, Encode};
|
||||
@@ -50,8 +48,6 @@ pub type Balance = u64;
|
||||
pub struct TestPayload {
|
||||
/// Field that may be used to identify messages.
|
||||
pub id: u64,
|
||||
/// Reject this message by lane verifier?
|
||||
pub reject_by_lane_verifier: bool,
|
||||
/// Dispatch weight that is declared by the message sender.
|
||||
pub declared_weight: Weight,
|
||||
/// Message dispatch result.
|
||||
@@ -120,7 +116,6 @@ impl Config for TestRuntime {
|
||||
type DeliveryPayments = TestDeliveryPayments;
|
||||
|
||||
type TargetHeaderChain = TestTargetHeaderChain;
|
||||
type LaneMessageVerifier = TestLaneMessageVerifier;
|
||||
type DeliveryConfirmationPayments = TestDeliveryConfirmationPayments;
|
||||
type OnMessagesDelivered = TestOnMessagesDelivered;
|
||||
|
||||
@@ -268,24 +263,6 @@ impl TargetHeaderChain<TestPayload, TestRelayer> for TestTargetHeaderChain {
|
||||
}
|
||||
}
|
||||
|
||||
/// Lane message verifier that is used in tests.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TestLaneMessageVerifier;
|
||||
|
||||
impl LaneMessageVerifier<TestPayload> for TestLaneMessageVerifier {
|
||||
fn verify_message(
|
||||
_lane: &LaneId,
|
||||
_lane_outbound_data: &OutboundLaneData,
|
||||
payload: &TestPayload,
|
||||
) -> Result<(), VerificationError> {
|
||||
if !payload.reject_by_lane_verifier {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(VerificationError::Other(TEST_ERROR))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Reward payments at the target chain during delivery transaction.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TestDeliveryPayments;
|
||||
@@ -425,8 +402,8 @@ pub fn message(nonce: MessageNonce, payload: TestPayload) -> Message {
|
||||
}
|
||||
|
||||
/// Return valid outbound message data, constructed from given payload.
|
||||
pub fn outbound_message_data(payload: TestPayload) -> MessagePayload {
|
||||
payload.encode()
|
||||
pub fn outbound_message_data(payload: TestPayload) -> StoredMessagePayload<TestRuntime, ()> {
|
||||
StoredMessagePayload::<TestRuntime, ()>::try_from(payload.encode()).expect("payload too large")
|
||||
}
|
||||
|
||||
/// Return valid inbound (dispatch) message data, constructed from given payload.
|
||||
@@ -438,7 +415,6 @@ pub fn inbound_message_data(payload: TestPayload) -> DispatchMessageData<TestPay
|
||||
pub const fn message_payload(id: u64, declared_weight: u64) -> TestPayload {
|
||||
TestPayload {
|
||||
id,
|
||||
reject_by_lane_verifier: false,
|
||||
declared_weight: Weight::from_parts(declared_weight, 0),
|
||||
dispatch_result: dispatch_result(0),
|
||||
extra: Vec::new(),
|
||||
|
||||
@@ -18,10 +18,7 @@
|
||||
|
||||
use crate::{Config, LOG_TARGET};
|
||||
|
||||
use bp_messages::{
|
||||
DeliveredMessages, LaneId, MessageNonce, MessagePayload, OutboundLaneData, UnrewardedRelayer,
|
||||
VerificationError,
|
||||
};
|
||||
use bp_messages::{DeliveredMessages, LaneId, MessageNonce, OutboundLaneData, UnrewardedRelayer};
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::{
|
||||
weights::{RuntimeDbWeight, Weight},
|
||||
@@ -34,6 +31,8 @@ use sp_std::collections::vec_deque::VecDeque;
|
||||
|
||||
/// Outbound lane storage.
|
||||
pub trait OutboundLaneStorage {
|
||||
type StoredMessagePayload;
|
||||
|
||||
/// Lane id.
|
||||
fn id(&self) -> LaneId;
|
||||
/// Get lane data from the storage.
|
||||
@@ -42,13 +41,9 @@ pub trait OutboundLaneStorage {
|
||||
fn set_data(&mut self, data: OutboundLaneData);
|
||||
/// Returns saved outbound message payload.
|
||||
#[cfg(test)]
|
||||
fn message(&self, nonce: &MessageNonce) -> Option<MessagePayload>;
|
||||
fn message(&self, nonce: &MessageNonce) -> Option<Self::StoredMessagePayload>;
|
||||
/// Save outbound message in the storage.
|
||||
fn save_message(
|
||||
&mut self,
|
||||
nonce: MessageNonce,
|
||||
message_payload: MessagePayload,
|
||||
) -> Result<(), VerificationError>;
|
||||
fn save_message(&mut self, nonce: MessageNonce, message_payload: Self::StoredMessagePayload);
|
||||
/// Remove outbound message from the storage.
|
||||
fn remove_message(&mut self, nonce: &MessageNonce);
|
||||
}
|
||||
@@ -91,18 +86,15 @@ impl<S: OutboundLaneStorage> OutboundLane<S> {
|
||||
/// Send message over lane.
|
||||
///
|
||||
/// Returns new message nonce.
|
||||
pub fn send_message(
|
||||
&mut self,
|
||||
message_payload: MessagePayload,
|
||||
) -> Result<MessageNonce, VerificationError> {
|
||||
pub fn send_message(&mut self, message_payload: S::StoredMessagePayload) -> MessageNonce {
|
||||
let mut data = self.storage.data();
|
||||
let nonce = data.latest_generated_nonce + 1;
|
||||
data.latest_generated_nonce = nonce;
|
||||
|
||||
self.storage.save_message(nonce, message_payload)?;
|
||||
self.storage.save_message(nonce, message_payload);
|
||||
self.storage.set_data(data);
|
||||
|
||||
Ok(nonce)
|
||||
nonce
|
||||
}
|
||||
|
||||
/// Confirm messages delivery.
|
||||
@@ -218,7 +210,7 @@ mod tests {
|
||||
},
|
||||
outbound_lane,
|
||||
};
|
||||
use frame_support::{assert_ok, weights::constants::RocksDbWeight};
|
||||
use frame_support::weights::constants::RocksDbWeight;
|
||||
use sp_std::ops::RangeInclusive;
|
||||
|
||||
fn unrewarded_relayers(
|
||||
@@ -239,9 +231,9 @@ mod tests {
|
||||
) -> Result<Option<DeliveredMessages>, ReceivalConfirmationError> {
|
||||
run_test(|| {
|
||||
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
||||
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
|
||||
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
|
||||
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
|
||||
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
|
||||
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
|
||||
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
|
||||
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
|
||||
assert_eq!(lane.storage.data().latest_received_nonce, 0);
|
||||
let result = lane.confirm_delivery(3, latest_received_nonce, relayers);
|
||||
@@ -256,7 +248,7 @@ mod tests {
|
||||
run_test(|| {
|
||||
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
||||
assert_eq!(lane.storage.data().latest_generated_nonce, 0);
|
||||
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(1));
|
||||
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 1);
|
||||
assert!(lane.storage.message(&1).is_some());
|
||||
assert_eq!(lane.storage.data().latest_generated_nonce, 1);
|
||||
});
|
||||
@@ -266,9 +258,9 @@ mod tests {
|
||||
fn confirm_delivery_works() {
|
||||
run_test(|| {
|
||||
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
||||
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(1));
|
||||
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(2));
|
||||
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(3));
|
||||
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 1);
|
||||
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 2);
|
||||
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 3);
|
||||
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
|
||||
assert_eq!(lane.storage.data().latest_received_nonce, 0);
|
||||
assert_eq!(
|
||||
@@ -284,9 +276,9 @@ mod tests {
|
||||
fn confirm_delivery_rejects_nonce_lesser_than_latest_received() {
|
||||
run_test(|| {
|
||||
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
||||
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
|
||||
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
|
||||
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
|
||||
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
|
||||
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
|
||||
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
|
||||
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
|
||||
assert_eq!(lane.storage.data().latest_received_nonce, 0);
|
||||
assert_eq!(
|
||||
@@ -368,9 +360,9 @@ mod tests {
|
||||
);
|
||||
assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1);
|
||||
// when nothing is confirmed, nothing is pruned
|
||||
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
|
||||
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
|
||||
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
|
||||
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
|
||||
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
|
||||
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
|
||||
assert!(lane.storage.message(&1).is_some());
|
||||
assert!(lane.storage.message(&2).is_some());
|
||||
assert!(lane.storage.message(&3).is_some());
|
||||
@@ -412,9 +404,9 @@ mod tests {
|
||||
fn confirm_delivery_detects_when_more_than_expected_messages_are_confirmed() {
|
||||
run_test(|| {
|
||||
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
||||
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
|
||||
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
|
||||
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
|
||||
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
|
||||
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
|
||||
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
|
||||
assert_eq!(
|
||||
lane.confirm_delivery(0, 3, &unrewarded_relayers(1..=3)),
|
||||
Err(ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected),
|
||||
|
||||
@@ -178,7 +178,7 @@ mod tests {
|
||||
RuntimeCall::Parachains(crate::Call::<TestRuntime, ()>::submit_parachain_heads {
|
||||
at_relay_block: (num, Default::default()),
|
||||
parachains,
|
||||
parachain_heads_proof: ParaHeadsProof(Vec::new()),
|
||||
parachain_heads_proof: ParaHeadsProof { storage_proof: Vec::new() },
|
||||
})
|
||||
.check_obsolete_submit_parachain_heads()
|
||||
.is_ok()
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
//! accepts storage proof of some parachain `Heads` entries from bridged relay chain.
|
||||
//! It requires corresponding relay headers to be already synced.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
pub use weights::WeightInfo;
|
||||
@@ -98,27 +99,49 @@ pub mod pallet {
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event<T: Config<I>, I: 'static = ()> {
|
||||
/// The caller has provided head of parachain that the pallet is not configured to track.
|
||||
UntrackedParachainRejected { parachain: ParaId },
|
||||
UntrackedParachainRejected {
|
||||
/// Identifier of the parachain that is not tracked by the pallet.
|
||||
parachain: ParaId,
|
||||
},
|
||||
/// The caller has declared that he has provided given parachain head, but it is missing
|
||||
/// from the storage proof.
|
||||
MissingParachainHead { parachain: ParaId },
|
||||
MissingParachainHead {
|
||||
/// Identifier of the parachain with missing head.
|
||||
parachain: ParaId,
|
||||
},
|
||||
/// The caller has provided parachain head hash that is not matching the hash read from the
|
||||
/// storage proof.
|
||||
IncorrectParachainHeadHash {
|
||||
/// Identifier of the parachain with incorrect head hast.
|
||||
parachain: ParaId,
|
||||
/// Specified parachain head hash.
|
||||
parachain_head_hash: ParaHash,
|
||||
/// Actual parachain head hash.
|
||||
actual_parachain_head_hash: ParaHash,
|
||||
},
|
||||
/// The caller has provided obsolete parachain head, which is already known to the pallet.
|
||||
RejectedObsoleteParachainHead { parachain: ParaId, parachain_head_hash: ParaHash },
|
||||
RejectedObsoleteParachainHead {
|
||||
/// Identifier of the parachain with obsolete head.
|
||||
parachain: ParaId,
|
||||
/// Obsolete parachain head hash.
|
||||
parachain_head_hash: ParaHash,
|
||||
},
|
||||
/// The caller has provided parachain head that exceeds the maximal configured head size.
|
||||
RejectedLargeParachainHead {
|
||||
/// Identifier of the parachain with rejected head.
|
||||
parachain: ParaId,
|
||||
/// Parachain head hash.
|
||||
parachain_head_hash: ParaHash,
|
||||
/// Parachain head size.
|
||||
parachain_head_size: u32,
|
||||
},
|
||||
/// Parachain head has been updated.
|
||||
UpdatedParachainHead { parachain: ParaId, parachain_head_hash: ParaHash },
|
||||
UpdatedParachainHead {
|
||||
/// Identifier of the parachain that has been updated.
|
||||
parachain: ParaId,
|
||||
/// Parachain head hash.
|
||||
parachain_head_hash: ParaHash,
|
||||
},
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
@@ -137,6 +160,7 @@ pub mod pallet {
|
||||
pub trait BoundedBridgeGrandpaConfig<I: 'static>:
|
||||
pallet_bridge_grandpa::Config<I, BridgedChain = Self::BridgedRelayChain>
|
||||
{
|
||||
/// Type of the bridged relay chain.
|
||||
type BridgedRelayChain: Chain<
|
||||
BlockNumber = RelayBlockNumber,
|
||||
Hash = RelayBlockHash,
|
||||
@@ -336,7 +360,7 @@ pub mod pallet {
|
||||
|
||||
let mut storage = GrandpaPalletOf::<T, I>::storage_proof_checker(
|
||||
relay_block_hash,
|
||||
parachain_heads_proof.0,
|
||||
parachain_heads_proof.storage_proof,
|
||||
)
|
||||
.map_err(Error::<T, I>::HeaderChainStorageProof)?;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use bp_header_chain::ChainWithGrandpa;
|
||||
use bp_polkadot_core::parachains::ParaId;
|
||||
use bp_runtime::{Chain, Parachain};
|
||||
use bp_runtime::{Chain, ChainId, Parachain};
|
||||
use frame_support::{
|
||||
construct_runtime, derive_impl, parameter_types, traits::ConstU32, weights::Weight,
|
||||
};
|
||||
@@ -49,6 +49,8 @@ pub type BigParachainHeader = sp_runtime::generic::Header<u128, BlakeTwo256>;
|
||||
pub struct Parachain1;
|
||||
|
||||
impl Chain for Parachain1 {
|
||||
const ID: ChainId = *b"pch1";
|
||||
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hasher = RegularParachainHasher;
|
||||
@@ -73,6 +75,8 @@ impl Parachain for Parachain1 {
|
||||
pub struct Parachain2;
|
||||
|
||||
impl Chain for Parachain2 {
|
||||
const ID: ChainId = *b"pch2";
|
||||
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hasher = RegularParachainHasher;
|
||||
@@ -97,6 +101,8 @@ impl Parachain for Parachain2 {
|
||||
pub struct Parachain3;
|
||||
|
||||
impl Chain for Parachain3 {
|
||||
const ID: ChainId = *b"pch3";
|
||||
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hasher = RegularParachainHasher;
|
||||
@@ -122,6 +128,8 @@ impl Parachain for Parachain3 {
|
||||
pub struct BigParachain;
|
||||
|
||||
impl Chain for BigParachain {
|
||||
const ID: ChainId = *b"bpch";
|
||||
|
||||
type BlockNumber = u128;
|
||||
type Hash = H256;
|
||||
type Hasher = RegularParachainHasher;
|
||||
@@ -229,6 +237,8 @@ impl pallet_bridge_parachains::benchmarking::Config<()> for TestRuntime {
|
||||
pub struct TestBridgedChain;
|
||||
|
||||
impl Chain for TestBridgedChain {
|
||||
const ID: ChainId = *b"tbch";
|
||||
|
||||
type BlockNumber = crate::RelayBlockNumber;
|
||||
type Hash = crate::RelayBlockHash;
|
||||
type Hasher = crate::RelayBlockHasher;
|
||||
@@ -260,6 +270,8 @@ impl ChainWithGrandpa for TestBridgedChain {
|
||||
pub struct OtherBridgedChain;
|
||||
|
||||
impl Chain for OtherBridgedChain {
|
||||
const ID: ChainId = *b"obch";
|
||||
|
||||
type BlockNumber = u64;
|
||||
type Hash = crate::RelayBlockHash;
|
||||
type Hasher = crate::RelayBlockHasher;
|
||||
|
||||
@@ -42,12 +42,13 @@ type MessagesPallet<T, I> = BridgeMessagesPallet<T, <T as Config<I>>::BridgeMess
|
||||
|
||||
impl<T: Config<I>, I: 'static> ExportXcm for Pallet<T, I>
|
||||
where
|
||||
T: BridgeMessagesConfig<
|
||||
<T as Config<I>>::BridgeMessagesPalletInstance,
|
||||
OutboundPayload = XcmAsPlainPayload,
|
||||
>,
|
||||
T: BridgeMessagesConfig<T::BridgeMessagesPalletInstance, OutboundPayload = XcmAsPlainPayload>,
|
||||
{
|
||||
type Ticket = (SenderAndLane, XcmAsPlainPayload, XcmHash);
|
||||
type Ticket = (
|
||||
SenderAndLane,
|
||||
<MessagesPallet<T, I> as MessagesBridge<T::OutboundPayload>>::SendMessageArgs,
|
||||
XcmHash,
|
||||
);
|
||||
|
||||
fn validate(
|
||||
network: NetworkId,
|
||||
@@ -74,42 +75,38 @@ where
|
||||
message,
|
||||
)?;
|
||||
|
||||
Ok(((sender_and_lane, blob, id), price))
|
||||
}
|
||||
|
||||
fn deliver(
|
||||
(sender_and_lane, blob, id): (SenderAndLane, XcmAsPlainPayload, XcmHash),
|
||||
) -> Result<XcmHash, SendError> {
|
||||
let lane_id = sender_and_lane.lane;
|
||||
let send_result = MessagesPallet::<T, I>::send_message(lane_id, blob);
|
||||
|
||||
match send_result {
|
||||
Ok(artifacts) => {
|
||||
log::info!(
|
||||
target: LOG_TARGET,
|
||||
"XCM message {:?} has been enqueued at bridge {:?} with nonce {}",
|
||||
id,
|
||||
lane_id,
|
||||
artifacts.nonce,
|
||||
);
|
||||
|
||||
// notify XCM queue manager about updated lane state
|
||||
LocalXcmQueueManager::<T::LanesSupport>::on_bridge_message_enqueued(
|
||||
&sender_and_lane,
|
||||
artifacts.enqueued_messages,
|
||||
);
|
||||
},
|
||||
Err(error) => {
|
||||
let bridge_message = MessagesPallet::<T, I>::validate_message(sender_and_lane.lane, &blob)
|
||||
.map_err(|e| {
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"XCM message {:?} has been dropped because of bridge error {:?} on bridge {:?}",
|
||||
"XCM message {:?} cannot be exported because of bridge error {:?} on bridge {:?}",
|
||||
id,
|
||||
error,
|
||||
lane_id,
|
||||
e,
|
||||
sender_and_lane.lane,
|
||||
);
|
||||
return Err(SendError::Transport("BridgeSendError"))
|
||||
},
|
||||
}
|
||||
SendError::Transport("BridgeValidateError")
|
||||
})?;
|
||||
|
||||
Ok(((sender_and_lane, bridge_message, id), price))
|
||||
}
|
||||
|
||||
fn deliver((sender_and_lane, bridge_message, id): Self::Ticket) -> Result<XcmHash, SendError> {
|
||||
let lane_id = sender_and_lane.lane;
|
||||
let artifacts = MessagesPallet::<T, I>::send_message(bridge_message);
|
||||
|
||||
log::info!(
|
||||
target: LOG_TARGET,
|
||||
"XCM message {:?} has been enqueued at bridge {:?} with nonce {}",
|
||||
id,
|
||||
lane_id,
|
||||
artifacts.nonce,
|
||||
);
|
||||
|
||||
// notify XCM queue manager about updated lane state
|
||||
LocalXcmQueueManager::<T::LanesSupport>::on_bridge_message_enqueued(
|
||||
&sender_and_lane,
|
||||
artifacts.enqueued_messages,
|
||||
);
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
@@ -19,11 +19,10 @@
|
||||
use crate as pallet_xcm_bridge_hub;
|
||||
|
||||
use bp_messages::{
|
||||
source_chain::LaneMessageVerifier,
|
||||
target_chain::{DispatchMessage, MessageDispatch},
|
||||
LaneId, OutboundLaneData, VerificationError,
|
||||
LaneId,
|
||||
};
|
||||
use bp_runtime::{messages::MessageDispatchResult, Chain, UnderlyingChainProvider};
|
||||
use bp_runtime::{messages::MessageDispatchResult, Chain, ChainId, UnderlyingChainProvider};
|
||||
use bridge_runtime_common::{
|
||||
messages::{
|
||||
source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter,
|
||||
@@ -78,20 +77,6 @@ impl pallet_balances::Config for TestRuntime {
|
||||
type AccountStore = System;
|
||||
}
|
||||
|
||||
/// Lane message verifier that is used in tests.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TestLaneMessageVerifier;
|
||||
|
||||
impl LaneMessageVerifier<Vec<u8>> for TestLaneMessageVerifier {
|
||||
fn verify_message(
|
||||
_lane: &LaneId,
|
||||
_lane_outbound_data: &OutboundLaneData,
|
||||
_payload: &Vec<u8>,
|
||||
) -> Result<(), VerificationError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const ActiveOutboundLanes: &'static [LaneId] = &[TEST_LANE_ID];
|
||||
}
|
||||
@@ -110,7 +95,6 @@ impl pallet_bridge_messages::Config for TestRuntime {
|
||||
type InboundRelayer = ();
|
||||
type DeliveryPayments = ();
|
||||
type TargetHeaderChain = TargetHeaderChainAdapter<OnThisChainBridge>;
|
||||
type LaneMessageVerifier = TestLaneMessageVerifier;
|
||||
type DeliveryConfirmationPayments = ();
|
||||
type OnMessagesDelivered = ();
|
||||
type SourceHeaderChain = SourceHeaderChainAdapter<OnThisChainBridge>;
|
||||
@@ -217,6 +201,7 @@ impl XcmBlobHauler for TestXcmBlobHauler {
|
||||
pub struct ThisChain;
|
||||
|
||||
impl Chain for ThisChain {
|
||||
const ID: ChainId = *b"tuch";
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hasher = BlakeTwo256;
|
||||
@@ -240,6 +225,7 @@ pub type BridgedHeaderHash = H256;
|
||||
pub type BridgedChainHeader = SubstrateHeader;
|
||||
|
||||
impl Chain for BridgedChain {
|
||||
const ID: ChainId = *b"tuch";
|
||||
type BlockNumber = u64;
|
||||
type Hash = BridgedHeaderHash;
|
||||
type Hasher = BlakeTwo256;
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
// 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/>.
|
||||
|
||||
//! Primitives of all Cumulus-based bridge hubs.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
pub use bp_polkadot_core::{
|
||||
@@ -61,6 +64,7 @@ const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(constants::WEIGHT_REF_TI
|
||||
pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5);
|
||||
|
||||
parameter_types! {
|
||||
/// Size limit of the Cumulus-based bridge hub blocks.
|
||||
pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio(
|
||||
5 * 1024 * 1024,
|
||||
NORMAL_DISPATCH_RATIO,
|
||||
@@ -73,6 +77,7 @@ parameter_types! {
|
||||
pub const ExtrinsicBaseWeight: Weight = Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS, 0)
|
||||
.saturating_mul(125_000);
|
||||
|
||||
/// Weight limit of the Cumulus-based bridge hub blocks.
|
||||
pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder()
|
||||
.base_block(BlockExecutionWeight::get())
|
||||
.for_class(DispatchClass::all(), |weights| {
|
||||
|
||||
@@ -17,12 +17,13 @@
|
||||
//! Module with configuration which reflects BridgeHubKusama runtime setup (AccountId, Headers,
|
||||
//! Hashes...)
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
pub use bp_bridge_hub_cumulus::*;
|
||||
use bp_messages::*;
|
||||
use bp_runtime::{
|
||||
decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain,
|
||||
decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, ChainId, Parachain,
|
||||
};
|
||||
use frame_support::{
|
||||
dispatch::DispatchClass,
|
||||
@@ -35,6 +36,8 @@ use sp_runtime::RuntimeDebug;
|
||||
pub struct BridgeHubKusama;
|
||||
|
||||
impl Chain for BridgeHubKusama {
|
||||
const ID: ChainId = *b"bhks";
|
||||
|
||||
type BlockNumber = BlockNumber;
|
||||
type Hash = Hash;
|
||||
type Hasher = Hasher;
|
||||
@@ -61,6 +64,15 @@ impl Parachain for BridgeHubKusama {
|
||||
const PARACHAIN_ID: u32 = BRIDGE_HUB_KUSAMA_PARACHAIN_ID;
|
||||
}
|
||||
|
||||
impl ChainWithMessages for BridgeHubKusama {
|
||||
const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str =
|
||||
WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME;
|
||||
const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce =
|
||||
MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
|
||||
const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce =
|
||||
MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
|
||||
}
|
||||
|
||||
/// Public key of the chain account that may be used to verify signatures.
|
||||
pub type AccountSigner = MultiSigner;
|
||||
|
||||
|
||||
@@ -17,12 +17,13 @@
|
||||
//! Module with configuration which reflects BridgeHubPolkadot runtime setup
|
||||
//! (AccountId, Headers, Hashes...)
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
pub use bp_bridge_hub_cumulus::*;
|
||||
use bp_messages::*;
|
||||
use bp_runtime::{
|
||||
decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain,
|
||||
decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, ChainId, Parachain,
|
||||
};
|
||||
use frame_support::dispatch::DispatchClass;
|
||||
use sp_runtime::RuntimeDebug;
|
||||
@@ -32,6 +33,8 @@ use sp_runtime::RuntimeDebug;
|
||||
pub struct BridgeHubPolkadot;
|
||||
|
||||
impl Chain for BridgeHubPolkadot {
|
||||
const ID: ChainId = *b"bhpd";
|
||||
|
||||
type BlockNumber = BlockNumber;
|
||||
type Hash = Hash;
|
||||
type Hasher = Hasher;
|
||||
@@ -58,6 +61,16 @@ impl Parachain for BridgeHubPolkadot {
|
||||
const PARACHAIN_ID: u32 = BRIDGE_HUB_POLKADOT_PARACHAIN_ID;
|
||||
}
|
||||
|
||||
impl ChainWithMessages for BridgeHubPolkadot {
|
||||
const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str =
|
||||
WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME;
|
||||
|
||||
const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce =
|
||||
MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
|
||||
const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce =
|
||||
MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
|
||||
}
|
||||
|
||||
/// Identifier of BridgeHubPolkadot in the Polkadot relay chain.
|
||||
pub const BRIDGE_HUB_POLKADOT_PARACHAIN_ID: u32 = 1002;
|
||||
|
||||
|
||||
@@ -17,12 +17,13 @@
|
||||
//! Module with configuration which reflects BridgeHubRococo runtime setup (AccountId, Headers,
|
||||
//! Hashes...)
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
pub use bp_bridge_hub_cumulus::*;
|
||||
use bp_messages::*;
|
||||
use bp_runtime::{
|
||||
decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain,
|
||||
decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, ChainId, Parachain,
|
||||
};
|
||||
use frame_support::dispatch::DispatchClass;
|
||||
use sp_runtime::{MultiAddress, MultiSigner, RuntimeDebug};
|
||||
@@ -32,6 +33,8 @@ use sp_runtime::{MultiAddress, MultiSigner, RuntimeDebug};
|
||||
pub struct BridgeHubRococo;
|
||||
|
||||
impl Chain for BridgeHubRococo {
|
||||
const ID: ChainId = *b"bhro";
|
||||
|
||||
type BlockNumber = BlockNumber;
|
||||
type Hash = Hash;
|
||||
type Hasher = Hasher;
|
||||
@@ -58,6 +61,16 @@ impl Parachain for BridgeHubRococo {
|
||||
const PARACHAIN_ID: u32 = BRIDGE_HUB_ROCOCO_PARACHAIN_ID;
|
||||
}
|
||||
|
||||
impl ChainWithMessages for BridgeHubRococo {
|
||||
const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str =
|
||||
WITH_BRIDGE_HUB_ROCOCO_MESSAGES_PALLET_NAME;
|
||||
|
||||
const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce =
|
||||
MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
|
||||
const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce =
|
||||
MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
|
||||
}
|
||||
|
||||
/// Public key of the chain account that may be used to verify signatures.
|
||||
pub type AccountSigner = MultiSigner;
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ workspace = true
|
||||
# Bridge Dependencies
|
||||
|
||||
bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false }
|
||||
bp-runtime = { path = "../../primitives/runtime", default-features = false }
|
||||
bp-messages = { path = "../../primitives/messages", default-features = false }
|
||||
bp-runtime = { path = "../runtime", default-features = false }
|
||||
bp-messages = { path = "../messages", default-features = false }
|
||||
|
||||
# Substrate Based Dependencies
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
pub use bp_bridge_hub_cumulus::*;
|
||||
use bp_messages::*;
|
||||
use bp_runtime::{
|
||||
decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain,
|
||||
decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, ChainId, Parachain,
|
||||
};
|
||||
use frame_support::dispatch::DispatchClass;
|
||||
use sp_runtime::RuntimeDebug;
|
||||
@@ -32,6 +32,8 @@ use sp_runtime::RuntimeDebug;
|
||||
pub struct BridgeHubWestend;
|
||||
|
||||
impl Chain for BridgeHubWestend {
|
||||
const ID: ChainId = *b"bhwd";
|
||||
|
||||
type BlockNumber = BlockNumber;
|
||||
type Hash = Hash;
|
||||
type Hasher = Hasher;
|
||||
@@ -58,6 +60,16 @@ impl Parachain for BridgeHubWestend {
|
||||
const PARACHAIN_ID: u32 = BRIDGE_HUB_WESTEND_PARACHAIN_ID;
|
||||
}
|
||||
|
||||
impl ChainWithMessages for BridgeHubWestend {
|
||||
const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str =
|
||||
WITH_BRIDGE_HUB_WESTEND_MESSAGES_PALLET_NAME;
|
||||
|
||||
const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce =
|
||||
MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
|
||||
const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce =
|
||||
MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
|
||||
}
|
||||
|
||||
/// Identifier of BridgeHubWestend in the Westend relay chain.
|
||||
pub const BRIDGE_HUB_WESTEND_PARACHAIN_ID: u32 = 1002;
|
||||
|
||||
|
||||
@@ -14,36 +14,39 @@
|
||||
// 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/>.
|
||||
|
||||
//! Primitives of the Kusama chain.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
// RuntimeApi generated functions
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
pub use bp_polkadot_core::*;
|
||||
|
||||
use bp_header_chain::ChainWithGrandpa;
|
||||
use bp_runtime::{decl_bridge_finality_runtime_apis, Chain};
|
||||
use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, ChainId};
|
||||
use frame_support::weights::Weight;
|
||||
|
||||
/// Kusama Chain
|
||||
pub struct Kusama;
|
||||
|
||||
impl Chain for Kusama {
|
||||
type BlockNumber = <PolkadotLike as Chain>::BlockNumber;
|
||||
type Hash = <PolkadotLike as Chain>::Hash;
|
||||
type Hasher = <PolkadotLike as Chain>::Hasher;
|
||||
type Header = <PolkadotLike as Chain>::Header;
|
||||
const ID: ChainId = *b"ksma";
|
||||
|
||||
type AccountId = <PolkadotLike as Chain>::AccountId;
|
||||
type Balance = <PolkadotLike as Chain>::Balance;
|
||||
type Nonce = <PolkadotLike as Chain>::Nonce;
|
||||
type Signature = <PolkadotLike as Chain>::Signature;
|
||||
type BlockNumber = BlockNumber;
|
||||
type Hash = Hash;
|
||||
type Hasher = Hasher;
|
||||
type Header = Header;
|
||||
|
||||
type AccountId = AccountId;
|
||||
type Balance = Balance;
|
||||
type Nonce = Nonce;
|
||||
type Signature = Signature;
|
||||
|
||||
fn max_extrinsic_size() -> u32 {
|
||||
PolkadotLike::max_extrinsic_size()
|
||||
max_extrinsic_size()
|
||||
}
|
||||
|
||||
fn max_extrinsic_weight() -> Weight {
|
||||
PolkadotLike::max_extrinsic_weight()
|
||||
max_extrinsic_weight()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,14 +20,14 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use bp_header_chain::ChainWithGrandpa;
|
||||
use bp_messages::MessageNonce;
|
||||
use bp_messages::{ChainWithMessages, MessageNonce};
|
||||
use bp_runtime::{
|
||||
decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis,
|
||||
extensions::{
|
||||
CheckEra, CheckGenesis, CheckNonZeroSender, CheckNonce, CheckSpecVersion, CheckTxVersion,
|
||||
CheckWeight, GenericSignedExtension, GenericSignedExtensionSchema,
|
||||
},
|
||||
Chain, TransactionEra,
|
||||
Chain, ChainId, TransactionEra,
|
||||
};
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::{
|
||||
@@ -177,6 +177,8 @@ parameter_types! {
|
||||
pub struct PolkadotBulletin;
|
||||
|
||||
impl Chain for PolkadotBulletin {
|
||||
const ID: ChainId = *b"pdbc";
|
||||
|
||||
type BlockNumber = BlockNumber;
|
||||
type Hash = Hash;
|
||||
type Hasher = Hasher;
|
||||
@@ -211,5 +213,15 @@ impl ChainWithGrandpa for PolkadotBulletin {
|
||||
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
|
||||
}
|
||||
|
||||
impl ChainWithMessages for PolkadotBulletin {
|
||||
const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str =
|
||||
WITH_POLKADOT_BULLETIN_MESSAGES_PALLET_NAME;
|
||||
|
||||
const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce =
|
||||
MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
|
||||
const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce =
|
||||
MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
|
||||
}
|
||||
|
||||
decl_bridge_finality_runtime_apis!(polkadot_bulletin, grandpa);
|
||||
decl_bridge_messages_runtime_apis!(polkadot_bulletin);
|
||||
|
||||
@@ -14,36 +14,41 @@
|
||||
// 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/>.
|
||||
|
||||
//! Primitives of the Polkadot chain.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
// RuntimeApi generated functions
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
pub use bp_polkadot_core::*;
|
||||
|
||||
use bp_header_chain::ChainWithGrandpa;
|
||||
use bp_runtime::{decl_bridge_finality_runtime_apis, extensions::PrevalidateAttests, Chain};
|
||||
use bp_runtime::{
|
||||
decl_bridge_finality_runtime_apis, extensions::PrevalidateAttests, Chain, ChainId,
|
||||
};
|
||||
use frame_support::weights::Weight;
|
||||
|
||||
/// Polkadot Chain
|
||||
pub struct Polkadot;
|
||||
|
||||
impl Chain for Polkadot {
|
||||
type BlockNumber = <PolkadotLike as Chain>::BlockNumber;
|
||||
type Hash = <PolkadotLike as Chain>::Hash;
|
||||
type Hasher = <PolkadotLike as Chain>::Hasher;
|
||||
type Header = <PolkadotLike as Chain>::Header;
|
||||
const ID: ChainId = *b"pdot";
|
||||
|
||||
type AccountId = <PolkadotLike as Chain>::AccountId;
|
||||
type Balance = <PolkadotLike as Chain>::Balance;
|
||||
type Nonce = <PolkadotLike as Chain>::Nonce;
|
||||
type Signature = <PolkadotLike as Chain>::Signature;
|
||||
type BlockNumber = BlockNumber;
|
||||
type Hash = Hash;
|
||||
type Hasher = Hasher;
|
||||
type Header = Header;
|
||||
|
||||
type AccountId = AccountId;
|
||||
type Balance = Balance;
|
||||
type Nonce = Nonce;
|
||||
type Signature = Signature;
|
||||
|
||||
fn max_extrinsic_size() -> u32 {
|
||||
PolkadotLike::max_extrinsic_size()
|
||||
max_extrinsic_size()
|
||||
}
|
||||
|
||||
fn max_extrinsic_weight() -> Weight {
|
||||
PolkadotLike::max_extrinsic_weight()
|
||||
max_extrinsic_weight()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,36 +14,39 @@
|
||||
// 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/>.
|
||||
|
||||
//! Primitives of the Rococo chain.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
// RuntimeApi generated functions
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
pub use bp_polkadot_core::*;
|
||||
|
||||
use bp_header_chain::ChainWithGrandpa;
|
||||
use bp_runtime::{decl_bridge_finality_runtime_apis, Chain};
|
||||
use frame_support::{parameter_types, weights::Weight};
|
||||
use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, ChainId};
|
||||
use frame_support::weights::Weight;
|
||||
|
||||
/// Rococo Chain
|
||||
pub struct Rococo;
|
||||
|
||||
impl Chain for Rococo {
|
||||
type BlockNumber = <PolkadotLike as Chain>::BlockNumber;
|
||||
type Hash = <PolkadotLike as Chain>::Hash;
|
||||
type Hasher = <PolkadotLike as Chain>::Hasher;
|
||||
type Header = <PolkadotLike as Chain>::Header;
|
||||
const ID: ChainId = *b"roco";
|
||||
|
||||
type AccountId = <PolkadotLike as Chain>::AccountId;
|
||||
type Balance = <PolkadotLike as Chain>::Balance;
|
||||
type Nonce = <PolkadotLike as Chain>::Nonce;
|
||||
type Signature = <PolkadotLike as Chain>::Signature;
|
||||
type BlockNumber = BlockNumber;
|
||||
type Hash = Hash;
|
||||
type Hasher = Hasher;
|
||||
type Header = Header;
|
||||
|
||||
type AccountId = AccountId;
|
||||
type Balance = Balance;
|
||||
type Nonce = Nonce;
|
||||
type Signature = Signature;
|
||||
|
||||
fn max_extrinsic_size() -> u32 {
|
||||
PolkadotLike::max_extrinsic_size()
|
||||
max_extrinsic_size()
|
||||
}
|
||||
|
||||
fn max_extrinsic_weight() -> Weight {
|
||||
PolkadotLike::max_extrinsic_weight()
|
||||
max_extrinsic_weight()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,10 +59,6 @@ impl ChainWithGrandpa for Rococo {
|
||||
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const SS58Prefix: u8 = 42;
|
||||
}
|
||||
|
||||
// The SignedExtension used by Rococo.
|
||||
pub use bp_polkadot_core::CommonSignedExtension as SignedExtension;
|
||||
|
||||
|
||||
@@ -14,36 +14,39 @@
|
||||
// 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/>.
|
||||
|
||||
//! Primitives of the Westend chain.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
// RuntimeApi generated functions
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
pub use bp_polkadot_core::*;
|
||||
|
||||
use bp_header_chain::ChainWithGrandpa;
|
||||
use bp_runtime::{decl_bridge_finality_runtime_apis, Chain};
|
||||
use frame_support::{parameter_types, weights::Weight};
|
||||
use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, ChainId};
|
||||
use frame_support::weights::Weight;
|
||||
|
||||
/// Westend Chain
|
||||
pub struct Westend;
|
||||
|
||||
impl Chain for Westend {
|
||||
type BlockNumber = <PolkadotLike as Chain>::BlockNumber;
|
||||
type Hash = <PolkadotLike as Chain>::Hash;
|
||||
type Hasher = <PolkadotLike as Chain>::Hasher;
|
||||
type Header = <PolkadotLike as Chain>::Header;
|
||||
const ID: ChainId = *b"wend";
|
||||
|
||||
type AccountId = <PolkadotLike as Chain>::AccountId;
|
||||
type Balance = <PolkadotLike as Chain>::Balance;
|
||||
type Nonce = <PolkadotLike as Chain>::Nonce;
|
||||
type Signature = <PolkadotLike as Chain>::Signature;
|
||||
type BlockNumber = BlockNumber;
|
||||
type Hash = Hash;
|
||||
type Hasher = Hasher;
|
||||
type Header = Header;
|
||||
|
||||
type AccountId = AccountId;
|
||||
type Balance = Balance;
|
||||
type Nonce = Nonce;
|
||||
type Signature = Signature;
|
||||
|
||||
fn max_extrinsic_size() -> u32 {
|
||||
PolkadotLike::max_extrinsic_size()
|
||||
max_extrinsic_size()
|
||||
}
|
||||
|
||||
fn max_extrinsic_weight() -> Weight {
|
||||
PolkadotLike::max_extrinsic_weight()
|
||||
max_extrinsic_weight()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,10 +59,6 @@ impl ChainWithGrandpa for Westend {
|
||||
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const SS58Prefix: u8 = 42;
|
||||
}
|
||||
|
||||
// The SignedExtension used by Westend.
|
||||
pub use bp_polkadot_core::CommonSignedExtension as SignedExtension;
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
//! Defines traits which represent a common interface for Substrate pallets which want to
|
||||
//! incorporate bridge functionality.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use crate::justification::{
|
||||
@@ -145,6 +146,7 @@ pub trait ConsensusLogReader {
|
||||
pub struct GrandpaConsensusLogReader<Number>(sp_std::marker::PhantomData<Number>);
|
||||
|
||||
impl<Number: Codec> GrandpaConsensusLogReader<Number> {
|
||||
/// Find and return scheduled (regular) change digest item.
|
||||
pub fn find_scheduled_change(
|
||||
digest: &Digest,
|
||||
) -> Option<sp_consensus_grandpa::ScheduledChange<Number>> {
|
||||
@@ -158,6 +160,8 @@ impl<Number: Codec> GrandpaConsensusLogReader<Number> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Find and return forced change digest item. Or light client can't do anything
|
||||
/// with forced changes, so we can't accept header with the forced change digest.
|
||||
pub fn find_forced_change(
|
||||
digest: &Digest,
|
||||
) -> Option<(Number, sp_consensus_grandpa::ScheduledChange<Number>)> {
|
||||
@@ -229,12 +233,17 @@ pub enum BridgeGrandpaCall<Header: HeaderT> {
|
||||
/// `pallet-bridge-grandpa::Call::submit_finality_proof`
|
||||
#[codec(index = 0)]
|
||||
submit_finality_proof {
|
||||
/// The header that we are going to finalize.
|
||||
finality_target: Box<Header>,
|
||||
/// Finality justification for the `finality_target`.
|
||||
justification: justification::GrandpaJustification<Header>,
|
||||
},
|
||||
/// `pallet-bridge-grandpa::Call::initialize`
|
||||
#[codec(index = 1)]
|
||||
initialize { init_data: InitializationData<Header> },
|
||||
initialize {
|
||||
/// All data, required to initialize the pallet.
|
||||
init_data: InitializationData<Header>,
|
||||
},
|
||||
}
|
||||
|
||||
/// The `BridgeGrandpaCall` used by a chain.
|
||||
@@ -325,12 +334,15 @@ pub fn max_expected_submit_finality_proof_arguments_size<C: ChainWithGrandpa>(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use bp_runtime::ChainId;
|
||||
use frame_support::weights::Weight;
|
||||
use sp_runtime::{testing::H256, traits::BlakeTwo256, MultiSignature};
|
||||
|
||||
struct TestChain;
|
||||
|
||||
impl Chain for TestChain {
|
||||
const ID: ChainId = *b"test";
|
||||
|
||||
type BlockNumber = u32;
|
||||
type Hash = H256;
|
||||
type Hasher = BlakeTwo256;
|
||||
|
||||
@@ -16,14 +16,13 @@
|
||||
|
||||
//! Primitives of messages module.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
// RuntimeApi generated functions
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
use bp_header_chain::HeaderChainError;
|
||||
use bp_runtime::{
|
||||
messages::MessageDispatchResult, BasicOperatingMode, OperatingMode, RangeInclusiveExt,
|
||||
StorageProofError,
|
||||
messages::MessageDispatchResult, BasicOperatingMode, Chain, OperatingMode, RangeInclusiveExt,
|
||||
StorageProofError, UnderlyingChainOf, UnderlyingChainProvider,
|
||||
};
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use frame_support::PalletError;
|
||||
@@ -39,6 +38,36 @@ pub mod source_chain;
|
||||
pub mod storage_keys;
|
||||
pub mod target_chain;
|
||||
|
||||
/// Substrate-based chain with messaging support.
|
||||
pub trait ChainWithMessages: Chain {
|
||||
/// Name of the bridge messages pallet (used in `construct_runtime` macro call) that is
|
||||
/// deployed at some other chain to bridge with this `ChainWithMessages`.
|
||||
///
|
||||
/// We assume that all chains that are bridging with this `ChainWithMessages` are using
|
||||
/// the same name.
|
||||
const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str;
|
||||
|
||||
/// Maximal number of unrewarded relayers in a single confirmation transaction at this
|
||||
/// `ChainWithMessages`.
|
||||
const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce;
|
||||
/// Maximal number of unconfirmed messages in a single confirmation transaction at this
|
||||
/// `ChainWithMessages`.
|
||||
const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce;
|
||||
}
|
||||
|
||||
impl<T> ChainWithMessages for T
|
||||
where
|
||||
T: Chain + UnderlyingChainProvider,
|
||||
UnderlyingChainOf<T>: ChainWithMessages,
|
||||
{
|
||||
const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str =
|
||||
UnderlyingChainOf::<T>::WITH_CHAIN_MESSAGES_PALLET_NAME;
|
||||
const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce =
|
||||
UnderlyingChainOf::<T>::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
|
||||
const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce =
|
||||
UnderlyingChainOf::<T>::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
|
||||
}
|
||||
|
||||
/// Messages pallet operating mode.
|
||||
#[derive(
|
||||
Encode,
|
||||
@@ -264,6 +293,7 @@ pub struct ReceivedMessages<DispatchLevelResult> {
|
||||
}
|
||||
|
||||
impl<DispatchLevelResult> ReceivedMessages<DispatchLevelResult> {
|
||||
/// Creates new `ReceivedMessages` structure from given results.
|
||||
pub fn new(
|
||||
lane: LaneId,
|
||||
receive_results: Vec<(MessageNonce, ReceivalResult<DispatchLevelResult>)>,
|
||||
@@ -271,6 +301,7 @@ impl<DispatchLevelResult> ReceivedMessages<DispatchLevelResult> {
|
||||
ReceivedMessages { lane, receive_results }
|
||||
}
|
||||
|
||||
/// Push `result` of the `message` delivery onto `receive_results` vector.
|
||||
pub fn push(&mut self, message: MessageNonce, result: ReceivalResult<DispatchLevelResult>) {
|
||||
self.receive_results.push((message, result));
|
||||
}
|
||||
@@ -342,7 +373,7 @@ pub struct UnrewardedRelayersState {
|
||||
}
|
||||
|
||||
impl UnrewardedRelayersState {
|
||||
// Verify that the relayers state corresponds with the `InboundLaneData`.
|
||||
/// Verify that the relayers state corresponds with the `InboundLaneData`.
|
||||
pub fn is_valid<RelayerId>(&self, lane_data: &InboundLaneData<RelayerId>) -> bool {
|
||||
self == &lane_data.into()
|
||||
}
|
||||
@@ -423,15 +454,21 @@ pub enum BridgeMessagesCall<AccountId, MessagesProof, MessagesDeliveryProof> {
|
||||
/// `pallet-bridge-messages::Call::receive_messages_proof`
|
||||
#[codec(index = 2)]
|
||||
receive_messages_proof {
|
||||
/// Account id of relayer at the **bridged** chain.
|
||||
relayer_id_at_bridged_chain: AccountId,
|
||||
/// Messages proof.
|
||||
proof: MessagesProof,
|
||||
/// A number of messages in the proof.
|
||||
messages_count: u32,
|
||||
/// Total dispatch weight of messages in the proof.
|
||||
dispatch_weight: Weight,
|
||||
},
|
||||
/// `pallet-bridge-messages::Call::receive_messages_delivery_proof`
|
||||
#[codec(index = 3)]
|
||||
receive_messages_delivery_proof {
|
||||
/// Messages delivery proof.
|
||||
proof: MessagesDeliveryProof,
|
||||
/// "Digest" of unrewarded relayers state at the bridged chain.
|
||||
relayers_state: UnrewardedRelayersState,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
//! Primitives of messages module, that are used on the source chain.
|
||||
|
||||
use crate::{InboundLaneData, LaneId, MessageNonce, OutboundLaneData, VerificationError};
|
||||
use crate::{InboundLaneData, LaneId, MessageNonce, VerificationError};
|
||||
|
||||
use crate::UnrewardedRelayer;
|
||||
use bp_runtime::Size;
|
||||
@@ -64,24 +64,6 @@ pub trait TargetHeaderChain<Payload, AccountId> {
|
||||
) -> Result<(LaneId, InboundLaneData<AccountId>), VerificationError>;
|
||||
}
|
||||
|
||||
/// Lane message verifier.
|
||||
///
|
||||
/// Runtime developer may implement any additional validation logic over message-lane mechanism.
|
||||
/// E.g. if lanes should have some security (e.g. you can only accept Lane1 messages from
|
||||
/// Submitter1, Lane2 messages for those who has submitted first message to this lane, disable
|
||||
/// Lane3 until some block, ...), then it may be built using this verifier.
|
||||
///
|
||||
/// Any fee requirements should also be enforced here.
|
||||
pub trait LaneMessageVerifier<Payload> {
|
||||
/// Verify message payload and return Ok(()) if message is valid and allowed to be sent over the
|
||||
/// lane.
|
||||
fn verify_message(
|
||||
lane: &LaneId,
|
||||
outbound_data: &OutboundLaneData,
|
||||
payload: &Payload,
|
||||
) -> Result<(), VerificationError>;
|
||||
}
|
||||
|
||||
/// Manages payments that are happening at the source chain during delivery confirmation
|
||||
/// transaction.
|
||||
pub trait DeliveryConfirmationPayments<AccountId> {
|
||||
@@ -143,25 +125,25 @@ pub trait MessagesBridge<Payload> {
|
||||
/// Error type.
|
||||
type Error: Debug;
|
||||
|
||||
/// Intermediary structure returned by `validate_message()`.
|
||||
///
|
||||
/// It can than be passed to `send_message()` in order to actually send the message
|
||||
/// on the bridge.
|
||||
type SendMessageArgs;
|
||||
|
||||
/// Check if the message can be sent over the bridge.
|
||||
fn validate_message(
|
||||
lane: LaneId,
|
||||
message: &Payload,
|
||||
) -> Result<Self::SendMessageArgs, Self::Error>;
|
||||
|
||||
/// Send message over the bridge.
|
||||
///
|
||||
/// Returns unique message nonce or error if send has failed.
|
||||
fn send_message(lane: LaneId, message: Payload) -> Result<SendMessageArtifacts, Self::Error>;
|
||||
fn send_message(message: Self::SendMessageArgs) -> SendMessageArtifacts;
|
||||
}
|
||||
|
||||
/// Bridge that does nothing when message is being sent.
|
||||
#[derive(Eq, RuntimeDebug, PartialEq)]
|
||||
pub struct NoopMessagesBridge;
|
||||
|
||||
impl<Payload> MessagesBridge<Payload> for NoopMessagesBridge {
|
||||
type Error = &'static str;
|
||||
|
||||
fn send_message(_lane: LaneId, _message: Payload) -> Result<SendMessageArtifacts, Self::Error> {
|
||||
Ok(SendMessageArtifacts { nonce: 0, enqueued_messages: 0 })
|
||||
}
|
||||
}
|
||||
|
||||
/// Structure that may be used in place of `TargetHeaderChain`, `LaneMessageVerifier` and
|
||||
/// Structure that may be used in place of `TargetHeaderChain` and
|
||||
/// `MessageDeliveryAndDispatchPayment` on chains, where outbound messages are forbidden.
|
||||
pub struct ForbidOutboundMessages;
|
||||
|
||||
@@ -183,16 +165,6 @@ impl<Payload, AccountId> TargetHeaderChain<Payload, AccountId> for ForbidOutboun
|
||||
}
|
||||
}
|
||||
|
||||
impl<Payload> LaneMessageVerifier<Payload> for ForbidOutboundMessages {
|
||||
fn verify_message(
|
||||
_lane: &LaneId,
|
||||
_outbound_data: &OutboundLaneData,
|
||||
_payload: &Payload,
|
||||
) -> Result<(), VerificationError> {
|
||||
Err(VerificationError::Other(ALL_OUTBOUND_MESSAGES_REJECTED))
|
||||
}
|
||||
}
|
||||
|
||||
impl<AccountId> DeliveryConfirmationPayments<AccountId> for ForbidOutboundMessages {
|
||||
type Error = &'static str;
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
//! Primitives of parachains module.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
pub use bp_header_chain::StoredHeaderData;
|
||||
@@ -173,8 +174,11 @@ pub enum BridgeParachainCall {
|
||||
/// `pallet-bridge-parachains::Call::submit_parachain_heads`
|
||||
#[codec(index = 0)]
|
||||
submit_parachain_heads {
|
||||
/// Relay chain block, for which we have submitted the `parachain_heads_proof`.
|
||||
at_relay_block: (RelayBlockNumber, RelayBlockHash),
|
||||
/// Parachain identifiers and their head hashes.
|
||||
parachains: Vec<(ParaId, ParaHash)>,
|
||||
/// Parachain heads proof.
|
||||
parachain_heads_proof: ParaHeadsProof,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
// 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/>.
|
||||
|
||||
//! Primitives of the Polkadot-like chains.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use bp_messages::MessageNonce;
|
||||
@@ -24,7 +27,7 @@ use bp_runtime::{
|
||||
CheckSpecVersion, CheckTxVersion, CheckWeight, GenericSignedExtension,
|
||||
SignedExtensionSchema,
|
||||
},
|
||||
Chain, EncodedOrDecodedCall, StorageMapKeyProvider, TransactionEra,
|
||||
EncodedOrDecodedCall, StorageMapKeyProvider, TransactionEra,
|
||||
};
|
||||
use frame_support::{
|
||||
dispatch::DispatchClass,
|
||||
@@ -40,7 +43,7 @@ use sp_core::{storage::StorageKey, Hasher as HasherT};
|
||||
use sp_runtime::{
|
||||
generic,
|
||||
traits::{BlakeTwo256, IdentifyAccount, Verify},
|
||||
MultiAddress, MultiSignature, OpaqueExtrinsic, RuntimeDebug,
|
||||
MultiAddress, MultiSignature, OpaqueExtrinsic,
|
||||
};
|
||||
use sp_std::prelude::Vec;
|
||||
|
||||
@@ -173,11 +176,16 @@ pub use time_units::*;
|
||||
pub mod time_units {
|
||||
use super::BlockNumber;
|
||||
|
||||
/// Milliseconds between Polkadot-like chain blocks.
|
||||
pub const MILLISECS_PER_BLOCK: u64 = 6000;
|
||||
/// Slot duration in Polkadot-like chain consensus algorithms.
|
||||
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
|
||||
|
||||
/// A minute, expressed in Polkadot-like chain blocks.
|
||||
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
|
||||
/// A hour, expressed in Polkadot-like chain blocks.
|
||||
pub const HOURS: BlockNumber = MINUTES * 60;
|
||||
/// A day, expressed in Polkadot-like chain blocks.
|
||||
pub const DAYS: BlockNumber = HOURS * 24;
|
||||
}
|
||||
|
||||
@@ -227,31 +235,17 @@ pub type UncheckedExtrinsic<Call, SignedExt> =
|
||||
/// Account address, used by the Polkadot-like chain.
|
||||
pub type Address = MultiAddress<AccountId, ()>;
|
||||
|
||||
/// Polkadot-like chain.
|
||||
#[derive(RuntimeDebug)]
|
||||
pub struct PolkadotLike;
|
||||
/// Returns maximal extrinsic size on all Polkadot-like chains.
|
||||
pub fn max_extrinsic_size() -> u32 {
|
||||
*BlockLength::get().max.get(DispatchClass::Normal)
|
||||
}
|
||||
|
||||
impl Chain for PolkadotLike {
|
||||
type BlockNumber = BlockNumber;
|
||||
type Hash = Hash;
|
||||
type Hasher = Hasher;
|
||||
type Header = Header;
|
||||
|
||||
type AccountId = AccountId;
|
||||
type Balance = Balance;
|
||||
type Nonce = Nonce;
|
||||
type Signature = Signature;
|
||||
|
||||
fn max_extrinsic_size() -> u32 {
|
||||
*BlockLength::get().max.get(DispatchClass::Normal)
|
||||
}
|
||||
|
||||
fn max_extrinsic_weight() -> Weight {
|
||||
BlockWeights::get()
|
||||
.get(DispatchClass::Normal)
|
||||
.max_extrinsic
|
||||
.unwrap_or(Weight::MAX)
|
||||
}
|
||||
/// Returns maximal extrinsic weight on all Polkadot-like chains.
|
||||
pub fn max_extrinsic_weight() -> Weight {
|
||||
BlockWeights::get()
|
||||
.get(DispatchClass::Normal)
|
||||
.max_extrinsic
|
||||
.unwrap_or(Weight::MAX)
|
||||
}
|
||||
|
||||
/// Provides a storage key for account data.
|
||||
@@ -271,8 +265,10 @@ impl StorageMapKeyProvider for AccountInfoStorageMapKeyProvider {
|
||||
}
|
||||
|
||||
impl AccountInfoStorageMapKeyProvider {
|
||||
/// Name of the system pallet.
|
||||
const PALLET_NAME: &'static str = "System";
|
||||
|
||||
/// Return storage key for given account data.
|
||||
pub fn final_key(id: &AccountId) -> StorageKey {
|
||||
<Self as StorageMapKeyProvider>::final_key(Self::PALLET_NAME, id)
|
||||
}
|
||||
|
||||
@@ -89,11 +89,18 @@ pub type ParaHasher = crate::Hasher;
|
||||
|
||||
/// Raw storage proof of parachain heads, stored in polkadot-like chain runtime.
|
||||
#[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
|
||||
pub struct ParaHeadsProof(pub RawStorageProof);
|
||||
pub struct ParaHeadsProof {
|
||||
/// Unverified storage proof of finalized parachain heads.
|
||||
pub storage_proof: RawStorageProof,
|
||||
}
|
||||
|
||||
impl Size for ParaHeadsProof {
|
||||
fn size(&self) -> u32 {
|
||||
u32::try_from(self.0.iter().fold(0usize, |sum, node| sum.saturating_add(node.len())))
|
||||
.unwrap_or(u32::MAX)
|
||||
u32::try_from(
|
||||
self.storage_proof
|
||||
.iter()
|
||||
.fold(0usize, |sum, node| sum.saturating_add(node.len())),
|
||||
)
|
||||
.unwrap_or(u32::MAX)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
// 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/>.
|
||||
|
||||
use crate::HeaderIdProvider;
|
||||
use crate::{ChainId, HeaderIdProvider};
|
||||
|
||||
use codec::{Codec, Decode, Encode, MaxEncodedLen};
|
||||
use frame_support::{weights::Weight, Parameter};
|
||||
use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero};
|
||||
@@ -99,6 +100,9 @@ impl<ChainCall: Encode> Encode for EncodedOrDecodedCall<ChainCall> {
|
||||
|
||||
/// Minimal Substrate-based chain representation that may be used from no_std environment.
|
||||
pub trait Chain: Send + Sync + 'static {
|
||||
/// Chain id.
|
||||
const ID: ChainId;
|
||||
|
||||
/// A type that fulfills the abstract idea of what a Substrate block number is.
|
||||
// Constraits come from the associated Number type of `sp_runtime::traits::Header`
|
||||
// See here for more info:
|
||||
@@ -208,6 +212,8 @@ impl<T> Chain for T
|
||||
where
|
||||
T: Send + Sync + 'static + UnderlyingChainProvider,
|
||||
{
|
||||
const ID: ChainId = <T::Chain as Chain>::ID;
|
||||
|
||||
type BlockNumber = <T::Chain as Chain>::BlockNumber;
|
||||
type Hash = <T::Chain as Chain>::Hash;
|
||||
type Hasher = <T::Chain as Chain>::Hasher;
|
||||
|
||||
@@ -102,6 +102,7 @@ impl SignedExtensionSchema for Tuple {
|
||||
/// and signed payloads in the client code.
|
||||
#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
|
||||
pub struct GenericSignedExtension<S: SignedExtensionSchema> {
|
||||
/// A payload that is included in the transaction.
|
||||
pub payload: S::Payload,
|
||||
#[codec(skip)]
|
||||
// It may be set to `None` if extensions are decoded. We are never reconstructing transactions
|
||||
@@ -112,6 +113,7 @@ pub struct GenericSignedExtension<S: SignedExtensionSchema> {
|
||||
}
|
||||
|
||||
impl<S: SignedExtensionSchema> GenericSignedExtension<S> {
|
||||
/// Create new `GenericSignedExtension` object.
|
||||
pub fn new(payload: S::Payload, additional_signed: Option<S::AdditionalSigned>) -> Self {
|
||||
Self { payload, additional_signed }
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
//! Primitives that may be used at (bridges) runtime level.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use codec::{Decode, Encode, FullCodec, MaxEncodedLen};
|
||||
@@ -61,36 +62,6 @@ pub use sp_runtime::paste;
|
||||
/// Use this when something must be shared among all instances.
|
||||
pub const NO_INSTANCE_ID: ChainId = [0, 0, 0, 0];
|
||||
|
||||
/// Polkadot chain id.
|
||||
pub const POLKADOT_CHAIN_ID: ChainId = *b"pdot";
|
||||
|
||||
/// Polkadot Bulletin chain id.
|
||||
pub const POLKADOT_BULLETIN_CHAIN_ID: ChainId = *b"pdbc";
|
||||
|
||||
/// Kusama chain id.
|
||||
pub const KUSAMA_CHAIN_ID: ChainId = *b"ksma";
|
||||
|
||||
/// Westend chain id.
|
||||
pub const WESTEND_CHAIN_ID: ChainId = *b"wend";
|
||||
|
||||
/// `AssetHubWestmint` chain id.
|
||||
pub const ASSET_HUB_WESTEND_CHAIN_ID: ChainId = *b"ahwe";
|
||||
|
||||
/// Rococo chain id.
|
||||
pub const ROCOCO_CHAIN_ID: ChainId = *b"roco";
|
||||
|
||||
/// BridgeHubRococo chain id.
|
||||
pub const BRIDGE_HUB_ROCOCO_CHAIN_ID: ChainId = *b"bhro";
|
||||
|
||||
/// BridgeHubWestend chain id.
|
||||
pub const BRIDGE_HUB_WESTEND_CHAIN_ID: ChainId = *b"bhwd";
|
||||
|
||||
/// BridgeHubKusama chain id.
|
||||
pub const BRIDGE_HUB_KUSAMA_CHAIN_ID: ChainId = *b"bhks";
|
||||
|
||||
/// BridgeHubPolkadot chain id.
|
||||
pub const BRIDGE_HUB_POLKADOT_CHAIN_ID: ChainId = *b"bhpd";
|
||||
|
||||
/// Generic header Id.
|
||||
#[derive(
|
||||
RuntimeDebug,
|
||||
@@ -126,10 +97,10 @@ pub type HeaderIdOf<C> = HeaderId<HashOf<C>, BlockNumberOf<C>>;
|
||||
|
||||
/// Generic header id provider.
|
||||
pub trait HeaderIdProvider<Header: HeaderT> {
|
||||
// Get the header id.
|
||||
/// Get the header id.
|
||||
fn id(&self) -> HeaderId<Header::Hash, Header::Number>;
|
||||
|
||||
// Get the header id for the parent block.
|
||||
/// Get the header id for the parent block.
|
||||
fn parent_id(&self) -> Option<HeaderId<Header::Hash, Header::Number>>;
|
||||
}
|
||||
|
||||
@@ -342,7 +313,7 @@ pub trait StorageDoubleMapKeyProvider {
|
||||
}
|
||||
|
||||
/// Error generated by the `OwnedBridgeModule` trait.
|
||||
#[derive(Encode, Decode, TypeInfo, PalletError)]
|
||||
#[derive(Encode, Decode, PartialEq, Eq, TypeInfo, PalletError)]
|
||||
pub enum OwnedBridgeModuleError {
|
||||
/// All pallet operations are halted.
|
||||
Halted,
|
||||
@@ -350,7 +321,7 @@ pub enum OwnedBridgeModuleError {
|
||||
|
||||
/// Operating mode for a bridge module.
|
||||
pub trait OperatingMode: Send + Copy + Debug + FullCodec {
|
||||
// Returns true if the bridge module is halted.
|
||||
/// Returns true if the bridge module is halted.
|
||||
fn is_halted(&self) -> bool;
|
||||
}
|
||||
|
||||
@@ -392,8 +363,11 @@ pub trait OwnedBridgeModule<T: frame_system::Config> {
|
||||
/// The target that will be used when publishing logs related to this module.
|
||||
const LOG_TARGET: &'static str;
|
||||
|
||||
/// A storage entry that holds the module `Owner` account.
|
||||
type OwnerStorage: StorageValue<T::AccountId, Query = Option<T::AccountId>>;
|
||||
/// Operating mode type of the pallet.
|
||||
type OperatingMode: OperatingMode;
|
||||
/// A storage value that holds the pallet operating mode.
|
||||
type OperatingModeStorage: StorageValue<Self::OperatingMode, Query = Self::OperatingMode>;
|
||||
|
||||
/// Check if the module is halted.
|
||||
@@ -469,9 +443,11 @@ impl WeightExtraOps for Weight {
|
||||
|
||||
/// Trait that provides a static `str`.
|
||||
pub trait StaticStrProvider {
|
||||
/// Static string.
|
||||
const STR: &'static str;
|
||||
}
|
||||
|
||||
/// A macro that generates `StaticStrProvider` with the string set to its stringified argument.
|
||||
#[macro_export]
|
||||
macro_rules! generate_static_str_provider {
|
||||
($str:expr) => {
|
||||
@@ -485,6 +461,7 @@ macro_rules! generate_static_str_provider {
|
||||
};
|
||||
}
|
||||
|
||||
/// Error message that is only dispayable in `std` environment.
|
||||
#[derive(Encode, Decode, Clone, Eq, PartialEq, PalletError, TypeInfo)]
|
||||
#[scale_info(skip_type_params(T))]
|
||||
pub struct StrippableError<T> {
|
||||
|
||||
@@ -24,12 +24,17 @@ use sp_consensus_grandpa::{AuthorityId, AuthorityList, AuthorityWeight, SetId};
|
||||
use sp_runtime::RuntimeDebug;
|
||||
use sp_std::prelude::*;
|
||||
|
||||
/// Set of test accounts with friendly names.
|
||||
/// Set of test accounts with friendly names: Alice.
|
||||
pub const ALICE: Account = Account(0);
|
||||
/// Set of test accounts with friendly names: Bob.
|
||||
pub const BOB: Account = Account(1);
|
||||
/// Set of test accounts with friendly names: Charlie.
|
||||
pub const CHARLIE: Account = Account(2);
|
||||
/// Set of test accounts with friendly names: Dave.
|
||||
pub const DAVE: Account = Account(3);
|
||||
/// Set of test accounts with friendly names: Eve.
|
||||
pub const EVE: Account = Account(4);
|
||||
/// Set of test accounts with friendly names: Ferdie.
|
||||
pub const FERDIE: Account = Account(5);
|
||||
|
||||
/// A test account which can be used to sign messages.
|
||||
@@ -37,10 +42,12 @@ pub const FERDIE: Account = Account(5);
|
||||
pub struct Account(pub u16);
|
||||
|
||||
impl Account {
|
||||
/// Returns public key of this account.
|
||||
pub fn public(&self) -> VerifyingKey {
|
||||
self.pair().verifying_key()
|
||||
}
|
||||
|
||||
/// Returns key pair, used to sign data on behalf of this account.
|
||||
pub fn pair(&self) -> SigningKey {
|
||||
let data = self.0.encode();
|
||||
let mut bytes = [0_u8; 32];
|
||||
@@ -48,6 +55,7 @@ impl Account {
|
||||
SigningKey::from_bytes(&bytes)
|
||||
}
|
||||
|
||||
/// Generate a signature of given message.
|
||||
pub fn sign(&self, msg: &[u8]) -> Signature {
|
||||
use ed25519_dalek::Signer;
|
||||
self.pair().sign(msg)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
//! Utilities for testing runtime code.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use bp_header_chain::justification::{required_justification_precommits, GrandpaJustification};
|
||||
@@ -33,8 +34,11 @@ pub use keyring::*;
|
||||
|
||||
mod keyring;
|
||||
|
||||
/// GRANDPA round number used across tests.
|
||||
pub const TEST_GRANDPA_ROUND: u64 = 1;
|
||||
/// GRANDPA validators set id used across tests.
|
||||
pub const TEST_GRANDPA_SET_ID: SetId = 1;
|
||||
/// Name of the `Paras` pallet used across tests.
|
||||
pub const PARAS_PALLET_NAME: &str = "Paras";
|
||||
|
||||
/// Configuration parameters when generating test GRANDPA justifications.
|
||||
@@ -190,7 +194,7 @@ pub fn prepare_parachain_heads_proof<H: HeaderT>(
|
||||
.map_err(|_| "record_all_trie_keys has failed")
|
||||
.expect("record_all_trie_keys should not fail in benchmarks");
|
||||
|
||||
(root, ParaHeadsProof(storage_proof), parachains)
|
||||
(root, ParaHeadsProof { storage_proof }, parachains)
|
||||
}
|
||||
|
||||
/// Create signed precommit with given target.
|
||||
|
||||
@@ -38,7 +38,7 @@ snowbridge-core = { path = "../../primitives/core", default-features = false }
|
||||
snowbridge-ethereum = { path = "../../primitives/ethereum", default-features = false }
|
||||
primitives = { package = "snowbridge-beacon-primitives", path = "../../primitives/beacon", default-features = false }
|
||||
static_assertions = { version = "1.1.0", default-features = false }
|
||||
bp-runtime = { path = "../../../../../bridges/primitives/runtime", default-features = false }
|
||||
bp-runtime = { path = "../../../../primitives/runtime", default-features = false }
|
||||
pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default-features = false, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -47,7 +47,7 @@ snowbridge-beacon-primitives = { path = "../../primitives/beacon", default-featu
|
||||
frame-benchmarking = { path = "../../../../../substrate/frame/benchmarking" }
|
||||
sp-keyring = { path = "../../../../../substrate/primitives/keyring" }
|
||||
snowbridge-beacon-primitives = { path = "../../primitives/beacon" }
|
||||
snowbridge-pallet-ethereum-client = { path = "../../pallets/ethereum-client" }
|
||||
snowbridge-pallet-ethereum-client = { path = "../ethereum-client" }
|
||||
hex-literal = { version = "0.4.1" }
|
||||
|
||||
[features]
|
||||
|
||||
@@ -31,7 +31,7 @@ sp-arithmetic = { path = "../../../../../substrate/primitives/arithmetic", defau
|
||||
|
||||
bridge-hub-common = { path = "../../../../../cumulus/parachains/runtimes/bridge-hubs/common", default-features = false }
|
||||
|
||||
snowbridge-core = { path = "../../primitives/core", features = ["serde"], default-features = false }
|
||||
snowbridge-core = { path = "../../primitives/core", default-features = false, features = ["serde"] }
|
||||
snowbridge-outbound-queue-merkle-tree = { path = "merkle-tree", default-features = false }
|
||||
ethabi = { git = "https://github.com/snowfork/ethabi-decode.git", package = "ethabi-decode", branch = "master", default-features = false }
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ ssz_rs = { version = "0.9.0", default-features = false }
|
||||
ssz_rs_derive = { version = "0.9.0", default-features = false }
|
||||
byte-slice-cast = { version = "1.2.1", default-features = false }
|
||||
|
||||
snowbridge-ethereum = { path = "../../primitives/ethereum", default-features = false }
|
||||
snowbridge-ethereum = { path = "../ethereum", default-features = false }
|
||||
static_assertions = { version = "1.1.0" }
|
||||
milagro_bls = { git = "https://github.com/snowfork/milagro_bls", default-features = false, rev = "a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176" }
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ sp-io = { path = "../../../../../substrate/primitives/io", default-features = fa
|
||||
sp-core = { path = "../../../../../substrate/primitives/core", default-features = false }
|
||||
sp-arithmetic = { path = "../../../../../substrate/primitives/arithmetic", default-features = false }
|
||||
|
||||
snowbridge-beacon-primitives = { path = "../../primitives/beacon", default-features = false }
|
||||
snowbridge-beacon-primitives = { path = "../beacon", default-features = false }
|
||||
|
||||
ethabi = { git = "https://github.com/Snowfork/ethabi-decode.git", package = "ethabi-decode", branch = "master", default-features = false }
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-f
|
||||
xcm-builder = { package = "staging-xcm-builder", path = "../../../../../polkadot/xcm/xcm-builder", default-features = false }
|
||||
xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkadot/xcm/xcm-executor", default-features = false }
|
||||
|
||||
snowbridge-core = { path = "../../primitives/core", default-features = false }
|
||||
snowbridge-core = { path = "../core", default-features = false }
|
||||
|
||||
ethabi = { git = "https://github.com/Snowfork/ethabi-decode.git", package = "ethabi-decode", branch = "master", default-features = false }
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ snowbridge-system-runtime-api = { path = "../../pallets/system/runtime-api", def
|
||||
[dev-dependencies]
|
||||
static_assertions = "1.1"
|
||||
bridge-hub-test-utils = { path = "../../../../../cumulus/parachains/runtimes/bridge-hubs/test-utils" }
|
||||
bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", features = ["integrity-test"] }
|
||||
bridge-runtime-common = { path = "../../../../bin/runtime-common", features = ["integrity-test"] }
|
||||
sp-keyring = { path = "../../../../../substrate/primitives/keyring" }
|
||||
|
||||
[features]
|
||||
|
||||
+2
-6
@@ -27,6 +27,7 @@ use crate::{
|
||||
RuntimeEvent, XcmOverRococoBulletin, XcmRouter,
|
||||
};
|
||||
use bp_messages::LaneId;
|
||||
use bp_runtime::Chain;
|
||||
use bridge_runtime_common::{
|
||||
messages,
|
||||
messages::{
|
||||
@@ -63,7 +64,7 @@ parameter_types! {
|
||||
pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce =
|
||||
bp_polkadot_bulletin::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
|
||||
/// Bridge specific chain (network) identifier of the Rococo Bulletin Chain.
|
||||
pub const RococoBulletinChainId: bp_runtime::ChainId = bp_runtime::POLKADOT_BULLETIN_CHAIN_ID;
|
||||
pub const RococoBulletinChainId: bp_runtime::ChainId = bp_polkadot_bulletin::PolkadotBulletin::ID;
|
||||
/// Interior location (relative to this runtime) of the with-RococoBulletin messages pallet.
|
||||
pub BridgeRococoToRococoBulletinMessagesPalletInstance: InteriorLocation = [
|
||||
PalletInstance(<BridgeRococoBulletinMessages as PalletInfoAccess>::index() as u8)
|
||||
@@ -151,10 +152,6 @@ impl MessageBridge for WithRococoBulletinMessageBridge {
|
||||
type BridgedHeaderChain = BridgeRococoBulletinGrandpa;
|
||||
}
|
||||
|
||||
/// Message verifier for RococoBulletin messages sent from BridgeHubRococo.
|
||||
pub type ToRococoBulletinMessageVerifier =
|
||||
messages::source::FromThisChainMessageVerifier<WithRococoBulletinMessageBridge>;
|
||||
|
||||
/// Maximal outbound payload size of BridgeHubRococo -> RococoBulletin messages.
|
||||
pub type ToRococoBulletinMaximalOutboundPayloadSize =
|
||||
messages::source::FromThisChainMaximalOutboundPayloadSize<WithRococoBulletinMessageBridge>;
|
||||
@@ -205,7 +202,6 @@ impl pallet_bridge_messages::Config<WithRococoBulletinMessagesInstance> for Runt
|
||||
type DeliveryPayments = ();
|
||||
|
||||
type TargetHeaderChain = TargetHeaderChainAdapter<WithRococoBulletinMessageBridge>;
|
||||
type LaneMessageVerifier = ToRococoBulletinMessageVerifier;
|
||||
type DeliveryConfirmationPayments = ();
|
||||
|
||||
type SourceHeaderChain = SourceHeaderChainAdapter<WithRococoBulletinMessageBridge>;
|
||||
|
||||
+3
-7
@@ -26,6 +26,7 @@ use crate::{
|
||||
XcmRouter,
|
||||
};
|
||||
use bp_messages::LaneId;
|
||||
use bp_runtime::Chain;
|
||||
use bridge_runtime_common::{
|
||||
messages,
|
||||
messages::{
|
||||
@@ -57,7 +58,7 @@ parameter_types! {
|
||||
bp_bridge_hub_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
|
||||
pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce =
|
||||
bp_bridge_hub_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
|
||||
pub const BridgeHubWestendChainId: bp_runtime::ChainId = bp_runtime::BRIDGE_HUB_WESTEND_CHAIN_ID;
|
||||
pub const BridgeHubWestendChainId: bp_runtime::ChainId = BridgeHubWestend::ID;
|
||||
pub BridgeRococoToWestendMessagesPalletInstance: InteriorLocation = [PalletInstance(<BridgeWestendMessages as PalletInfoAccess>::index() as u8)].into();
|
||||
pub WestendGlobalConsensusNetwork: NetworkId = NetworkId::Westend;
|
||||
pub WestendGlobalConsensusNetworkLocation: Location = Location::new(
|
||||
@@ -157,10 +158,6 @@ impl MessageBridge for WithBridgeHubWestendMessageBridge {
|
||||
>;
|
||||
}
|
||||
|
||||
/// Message verifier for BridgeHubWestend messages sent from BridgeHubRococo
|
||||
pub type ToBridgeHubWestendMessageVerifier =
|
||||
messages::source::FromThisChainMessageVerifier<WithBridgeHubWestendMessageBridge>;
|
||||
|
||||
/// Maximal outbound payload size of BridgeHubRococo -> BridgeHubWestend messages.
|
||||
pub type ToBridgeHubWestendMaximalOutboundPayloadSize =
|
||||
messages::source::FromThisChainMaximalOutboundPayloadSize<WithBridgeHubWestendMessageBridge>;
|
||||
@@ -212,7 +209,6 @@ impl pallet_bridge_messages::Config<WithBridgeHubWestendMessagesInstance> for Ru
|
||||
type DeliveryPayments = ();
|
||||
|
||||
type TargetHeaderChain = TargetHeaderChainAdapter<WithBridgeHubWestendMessageBridge>;
|
||||
type LaneMessageVerifier = ToBridgeHubWestendMessageVerifier;
|
||||
type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter<
|
||||
Runtime,
|
||||
WithBridgeHubWestendMessagesInstance,
|
||||
@@ -309,7 +305,7 @@ mod tests {
|
||||
bp_bridge_hub_westend::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
|
||||
max_unconfirmed_messages_in_bridged_confirmation_tx:
|
||||
bp_bridge_hub_westend::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
|
||||
bridged_chain_id: bp_runtime::BRIDGE_HUB_WESTEND_CHAIN_ID,
|
||||
bridged_chain_id: BridgeHubWestend::ID,
|
||||
},
|
||||
pallet_names: AssertBridgePalletNames {
|
||||
with_this_chain_messages_pallet_name:
|
||||
|
||||
@@ -70,6 +70,8 @@ use frame_system::{
|
||||
EnsureRoot,
|
||||
};
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
use bp_runtime::Chain;
|
||||
use bp_runtime::HeaderId;
|
||||
use bridge_hub_common::{
|
||||
message_queue::{NarrowOriginToSibling, ParaIdToSibling},
|
||||
@@ -1275,7 +1277,7 @@ impl_runtime_apis! {
|
||||
impl BridgeMessagesConfig<bridge_to_westend_config::WithBridgeHubWestendMessagesInstance> for Runtime {
|
||||
fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool {
|
||||
let bench_lane_id = <Self as BridgeMessagesConfig<bridge_to_westend_config::WithBridgeHubWestendMessagesInstance>>::bench_lane_id();
|
||||
let bridged_chain_id = bp_runtime::BRIDGE_HUB_WESTEND_CHAIN_ID;
|
||||
let bridged_chain_id = bp_bridge_hub_westend::BridgeHubWestend::ID;
|
||||
pallet_bridge_relayers::Pallet::<Runtime>::relayer_reward(
|
||||
relayer,
|
||||
bp_relayers::RewardsAccountParams::new(
|
||||
|
||||
+3
-7
@@ -23,6 +23,7 @@ use crate::{
|
||||
};
|
||||
use bp_messages::LaneId;
|
||||
use bp_parachains::SingleParaStoredHeaderDataBuilder;
|
||||
use bp_runtime::Chain;
|
||||
use bridge_runtime_common::{
|
||||
messages,
|
||||
messages::{
|
||||
@@ -62,7 +63,7 @@ parameter_types! {
|
||||
bp_bridge_hub_westend::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
|
||||
pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce =
|
||||
bp_bridge_hub_westend::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
|
||||
pub const BridgeHubRococoChainId: bp_runtime::ChainId = bp_runtime::BRIDGE_HUB_ROCOCO_CHAIN_ID;
|
||||
pub const BridgeHubRococoChainId: bp_runtime::ChainId = BridgeHubRococo::ID;
|
||||
pub BridgeWestendToRococoMessagesPalletInstance: InteriorLocation = [PalletInstance(<BridgeRococoMessages as PalletInfoAccess>::index() as u8)].into();
|
||||
pub RococoGlobalConsensusNetwork: NetworkId = NetworkId::Rococo;
|
||||
pub RococoGlobalConsensusNetworkLocation: Location = Location::new(
|
||||
@@ -162,10 +163,6 @@ impl MessageBridge for WithBridgeHubRococoMessageBridge {
|
||||
>;
|
||||
}
|
||||
|
||||
/// Message verifier for BridgeHubRococo messages sent from BridgeHubWestend
|
||||
type ToBridgeHubRococoMessageVerifier =
|
||||
messages::source::FromThisChainMessageVerifier<WithBridgeHubRococoMessageBridge>;
|
||||
|
||||
/// Maximal outbound payload size of BridgeHubWestend -> BridgeHubRococo messages.
|
||||
type ToBridgeHubRococoMaximalOutboundPayloadSize =
|
||||
messages::source::FromThisChainMaximalOutboundPayloadSize<WithBridgeHubRococoMessageBridge>;
|
||||
@@ -249,7 +246,6 @@ impl pallet_bridge_messages::Config<WithBridgeHubRococoMessagesInstance> for Run
|
||||
type DeliveryPayments = ();
|
||||
|
||||
type TargetHeaderChain = TargetHeaderChainAdapter<WithBridgeHubRococoMessageBridge>;
|
||||
type LaneMessageVerifier = ToBridgeHubRococoMessageVerifier;
|
||||
type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter<
|
||||
Runtime,
|
||||
WithBridgeHubRococoMessagesInstance,
|
||||
@@ -344,7 +340,7 @@ mod tests {
|
||||
bp_bridge_hub_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
|
||||
max_unconfirmed_messages_in_bridged_confirmation_tx:
|
||||
bp_bridge_hub_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
|
||||
bridged_chain_id: bp_runtime::BRIDGE_HUB_ROCOCO_CHAIN_ID,
|
||||
bridged_chain_id: BridgeHubRococo::ID,
|
||||
},
|
||||
pallet_names: AssertBridgePalletNames {
|
||||
with_this_chain_messages_pallet_name:
|
||||
|
||||
@@ -69,6 +69,8 @@ pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
|
||||
pub use sp_runtime::{MultiAddress, Perbill, Permill};
|
||||
use xcm_config::{XcmOriginToTransactDispatchOrigin, XcmRouter};
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
use bp_runtime::Chain;
|
||||
use bp_runtime::HeaderId;
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
@@ -974,7 +976,7 @@ impl_runtime_apis! {
|
||||
impl BridgeMessagesConfig<bridge_to_rococo_config::WithBridgeHubRococoMessagesInstance> for Runtime {
|
||||
fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool {
|
||||
let bench_lane_id = <Self as BridgeMessagesConfig<bridge_to_rococo_config::WithBridgeHubRococoMessagesInstance>>::bench_lane_id();
|
||||
let bridged_chain_id = bp_runtime::BRIDGE_HUB_ROCOCO_CHAIN_ID;
|
||||
let bridged_chain_id = bp_bridge_hub_rococo::BridgeHubRococo::ID;
|
||||
pallet_bridge_relayers::Pallet::<Runtime>::relayer_reward(
|
||||
relayer,
|
||||
bp_relayers::RewardsAccountParams::new(
|
||||
|
||||
Reference in New Issue
Block a user