mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 21:01:02 +00:00
Move pallet-bridge-dispatch types to primitives (#948)
* message dispatch support multiple instances * Move pallet-bridge-dispatch types to primitives * remove pallet-bridge-dispatch dependency * Update cargo.lock (remove pallet-bridge-dispatch in substrate-relay) * remove extra dependencies
This commit is contained in:
@@ -889,7 +889,7 @@ impl_runtime_apis! {
|
|||||||
params: MessageParams<Self::AccountId>,
|
params: MessageParams<Self::AccountId>,
|
||||||
) -> (millau_messages::ToMillauMessagePayload, Balance) {
|
) -> (millau_messages::ToMillauMessagePayload, Balance) {
|
||||||
let message_payload = vec![0; params.size as usize];
|
let message_payload = vec![0; params.size as usize];
|
||||||
let dispatch_origin = pallet_bridge_dispatch::CallOrigin::SourceAccount(
|
let dispatch_origin = bp_message_dispatch::CallOrigin::SourceAccount(
|
||||||
params.sender_account,
|
params.sender_account,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -959,10 +959,10 @@ impl_runtime_apis! {
|
|||||||
make_millau_outbound_lane_data_key,
|
make_millau_outbound_lane_data_key,
|
||||||
make_millau_header,
|
make_millau_header,
|
||||||
call_weight,
|
call_weight,
|
||||||
pallet_bridge_dispatch::MessagePayload {
|
bp_message_dispatch::MessagePayload {
|
||||||
spec_version: VERSION.spec_version,
|
spec_version: VERSION.spec_version,
|
||||||
weight: call_weight,
|
weight: call_weight,
|
||||||
origin: pallet_bridge_dispatch::CallOrigin::<
|
origin: bp_message_dispatch::CallOrigin::<
|
||||||
bp_millau::AccountId,
|
bp_millau::AccountId,
|
||||||
MultiSigner,
|
MultiSigner,
|
||||||
Signature,
|
Signature,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ messages module into your runtime. Basic prerequisites of these helpers are:
|
|||||||
- all message lanes are identical and may be used to transfer the same messages;
|
- all message lanes are identical and may be used to transfer the same messages;
|
||||||
- the messages sent over the bridge are dispatched using
|
- the messages sent over the bridge are dispatched using
|
||||||
[call dispatch module](../../modules/dispatch/README.md);
|
[call dispatch module](../../modules/dispatch/README.md);
|
||||||
- the messages are `pallet_bridge_dispatch::MessagePayload` structures, where `call` field is
|
- the messages are `bp_message_dispatch::MessagePayload` structures, where `call` field is
|
||||||
encoded `Call` of the target chain. This means that the `Call` is opaque to the
|
encoded `Call` of the target chain. This means that the `Call` is opaque to the
|
||||||
[messages module](../../modules/messages/README.md) instance at the source chain.
|
[messages module](../../modules/messages/README.md) instance at the source chain.
|
||||||
It is pre-encoded by the message submitter;
|
It is pre-encoded by the message submitter;
|
||||||
@@ -118,7 +118,7 @@ are: `maximal_message_size`, `verify_chain_message`, `verify_messages_delivery_p
|
|||||||
`estimate_message_dispatch_and_delivery_fee`.
|
`estimate_message_dispatch_and_delivery_fee`.
|
||||||
|
|
||||||
`FromThisChainMessagePayload` is a message that the sender sends through our bridge. It is the
|
`FromThisChainMessagePayload` is a message that the sender sends through our bridge. It is the
|
||||||
`pallet_bridge_dispatch::MessagePayload`, where `call` field is encoded target chain call. So
|
`bp_message_dispatch::MessagePayload`, where `call` field is encoded target chain call. So
|
||||||
at this chain we don't see internals of this call - we just know its size.
|
at this chain we don't see internals of this call - we just know its size.
|
||||||
|
|
||||||
`FromThisChainMessageVerifier` is an implementation of `bp_messages::LaneMessageVerifier`. It
|
`FromThisChainMessageVerifier` is an implementation of `bp_messages::LaneMessageVerifier`. It
|
||||||
@@ -131,8 +131,8 @@ has following checks in its `verify_message` method:
|
|||||||
|
|
||||||
1. it'll reject a message if it has the wrong dispatch origin declared. Like if the submitter is not
|
1. it'll reject a message if it has the wrong dispatch origin declared. Like if the submitter is not
|
||||||
the root of this chain, but it tries to dispatch the message at the target chain using
|
the root of this chain, but it tries to dispatch the message at the target chain using
|
||||||
`pallet_bridge_dispatch::CallOrigin::SourceRoot` origin. Or he has provided wrong signature
|
`bp_message_dispatch::CallOrigin::SourceRoot` origin. Or he has provided wrong signature
|
||||||
in the `pallet_bridge_dispatch::CallOrigin::TargetAccount` origin;
|
in the `bp_message_dispatch::CallOrigin::TargetAccount` origin;
|
||||||
|
|
||||||
1. it'll reject a message if the delivery and dispatch fee that the submitter wants to pay is lesser
|
1. it'll reject a message if the delivery and dispatch fee that the submitter wants to pay is lesser
|
||||||
than the fee that is computed using the `estimate_message_dispatch_and_delivery_fee` function.
|
than the fee that is computed using the `estimate_message_dispatch_and_delivery_fee` function.
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ pub mod source {
|
|||||||
pub type BridgedChainOpaqueCall = Vec<u8>;
|
pub type BridgedChainOpaqueCall = Vec<u8>;
|
||||||
|
|
||||||
/// Message payload for This -> Bridged chain messages.
|
/// Message payload for This -> Bridged chain messages.
|
||||||
pub type FromThisChainMessagePayload<B> = pallet_bridge_dispatch::MessagePayload<
|
pub type FromThisChainMessagePayload<B> = bp_message_dispatch::MessagePayload<
|
||||||
AccountIdOf<ThisChain<B>>,
|
AccountIdOf<ThisChain<B>>,
|
||||||
SignerOf<BridgedChain<B>>,
|
SignerOf<BridgedChain<B>>,
|
||||||
SignatureOf<BridgedChain<B>>,
|
SignatureOf<BridgedChain<B>>,
|
||||||
@@ -395,14 +395,14 @@ pub mod target {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// Call origin for Bridged -> This chain messages.
|
/// Call origin for Bridged -> This chain messages.
|
||||||
pub type FromBridgedChainMessageCallOrigin<B> = pallet_bridge_dispatch::CallOrigin<
|
pub type FromBridgedChainMessageCallOrigin<B> = bp_message_dispatch::CallOrigin<
|
||||||
AccountIdOf<BridgedChain<B>>,
|
AccountIdOf<BridgedChain<B>>,
|
||||||
SignerOf<ThisChain<B>>,
|
SignerOf<ThisChain<B>>,
|
||||||
SignatureOf<ThisChain<B>>,
|
SignatureOf<ThisChain<B>>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/// Decoded Bridged -> This message payload.
|
/// Decoded Bridged -> This message payload.
|
||||||
pub type FromBridgedChainMessagePayload<B> = pallet_bridge_dispatch::MessagePayload<
|
pub type FromBridgedChainMessagePayload<B> = bp_message_dispatch::MessagePayload<
|
||||||
AccountIdOf<BridgedChain<B>>,
|
AccountIdOf<BridgedChain<B>>,
|
||||||
SignerOf<ThisChain<B>>,
|
SignerOf<ThisChain<B>>,
|
||||||
SignatureOf<ThisChain<B>>,
|
SignatureOf<ThisChain<B>>,
|
||||||
@@ -931,7 +931,7 @@ mod tests {
|
|||||||
let message_on_bridged_chain = source::FromThisChainMessagePayload::<OnBridgedChainBridge> {
|
let message_on_bridged_chain = source::FromThisChainMessagePayload::<OnBridgedChainBridge> {
|
||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: 100,
|
weight: 100,
|
||||||
origin: pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
call: ThisChainCall::Transfer.encode(),
|
call: ThisChainCall::Transfer.encode(),
|
||||||
}
|
}
|
||||||
.encode();
|
.encode();
|
||||||
@@ -945,7 +945,7 @@ mod tests {
|
|||||||
target::FromBridgedChainMessagePayload::<OnThisChainBridge> {
|
target::FromBridgedChainMessagePayload::<OnThisChainBridge> {
|
||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: 100,
|
weight: 100,
|
||||||
origin: pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
call: target::FromBridgedChainEncodedMessageCall::<OnThisChainBridge> {
|
call: target::FromBridgedChainEncodedMessageCall::<OnThisChainBridge> {
|
||||||
encoded_call: ThisChainCall::Transfer.encode(),
|
encoded_call: ThisChainCall::Transfer.encode(),
|
||||||
_marker: PhantomData::default(),
|
_marker: PhantomData::default(),
|
||||||
@@ -962,7 +962,7 @@ mod tests {
|
|||||||
source::FromThisChainMessagePayload::<OnThisChainBridge> {
|
source::FromThisChainMessagePayload::<OnThisChainBridge> {
|
||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: 100,
|
weight: 100,
|
||||||
origin: pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
call: vec![42],
|
call: vec![42],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1012,7 +1012,7 @@ mod tests {
|
|||||||
let payload = source::FromThisChainMessagePayload::<OnThisChainBridge> {
|
let payload = source::FromThisChainMessagePayload::<OnThisChainBridge> {
|
||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: 100,
|
weight: 100,
|
||||||
origin: pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
call: vec![42],
|
call: vec![42],
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1055,7 +1055,7 @@ mod tests {
|
|||||||
let payload = source::FromThisChainMessagePayload::<OnThisChainBridge> {
|
let payload = source::FromThisChainMessagePayload::<OnThisChainBridge> {
|
||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: 100,
|
weight: 100,
|
||||||
origin: pallet_bridge_dispatch::CallOrigin::SourceAccount(ThisChainAccountId(1)),
|
origin: bp_message_dispatch::CallOrigin::SourceAccount(ThisChainAccountId(1)),
|
||||||
call: vec![42],
|
call: vec![42],
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1122,7 +1122,7 @@ mod tests {
|
|||||||
> {
|
> {
|
||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: 5,
|
weight: 5,
|
||||||
origin: pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
call: vec![1, 2, 3, 4, 5, 6],
|
call: vec![1, 2, 3, 4, 5, 6],
|
||||||
},)
|
},)
|
||||||
.is_err()
|
.is_err()
|
||||||
@@ -1137,7 +1137,7 @@ mod tests {
|
|||||||
> {
|
> {
|
||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + 1,
|
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + 1,
|
||||||
origin: pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
call: vec![1, 2, 3, 4, 5, 6],
|
call: vec![1, 2, 3, 4, 5, 6],
|
||||||
},)
|
},)
|
||||||
.is_err()
|
.is_err()
|
||||||
@@ -1152,7 +1152,7 @@ mod tests {
|
|||||||
> {
|
> {
|
||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT,
|
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT,
|
||||||
origin: pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
call: vec![0; source::maximal_message_size::<OnThisChainBridge>() as usize + 1],
|
call: vec![0; source::maximal_message_size::<OnThisChainBridge>() as usize + 1],
|
||||||
},)
|
},)
|
||||||
.is_err()
|
.is_err()
|
||||||
@@ -1167,7 +1167,7 @@ mod tests {
|
|||||||
> {
|
> {
|
||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT,
|
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT,
|
||||||
origin: pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
call: vec![0; source::maximal_message_size::<OnThisChainBridge>() as _],
|
call: vec![0; source::maximal_message_size::<OnThisChainBridge>() as _],
|
||||||
},),
|
},),
|
||||||
Ok(()),
|
Ok(()),
|
||||||
|
|||||||
@@ -172,6 +172,6 @@ source chain needs to prove ownership of this account by using their target chai
|
|||||||
sign: `(Call, SourceChainAccountId).encode()`. This will be included in the message payload and
|
sign: `(Call, SourceChainAccountId).encode()`. This will be included in the message payload and
|
||||||
verified by the target chain before dispatch.
|
verified by the target chain before dispatch.
|
||||||
|
|
||||||
See [`CallOrigin` documentation](../modules/dispatch/src/lib.rs) for more details.
|
See [`CallOrigin` documentation](../primitives/message-dispatch/src/lib.rs) for more details.
|
||||||
|
|
||||||
#### Message Relayers Strategy
|
#### Message Relayers Strategy
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Every message that is being dispatched has three main characteristics:
|
|||||||
- `id` is the unique id of the message within the given bridge. For messages coming from the
|
- `id` is the unique id of the message within the given bridge. For messages coming from the
|
||||||
[messages module](../messages/README.md), it may worth to use a tuple
|
[messages module](../messages/README.md), it may worth to use a tuple
|
||||||
`(LaneId, MessageNonce)` to identify a message;
|
`(LaneId, MessageNonce)` to identify a message;
|
||||||
- `message` is the `pallet_bridge_dispatch::MessagePayload` structure. The `call` field is set
|
- `message` is the `bp_message_dispatch::MessagePayload` structure. The `call` field is set
|
||||||
to the (potentially) encoded `Call` of this chain.
|
to the (potentially) encoded `Call` of this chain.
|
||||||
|
|
||||||
The easiest way to understand what is happening when a `Call` is being dispatched, is to look at the
|
The easiest way to understand what is happening when a `Call` is being dispatched, is to look at the
|
||||||
@@ -33,7 +33,7 @@ module events set:
|
|||||||
chain storage has been corrupted. The `Call` is decoded after `spec_version` check, so we'll never
|
chain storage has been corrupted. The `Call` is decoded after `spec_version` check, so we'll never
|
||||||
try to decode `Call` from other runtime version;
|
try to decode `Call` from other runtime version;
|
||||||
- `MessageSignatureMismatch` event is emitted if submitter has chose to dispatch message using
|
- `MessageSignatureMismatch` event is emitted if submitter has chose to dispatch message using
|
||||||
specified this chain account (`pallet_bridge_dispatch::CallOrigin::TargetAccount` origin),
|
specified this chain account (`bp_message_dispatch::CallOrigin::TargetAccount` origin),
|
||||||
but he has failed to prove that he owns the private key for this account;
|
but he has failed to prove that he owns the private key for this account;
|
||||||
- `MessageCallRejected` event is emitted if the module has been deployed with some call filter and
|
- `MessageCallRejected` event is emitted if the module has been deployed with some call filter and
|
||||||
this filter has rejected the `Call`. In your bridge you may choose to reject all messages except
|
this filter has rejected the `Call`. In your bridge you may choose to reject all messages except
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
use bp_message_dispatch::{MessageDispatch, Weight};
|
use bp_message_dispatch::{CallOrigin, MessageDispatch, MessagePayload, SpecVersion, Weight};
|
||||||
use bp_runtime::{derive_account_id, InstanceId, Size, SourceAccount};
|
use bp_runtime::{derive_account_id, InstanceId, SourceAccount};
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
decl_event, decl_module, decl_storage,
|
decl_event, decl_module, decl_storage,
|
||||||
@@ -33,7 +33,6 @@ use frame_support::{
|
|||||||
ensure,
|
ensure,
|
||||||
traits::{Filter, Get},
|
traits::{Filter, Get},
|
||||||
weights::{extract_actual_weight, GetDispatchInfo},
|
weights::{extract_actual_weight, GetDispatchInfo},
|
||||||
RuntimeDebug,
|
|
||||||
};
|
};
|
||||||
use frame_system::RawOrigin;
|
use frame_system::RawOrigin;
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
@@ -42,78 +41,6 @@ use sp_runtime::{
|
|||||||
};
|
};
|
||||||
use sp_std::{fmt::Debug, marker::PhantomData, prelude::*};
|
use sp_std::{fmt::Debug, marker::PhantomData, prelude::*};
|
||||||
|
|
||||||
/// Spec version type.
|
|
||||||
pub type SpecVersion = u32;
|
|
||||||
|
|
||||||
// TODO [#895] move to primitives
|
|
||||||
/// Origin of a Call when it is dispatched on the target chain.
|
|
||||||
///
|
|
||||||
/// The source chain can (and should) verify that the message can be dispatched on the target chain
|
|
||||||
/// with a particular origin given the source chain's origin. This can be done with the
|
|
||||||
/// `verify_message_origin()` function.
|
|
||||||
#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)]
|
|
||||||
pub enum CallOrigin<SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature> {
|
|
||||||
/// Call is sent by the Root origin on the source chain. On the target chain it is dispatched
|
|
||||||
/// from a derived account.
|
|
||||||
///
|
|
||||||
/// The derived account represents the source Root account on the target chain. This is useful
|
|
||||||
/// if the target chain needs some way of knowing that a call came from a priviledged origin on
|
|
||||||
/// the source chain (maybe to allow a configuration change for example).
|
|
||||||
SourceRoot,
|
|
||||||
|
|
||||||
/// Call is sent by `SourceChainAccountId` on the source chain. On the target chain it is
|
|
||||||
/// dispatched from an account controlled by a private key on the target chain.
|
|
||||||
///
|
|
||||||
/// The account can be identified by `TargetChainAccountPublic`. The proof that the
|
|
||||||
/// `SourceChainAccountId` controls `TargetChainAccountPublic` is the `TargetChainSignature`
|
|
||||||
/// over `(Call, SourceChainAccountId, TargetChainSpecVersion, SourceChainBridgeId).encode()`.
|
|
||||||
///
|
|
||||||
/// NOTE sending messages using this origin (or any other) does not have replay protection!
|
|
||||||
/// The assumption is that both the source account and the target account is controlled by
|
|
||||||
/// the same entity, so source-chain replay protection is sufficient.
|
|
||||||
/// As a consequence, it's extremely important for the target chain user to never produce
|
|
||||||
/// a signature with their target-private key on something that could be sent over the bridge,
|
|
||||||
/// i.e. if the target user signs `(<some-source-account-id>, Call::Transfer(X, 5))`
|
|
||||||
/// The owner of `some-source-account-id` can send that message multiple times, which would
|
|
||||||
/// result with multiple transfer calls being dispatched on the target chain.
|
|
||||||
/// So please, NEVER USE YOUR PRIVATE KEY TO SIGN SOMETHING YOU DON'T FULLY UNDERSTAND!
|
|
||||||
TargetAccount(SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature),
|
|
||||||
|
|
||||||
/// Call is sent by the `SourceChainAccountId` on the source chain. On the target chain it is
|
|
||||||
/// dispatched from a derived account ID.
|
|
||||||
///
|
|
||||||
/// The account ID on the target chain is derived from the source account ID This is useful if
|
|
||||||
/// you need a way to represent foreign accounts on this chain for call dispatch purposes.
|
|
||||||
///
|
|
||||||
/// Note that the derived account does not need to have a private key on the target chain. This
|
|
||||||
/// origin can therefore represent proxies, pallets, etc. as well as "regular" accounts.
|
|
||||||
SourceAccount(SourceChainAccountId),
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO [#895] move to primitives
|
|
||||||
/// Message payload type used by dispatch module.
|
|
||||||
#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)]
|
|
||||||
pub struct MessagePayload<SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature, Call> {
|
|
||||||
/// Runtime specification version. We only dispatch messages that have the same
|
|
||||||
/// runtime version. Otherwise we risk to misinterpret encoded calls.
|
|
||||||
pub spec_version: SpecVersion,
|
|
||||||
/// Weight of the call, declared by the message sender. If it is less than actual
|
|
||||||
/// static weight, the call is not dispatched.
|
|
||||||
pub weight: Weight,
|
|
||||||
/// Call origin to be used during dispatch.
|
|
||||||
pub origin: CallOrigin<SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature>,
|
|
||||||
/// The call itself.
|
|
||||||
pub call: Call,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature> Size
|
|
||||||
for MessagePayload<SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature, Vec<u8>>
|
|
||||||
{
|
|
||||||
fn size_hint(&self) -> u32 {
|
|
||||||
self.call.len() as _
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The module configuration trait.
|
/// The module configuration trait.
|
||||||
pub trait Config<I = DefaultInstance>: frame_system::Config {
|
pub trait Config<I = DefaultInstance>: frame_system::Config {
|
||||||
/// The overarching event type.
|
/// The overarching event type.
|
||||||
|
|||||||
@@ -10,9 +10,16 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
|||||||
bp-runtime = { path = "../runtime", default-features = false }
|
bp-runtime = { path = "../runtime", default-features = false }
|
||||||
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
|
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
|
||||||
|
|
||||||
|
# Substrate Dependencies
|
||||||
|
|
||||||
|
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||||
|
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = [
|
std = [
|
||||||
"bp-runtime/std",
|
"bp-runtime/std",
|
||||||
"codec/std",
|
"codec/std",
|
||||||
|
"frame-support/std",
|
||||||
|
"sp-std/std",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -19,11 +19,17 @@
|
|||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
use bp_runtime::InstanceId;
|
use bp_runtime::{InstanceId, Size};
|
||||||
|
use codec::{Decode, Encode};
|
||||||
|
use frame_support::RuntimeDebug;
|
||||||
|
use sp_std::prelude::*;
|
||||||
|
|
||||||
/// Message dispatch weight.
|
/// Message dispatch weight.
|
||||||
pub type Weight = u64;
|
pub type Weight = u64;
|
||||||
|
|
||||||
|
/// Spec version type.
|
||||||
|
pub type SpecVersion = u32;
|
||||||
|
|
||||||
/// A generic trait to dispatch arbitrary messages delivered over the bridge.
|
/// A generic trait to dispatch arbitrary messages delivered over the bridge.
|
||||||
pub trait MessageDispatch<MessageId> {
|
pub trait MessageDispatch<MessageId> {
|
||||||
/// A type of the message to be dispatched.
|
/// A type of the message to be dispatched.
|
||||||
@@ -47,3 +53,70 @@ pub trait MessageDispatch<MessageId> {
|
|||||||
/// the whole message).
|
/// the whole message).
|
||||||
fn dispatch(bridge: InstanceId, id: MessageId, message: Result<Self::Message, ()>);
|
fn dispatch(bridge: InstanceId, id: MessageId, message: Result<Self::Message, ()>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Origin of a Call when it is dispatched on the target chain.
|
||||||
|
///
|
||||||
|
/// The source chain can (and should) verify that the message can be dispatched on the target chain
|
||||||
|
/// with a particular origin given the source chain's origin. This can be done with the
|
||||||
|
/// `verify_message_origin()` function.
|
||||||
|
#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)]
|
||||||
|
pub enum CallOrigin<SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature> {
|
||||||
|
/// Call is sent by the Root origin on the source chain. On the target chain it is dispatched
|
||||||
|
/// from a derived account.
|
||||||
|
///
|
||||||
|
/// The derived account represents the source Root account on the target chain. This is useful
|
||||||
|
/// if the target chain needs some way of knowing that a call came from a priviledged origin on
|
||||||
|
/// the source chain (maybe to allow a configuration change for example).
|
||||||
|
SourceRoot,
|
||||||
|
|
||||||
|
/// Call is sent by `SourceChainAccountId` on the source chain. On the target chain it is
|
||||||
|
/// dispatched from an account controlled by a private key on the target chain.
|
||||||
|
///
|
||||||
|
/// The account can be identified by `TargetChainAccountPublic`. The proof that the
|
||||||
|
/// `SourceChainAccountId` controls `TargetChainAccountPublic` is the `TargetChainSignature`
|
||||||
|
/// over `(Call, SourceChainAccountId, TargetChainSpecVersion, SourceChainBridgeId).encode()`.
|
||||||
|
///
|
||||||
|
/// NOTE sending messages using this origin (or any other) does not have replay protection!
|
||||||
|
/// The assumption is that both the source account and the target account is controlled by
|
||||||
|
/// the same entity, so source-chain replay protection is sufficient.
|
||||||
|
/// As a consequence, it's extremely important for the target chain user to never produce
|
||||||
|
/// a signature with their target-private key on something that could be sent over the bridge,
|
||||||
|
/// i.e. if the target user signs `(<some-source-account-id>, Call::Transfer(X, 5))`
|
||||||
|
/// The owner of `some-source-account-id` can send that message multiple times, which would
|
||||||
|
/// result with multiple transfer calls being dispatched on the target chain.
|
||||||
|
/// So please, NEVER USE YOUR PRIVATE KEY TO SIGN SOMETHING YOU DON'T FULLY UNDERSTAND!
|
||||||
|
TargetAccount(SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature),
|
||||||
|
|
||||||
|
/// Call is sent by the `SourceChainAccountId` on the source chain. On the target chain it is
|
||||||
|
/// dispatched from a derived account ID.
|
||||||
|
///
|
||||||
|
/// The account ID on the target chain is derived from the source account ID This is useful if
|
||||||
|
/// you need a way to represent foreign accounts on this chain for call dispatch purposes.
|
||||||
|
///
|
||||||
|
/// Note that the derived account does not need to have a private key on the target chain. This
|
||||||
|
/// origin can therefore represent proxies, pallets, etc. as well as "regular" accounts.
|
||||||
|
SourceAccount(SourceChainAccountId),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Message payload type used by dispatch module.
|
||||||
|
#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)]
|
||||||
|
pub struct MessagePayload<SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature, Call> {
|
||||||
|
/// Runtime specification version. We only dispatch messages that have the same
|
||||||
|
/// runtime version. Otherwise we risk to misinterpret encoded calls.
|
||||||
|
pub spec_version: SpecVersion,
|
||||||
|
/// Weight of the call, declared by the message sender. If it is less than actual
|
||||||
|
/// static weight, the call is not dispatched.
|
||||||
|
pub weight: Weight,
|
||||||
|
/// Call origin to be used during dispatch.
|
||||||
|
pub origin: CallOrigin<SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature>,
|
||||||
|
/// The call itself.
|
||||||
|
pub call: Call,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature> Size
|
||||||
|
for MessagePayload<SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature, Vec<u8>>
|
||||||
|
{
|
||||||
|
fn size_hint(&self) -> u32 {
|
||||||
|
self.call.len() as _
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ structopt = "0.3"
|
|||||||
bp-header-chain = { path = "../../primitives/header-chain" }
|
bp-header-chain = { path = "../../primitives/header-chain" }
|
||||||
bp-kusama = { path = "../../primitives/chain-kusama" }
|
bp-kusama = { path = "../../primitives/chain-kusama" }
|
||||||
bp-messages = { path = "../../primitives/messages" }
|
bp-messages = { path = "../../primitives/messages" }
|
||||||
|
bp-message-dispatch = { path = "../../primitives/message-dispatch" }
|
||||||
bp-millau = { path = "../../primitives/chain-millau" }
|
bp-millau = { path = "../../primitives/chain-millau" }
|
||||||
bp-polkadot = { path = "../../primitives/chain-polkadot" }
|
bp-polkadot = { path = "../../primitives/chain-polkadot" }
|
||||||
bp-rialto = { path = "../../primitives/chain-rialto" }
|
bp-rialto = { path = "../../primitives/chain-rialto" }
|
||||||
@@ -36,7 +37,6 @@ finality-relay = { path = "../finality" }
|
|||||||
headers-relay = { path = "../headers" }
|
headers-relay = { path = "../headers" }
|
||||||
messages-relay = { path = "../messages" }
|
messages-relay = { path = "../messages" }
|
||||||
millau-runtime = { path = "../../bin/millau/runtime" }
|
millau-runtime = { path = "../../bin/millau/runtime" }
|
||||||
pallet-bridge-dispatch = { path = "../../modules/dispatch" }
|
|
||||||
pallet-bridge-messages = { path = "../../modules/messages" }
|
pallet-bridge-messages = { path = "../../modules/messages" }
|
||||||
relay-kusama-client = { path = "../client-kusama" }
|
relay-kusama-client = { path = "../client-kusama" }
|
||||||
relay-millau-client = { path = "../client-millau" }
|
relay-millau-client = { path = "../client-millau" }
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ use crate::cli::{
|
|||||||
encode_call::{self, Call, CliEncodeCall},
|
encode_call::{self, Call, CliEncodeCall},
|
||||||
encode_message, send_message, CliChain,
|
encode_message, send_message, CliChain,
|
||||||
};
|
};
|
||||||
|
use bp_message_dispatch::{CallOrigin, MessagePayload};
|
||||||
use codec::Decode;
|
use codec::Decode;
|
||||||
use frame_support::weights::{GetDispatchInfo, Weight};
|
use frame_support::weights::{GetDispatchInfo, Weight};
|
||||||
use pallet_bridge_dispatch::{CallOrigin, MessagePayload};
|
|
||||||
use relay_millau_client::Millau;
|
use relay_millau_client::Millau;
|
||||||
use sp_version::RuntimeVersion;
|
use sp_version::RuntimeVersion;
|
||||||
|
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ mod tests {
|
|||||||
let payload = send_message::message_payload(
|
let payload = send_message::message_payload(
|
||||||
Default::default(),
|
Default::default(),
|
||||||
call.get_dispatch_info().weight,
|
call.get_dispatch_info().weight,
|
||||||
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
&call,
|
&call,
|
||||||
);
|
);
|
||||||
assert_eq!(Millau::verify_message(&payload), Ok(()));
|
assert_eq!(Millau::verify_message(&payload), Ok(()));
|
||||||
@@ -142,7 +142,7 @@ mod tests {
|
|||||||
let payload = send_message::message_payload(
|
let payload = send_message::message_payload(
|
||||||
Default::default(),
|
Default::default(),
|
||||||
call.get_dispatch_info().weight,
|
call.get_dispatch_info().weight,
|
||||||
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
&call,
|
&call,
|
||||||
);
|
);
|
||||||
assert!(Millau::verify_message(&payload).is_err());
|
assert!(Millau::verify_message(&payload).is_err());
|
||||||
@@ -169,7 +169,7 @@ mod tests {
|
|||||||
let payload = send_message::message_payload(
|
let payload = send_message::message_payload(
|
||||||
Default::default(),
|
Default::default(),
|
||||||
maximal_dispatch_weight,
|
maximal_dispatch_weight,
|
||||||
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
&call,
|
&call,
|
||||||
);
|
);
|
||||||
assert_eq!(Millau::verify_message(&payload), Ok(()));
|
assert_eq!(Millau::verify_message(&payload), Ok(()));
|
||||||
@@ -177,7 +177,7 @@ mod tests {
|
|||||||
let payload = send_message::message_payload(
|
let payload = send_message::message_payload(
|
||||||
Default::default(),
|
Default::default(),
|
||||||
maximal_dispatch_weight + 1,
|
maximal_dispatch_weight + 1,
|
||||||
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
&call,
|
&call,
|
||||||
);
|
);
|
||||||
assert!(Millau::verify_message(&payload).is_err());
|
assert!(Millau::verify_message(&payload).is_err());
|
||||||
@@ -194,7 +194,7 @@ mod tests {
|
|||||||
let payload = send_message::message_payload(
|
let payload = send_message::message_payload(
|
||||||
Default::default(),
|
Default::default(),
|
||||||
maximal_dispatch_weight,
|
maximal_dispatch_weight,
|
||||||
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
&call,
|
&call,
|
||||||
);
|
);
|
||||||
assert_eq!(Rialto::verify_message(&payload), Ok(()));
|
assert_eq!(Rialto::verify_message(&payload), Ok(()));
|
||||||
@@ -202,7 +202,7 @@ mod tests {
|
|||||||
let payload = send_message::message_payload(
|
let payload = send_message::message_payload(
|
||||||
Default::default(),
|
Default::default(),
|
||||||
maximal_dispatch_weight + 1,
|
maximal_dispatch_weight + 1,
|
||||||
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
&call,
|
&call,
|
||||||
);
|
);
|
||||||
assert!(Rialto::verify_message(&payload).is_err());
|
assert!(Rialto::verify_message(&payload).is_err());
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ use crate::cli::{
|
|||||||
encode_call::{self, Call, CliEncodeCall},
|
encode_call::{self, Call, CliEncodeCall},
|
||||||
encode_message, send_message, CliChain,
|
encode_message, send_message, CliChain,
|
||||||
};
|
};
|
||||||
|
use bp_message_dispatch::{CallOrigin, MessagePayload};
|
||||||
use codec::Decode;
|
use codec::Decode;
|
||||||
use frame_support::weights::{GetDispatchInfo, Weight};
|
use frame_support::weights::{GetDispatchInfo, Weight};
|
||||||
use pallet_bridge_dispatch::{CallOrigin, MessagePayload};
|
|
||||||
use relay_rialto_client::Rialto;
|
use relay_rialto_client::Rialto;
|
||||||
use sp_version::RuntimeVersion;
|
use sp_version::RuntimeVersion;
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ use crate::cli::{
|
|||||||
Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams,
|
Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams,
|
||||||
TargetSigningParams,
|
TargetSigningParams,
|
||||||
};
|
};
|
||||||
|
use bp_message_dispatch::{CallOrigin, MessagePayload};
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use frame_support::{dispatch::GetDispatchInfo, weights::Weight};
|
use frame_support::{dispatch::GetDispatchInfo, weights::Weight};
|
||||||
use pallet_bridge_dispatch::{CallOrigin, MessagePayload};
|
|
||||||
use relay_substrate_client::{Chain, TransactionSignScheme};
|
use relay_substrate_client::{Chain, TransactionSignScheme};
|
||||||
use sp_core::{Bytes, Pair};
|
use sp_core::{Bytes, Pair};
|
||||||
use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner};
|
use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner};
|
||||||
|
|||||||
Reference in New Issue
Block a user