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:
fewensa
2021-05-04 01:52:43 +08:00
committed by Bastian Köcher
parent d85240b539
commit 4ccf7a2f5a
13 changed files with 115 additions and 108 deletions
+3 -3
View File
@@ -889,7 +889,7 @@ impl_runtime_apis! {
params: MessageParams<Self::AccountId>,
) -> (millau_messages::ToMillauMessagePayload, Balance) {
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,
);
@@ -959,10 +959,10 @@ impl_runtime_apis! {
make_millau_outbound_lane_data_key,
make_millau_header,
call_weight,
pallet_bridge_dispatch::MessagePayload {
bp_message_dispatch::MessagePayload {
spec_version: VERSION.spec_version,
weight: call_weight,
origin: pallet_bridge_dispatch::CallOrigin::<
origin: bp_message_dispatch::CallOrigin::<
bp_millau::AccountId,
MultiSigner,
Signature,
+4 -4
View File
@@ -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;
- the messages sent over the bridge are dispatched using
[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
[messages module](../../modules/messages/README.md) instance at the source chain.
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`.
`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.
`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
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
in the `pallet_bridge_dispatch::CallOrigin::TargetAccount` origin;
`bp_message_dispatch::CallOrigin::SourceRoot` origin. Or he has provided wrong signature
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
than the fee that is computed using the `estimate_message_dispatch_and_delivery_fee` function.
+12 -12
View File
@@ -180,7 +180,7 @@ pub mod source {
pub type BridgedChainOpaqueCall = Vec<u8>;
/// 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>>,
SignerOf<BridgedChain<B>>,
SignatureOf<BridgedChain<B>>,
@@ -395,14 +395,14 @@ pub mod target {
use super::*;
/// 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>>,
SignerOf<ThisChain<B>>,
SignatureOf<ThisChain<B>>,
>;
/// Decoded Bridged -> This message payload.
pub type FromBridgedChainMessagePayload<B> = pallet_bridge_dispatch::MessagePayload<
pub type FromBridgedChainMessagePayload<B> = bp_message_dispatch::MessagePayload<
AccountIdOf<BridgedChain<B>>,
SignerOf<ThisChain<B>>,
SignatureOf<ThisChain<B>>,
@@ -931,7 +931,7 @@ mod tests {
let message_on_bridged_chain = source::FromThisChainMessagePayload::<OnBridgedChainBridge> {
spec_version: 1,
weight: 100,
origin: pallet_bridge_dispatch::CallOrigin::SourceRoot,
origin: bp_message_dispatch::CallOrigin::SourceRoot,
call: ThisChainCall::Transfer.encode(),
}
.encode();
@@ -945,7 +945,7 @@ mod tests {
target::FromBridgedChainMessagePayload::<OnThisChainBridge> {
spec_version: 1,
weight: 100,
origin: pallet_bridge_dispatch::CallOrigin::SourceRoot,
origin: bp_message_dispatch::CallOrigin::SourceRoot,
call: target::FromBridgedChainEncodedMessageCall::<OnThisChainBridge> {
encoded_call: ThisChainCall::Transfer.encode(),
_marker: PhantomData::default(),
@@ -962,7 +962,7 @@ mod tests {
source::FromThisChainMessagePayload::<OnThisChainBridge> {
spec_version: 1,
weight: 100,
origin: pallet_bridge_dispatch::CallOrigin::SourceRoot,
origin: bp_message_dispatch::CallOrigin::SourceRoot,
call: vec![42],
}
}
@@ -1012,7 +1012,7 @@ mod tests {
let payload = source::FromThisChainMessagePayload::<OnThisChainBridge> {
spec_version: 1,
weight: 100,
origin: pallet_bridge_dispatch::CallOrigin::SourceRoot,
origin: bp_message_dispatch::CallOrigin::SourceRoot,
call: vec![42],
};
@@ -1055,7 +1055,7 @@ mod tests {
let payload = source::FromThisChainMessagePayload::<OnThisChainBridge> {
spec_version: 1,
weight: 100,
origin: pallet_bridge_dispatch::CallOrigin::SourceAccount(ThisChainAccountId(1)),
origin: bp_message_dispatch::CallOrigin::SourceAccount(ThisChainAccountId(1)),
call: vec![42],
};
@@ -1122,7 +1122,7 @@ mod tests {
> {
spec_version: 1,
weight: 5,
origin: pallet_bridge_dispatch::CallOrigin::SourceRoot,
origin: bp_message_dispatch::CallOrigin::SourceRoot,
call: vec![1, 2, 3, 4, 5, 6],
},)
.is_err()
@@ -1137,7 +1137,7 @@ mod tests {
> {
spec_version: 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],
},)
.is_err()
@@ -1152,7 +1152,7 @@ mod tests {
> {
spec_version: 1,
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],
},)
.is_err()
@@ -1167,7 +1167,7 @@ mod tests {
> {
spec_version: 1,
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 _],
},),
Ok(()),
+1 -1
View File
@@ -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
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
+2 -2
View File
@@ -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
[messages module](../messages/README.md), it may worth to use a tuple
`(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.
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
try to decode `Call` from other runtime version;
- `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;
- `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
+2 -75
View File
@@ -24,8 +24,8 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![warn(missing_docs)]
use bp_message_dispatch::{MessageDispatch, Weight};
use bp_runtime::{derive_account_id, InstanceId, Size, SourceAccount};
use bp_message_dispatch::{CallOrigin, MessageDispatch, MessagePayload, SpecVersion, Weight};
use bp_runtime::{derive_account_id, InstanceId, SourceAccount};
use codec::{Decode, Encode};
use frame_support::{
decl_event, decl_module, decl_storage,
@@ -33,7 +33,6 @@ use frame_support::{
ensure,
traits::{Filter, Get},
weights::{extract_actual_weight, GetDispatchInfo},
RuntimeDebug,
};
use frame_system::RawOrigin;
use sp_runtime::{
@@ -42,78 +41,6 @@ use sp_runtime::{
};
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.
pub trait Config<I = DefaultInstance>: frame_system::Config {
/// 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 }
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]
default = ["std"]
std = [
"bp-runtime/std",
"codec/std",
"frame-support/std",
"sp-std/std",
]
+74 -1
View File
@@ -19,11 +19,17 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![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.
pub type Weight = u64;
/// Spec version type.
pub type SpecVersion = u32;
/// A generic trait to dispatch arbitrary messages delivered over the bridge.
pub trait MessageDispatch<MessageId> {
/// A type of the message to be dispatched.
@@ -47,3 +53,70 @@ pub trait MessageDispatch<MessageId> {
/// the whole 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 _
}
}
+1 -1
View File
@@ -23,6 +23,7 @@ structopt = "0.3"
bp-header-chain = { path = "../../primitives/header-chain" }
bp-kusama = { path = "../../primitives/chain-kusama" }
bp-messages = { path = "../../primitives/messages" }
bp-message-dispatch = { path = "../../primitives/message-dispatch" }
bp-millau = { path = "../../primitives/chain-millau" }
bp-polkadot = { path = "../../primitives/chain-polkadot" }
bp-rialto = { path = "../../primitives/chain-rialto" }
@@ -36,7 +37,6 @@ finality-relay = { path = "../finality" }
headers-relay = { path = "../headers" }
messages-relay = { path = "../messages" }
millau-runtime = { path = "../../bin/millau/runtime" }
pallet-bridge-dispatch = { path = "../../modules/dispatch" }
pallet-bridge-messages = { path = "../../modules/messages" }
relay-kusama-client = { path = "../client-kusama" }
relay-millau-client = { path = "../client-millau" }
@@ -21,9 +21,9 @@ use crate::cli::{
encode_call::{self, Call, CliEncodeCall},
encode_message, send_message, CliChain,
};
use bp_message_dispatch::{CallOrigin, MessagePayload};
use codec::Decode;
use frame_support::weights::{GetDispatchInfo, Weight};
use pallet_bridge_dispatch::{CallOrigin, MessagePayload};
use relay_millau_client::Millau;
use sp_version::RuntimeVersion;
@@ -132,7 +132,7 @@ mod tests {
let payload = send_message::message_payload(
Default::default(),
call.get_dispatch_info().weight,
pallet_bridge_dispatch::CallOrigin::SourceRoot,
bp_message_dispatch::CallOrigin::SourceRoot,
&call,
);
assert_eq!(Millau::verify_message(&payload), Ok(()));
@@ -142,7 +142,7 @@ mod tests {
let payload = send_message::message_payload(
Default::default(),
call.get_dispatch_info().weight,
pallet_bridge_dispatch::CallOrigin::SourceRoot,
bp_message_dispatch::CallOrigin::SourceRoot,
&call,
);
assert!(Millau::verify_message(&payload).is_err());
@@ -169,7 +169,7 @@ mod tests {
let payload = send_message::message_payload(
Default::default(),
maximal_dispatch_weight,
pallet_bridge_dispatch::CallOrigin::SourceRoot,
bp_message_dispatch::CallOrigin::SourceRoot,
&call,
);
assert_eq!(Millau::verify_message(&payload), Ok(()));
@@ -177,7 +177,7 @@ mod tests {
let payload = send_message::message_payload(
Default::default(),
maximal_dispatch_weight + 1,
pallet_bridge_dispatch::CallOrigin::SourceRoot,
bp_message_dispatch::CallOrigin::SourceRoot,
&call,
);
assert!(Millau::verify_message(&payload).is_err());
@@ -194,7 +194,7 @@ mod tests {
let payload = send_message::message_payload(
Default::default(),
maximal_dispatch_weight,
pallet_bridge_dispatch::CallOrigin::SourceRoot,
bp_message_dispatch::CallOrigin::SourceRoot,
&call,
);
assert_eq!(Rialto::verify_message(&payload), Ok(()));
@@ -202,7 +202,7 @@ mod tests {
let payload = send_message::message_payload(
Default::default(),
maximal_dispatch_weight + 1,
pallet_bridge_dispatch::CallOrigin::SourceRoot,
bp_message_dispatch::CallOrigin::SourceRoot,
&call,
);
assert!(Rialto::verify_message(&payload).is_err());
@@ -21,9 +21,9 @@ use crate::cli::{
encode_call::{self, Call, CliEncodeCall},
encode_message, send_message, CliChain,
};
use bp_message_dispatch::{CallOrigin, MessagePayload};
use codec::Decode;
use frame_support::weights::{GetDispatchInfo, Weight};
use pallet_bridge_dispatch::{CallOrigin, MessagePayload};
use relay_rialto_client::Rialto;
use sp_version::RuntimeVersion;
@@ -21,9 +21,9 @@ use crate::cli::{
Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams,
TargetSigningParams,
};
use bp_message_dispatch::{CallOrigin, MessagePayload};
use codec::Encode;
use frame_support::{dispatch::GetDispatchInfo, weights::Weight};
use pallet_bridge_dispatch::{CallOrigin, MessagePayload};
use relay_substrate_client::{Chain, TransactionSignScheme};
use sp_core::{Bytes, Pair};
use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner};