Squashed 'bridges/' changes from b2099c5..23dda62 (#3369)

23dda62 Rococo <> Wococo messages relay (#1030)
bcde21d Update the wasm builder to substrate master (#1029)
a8318ce Make target signer optional when sending message. (#1018)
f8602e1 Fix insufficient balance when send message. (#1020)
d95c0a7 greedy relayer don't need message dispatch to be prepaid if dispatch is supposed to be paid at the target chain (#1016)
ad5876f Update types. (#1027)
116cbbc CI: fix starting the pipeline (#1022)
7e0fadd Add temporary `canary` job (#1019)
6787091 Update types to contain dispatch_fee_payment (#1017)
03f79ad Allow Root to assume SourceAccount. (#1011)
372d019 Return dispatch_fee_payment from message details RPC (#1014)
604eb1c Relay basic single-bit message dispatch results back to the source chain (#935)
bf52fff Use plain source_queue view when selecting nonces for delivery (#1010)
fc5cf7d pay dispatch fee at target chain (#911)
1e35477 Bump Substrate to `286d7ce` (#1006)
7ad07b3 Add --only-mandatory-headers mode (#1004)
5351dc9 Messages relayer operating mode (#995)
9bc29a7 Rococo <> Wococo relayer balance guard (#998)
bc17341 rename messages_dispatch_weight -> message_details (#996)
95be244 Bump Rococo and Wococo spec versions (#999)
c35567b Move ChainWithBalances::NativeBalance -> Chain::Balance (#990)
1bfece1 Fix some nits (#988)
334ea0f Increase pause before starting relays again (#989)
7fb8248 Fix clippy in test code (#993)
d60ae50 fix clippy issues (#991)
75ca813 Make sure GRANDPA shares state with RPC. (#987)
da2a38a Bump Substrate (#986)
5a9862f Update submit finality proof weight formula (#981)
69df513 Flag for rejecting all outbound messages (#982)
14d0506 Add script to setup bench machine. (#984)
e74e8ab Move CI from GitHub Actions to GitLab (#814)
c5ca5dd Custom justification verification (#979)
643f10d Always run on-demand headers relay in complex relay (#975)
a35b0ef Add JSON type definitions for Rococo<>Wococo bridge (#977)
0eb83f2 Update cargo.deny (#980)
e1d1f4c Bump Rococo/Wococo spec_version (#976)
deac90d increase pause before starting relays (#974)
68d6d79 Revert to use InspectCmd, bump substrate `6bef4f4` (#966)
66e1508 Avoid hashing headers twice in verify_justification (#973)
a31844f Bump `environmental` dependency (#972)
2a4c29a in auto-relays keep trying to connect to nodes until connection is established (#971)
0e767b3 removed stray file (#969)
b9545dc Serve multiple lanes with single complex relay instance (#964)
73419f4 Correct type error (#968)
bac256f Start finality relay spec-version guards for Rococo <> Wococo finality relays (#965)
bfd7037 pass source and target chain ids to account_ownership_proof (#963)
8436073 Upstream changes from Polkadot repo (#961)
e58d851 Increase account endowment amount (#960)

git-subtree-dir: bridges
git-subtree-split: 23dda6248236b27f20d76cbedc30e189cc6f736c
This commit is contained in:
Svyatoslav Nikolsky
2021-06-25 16:45:02 +03:00
committed by GitHub
parent 022e8bc11c
commit feefc34567
167 changed files with 7023 additions and 3239 deletions
+264 -84
View File
@@ -23,9 +23,15 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![warn(missing_docs)]
// Generated by `decl_event!`
#![allow(clippy::unused_unit)]
use bp_message_dispatch::{CallOrigin, MessageDispatch, MessagePayload, SpecVersion, Weight};
use bp_runtime::{derive_account_id, InstanceId, SourceAccount};
use bp_runtime::{
derive_account_id,
messages::{DispatchFeePayment, MessageDispatchResult},
ChainId, SourceAccount,
};
use codec::{Decode, Encode};
use frame_support::{
decl_event, decl_module, decl_storage,
@@ -87,24 +93,27 @@ decl_storage! {
decl_event!(
pub enum Event<T, I = DefaultInstance> where
<T as Config<I>>::MessageId
<T as Config<I>>::MessageId,
AccountId = <T as frame_system::Config>::AccountId,
{
/// Message has been rejected before reaching dispatch.
MessageRejected(InstanceId, MessageId),
MessageRejected(ChainId, MessageId),
/// Message has been rejected by dispatcher because of spec version mismatch.
/// Last two arguments are: expected and passed spec version.
MessageVersionSpecMismatch(InstanceId, MessageId, SpecVersion, SpecVersion),
MessageVersionSpecMismatch(ChainId, MessageId, SpecVersion, SpecVersion),
/// Message has been rejected by dispatcher because of weight mismatch.
/// Last two arguments are: expected and passed call weight.
MessageWeightMismatch(InstanceId, MessageId, Weight, Weight),
MessageWeightMismatch(ChainId, MessageId, Weight, Weight),
/// Message signature mismatch.
MessageSignatureMismatch(InstanceId, MessageId),
/// Message has been dispatched with given result.
MessageDispatched(InstanceId, MessageId, DispatchResult),
MessageSignatureMismatch(ChainId, MessageId),
/// We have failed to decode Call from the message.
MessageCallDecodeFailed(InstanceId, MessageId),
MessageCallDecodeFailed(ChainId, MessageId),
/// The call from the message has been rejected by the call filter.
MessageCallRejected(InstanceId, MessageId),
MessageCallRejected(ChainId, MessageId),
/// The origin account has failed to pay fee for dispatching the message.
MessageDispatchPaymentFailed(ChainId, MessageId, AccountId, Weight),
/// Message has been dispatched with given result.
MessageDispatched(ChainId, MessageId, DispatchResult),
/// Phantom member, never used. Needed to handle multiple pallet instances.
_Dummy(PhantomData<I>),
}
@@ -118,7 +127,7 @@ decl_module! {
}
}
impl<T: Config<I>, I: Instance> MessageDispatch<T::MessageId> for Pallet<T, I> {
impl<T: Config<I>, I: Instance> MessageDispatch<T::AccountId, T::MessageId> for Pallet<T, I> {
type Message =
MessagePayload<T::SourceChainAccountId, T::TargetChainAccountPublic, T::TargetChainSignature, T::EncodedCall>;
@@ -126,77 +135,108 @@ impl<T: Config<I>, I: Instance> MessageDispatch<T::MessageId> for Pallet<T, I> {
message.weight
}
fn dispatch(bridge: InstanceId, id: T::MessageId, message: Result<Self::Message, ()>) {
fn dispatch<P: FnOnce(&T::AccountId, Weight) -> Result<(), ()>>(
source_chain: ChainId,
target_chain: ChainId,
id: T::MessageId,
message: Result<Self::Message, ()>,
pay_dispatch_fee: P,
) -> MessageDispatchResult {
// emit special even if message has been rejected by external component
let message = match message {
Ok(message) => message,
Err(_) => {
log::trace!(target: "runtime::bridge-dispatch", "Message {:?}/{:?}: rejected before actual dispatch", bridge, id);
Self::deposit_event(RawEvent::MessageRejected(bridge, id));
return;
log::trace!(
target: "runtime::bridge-dispatch",
"Message {:?}/{:?}: rejected before actual dispatch",
source_chain,
id,
);
Self::deposit_event(RawEvent::MessageRejected(source_chain, id));
return MessageDispatchResult {
dispatch_result: false,
unspent_weight: 0,
dispatch_fee_paid_during_dispatch: false,
};
}
};
// verify spec version
// (we want it to be the same, because otherwise we may decode Call improperly)
let mut dispatch_result = MessageDispatchResult {
dispatch_result: false,
unspent_weight: message.weight,
dispatch_fee_paid_during_dispatch: false,
};
let expected_version = <T as frame_system::Config>::Version::get().spec_version;
if message.spec_version != expected_version {
log::trace!(
"Message {:?}/{:?}: spec_version mismatch. Expected {:?}, got {:?}",
bridge,
source_chain,
id,
expected_version,
message.spec_version,
);
Self::deposit_event(RawEvent::MessageVersionSpecMismatch(
bridge,
source_chain,
id,
expected_version,
message.spec_version,
));
return;
return dispatch_result;
}
// now that we have spec version checked, let's decode the call
let call = match message.call.into() {
Ok(call) => call,
Err(_) => {
log::trace!(target: "runtime::bridge-dispatch", "Failed to decode Call from message {:?}/{:?}", bridge, id,);
Self::deposit_event(RawEvent::MessageCallDecodeFailed(bridge, id));
return;
log::trace!(
target: "runtime::bridge-dispatch",
"Failed to decode Call from message {:?}/{:?}",
source_chain,
id,
);
Self::deposit_event(RawEvent::MessageCallDecodeFailed(source_chain, id));
return dispatch_result;
}
};
// prepare dispatch origin
let origin_account = match message.origin {
CallOrigin::SourceRoot => {
let hex_id = derive_account_id::<T::SourceChainAccountId>(bridge, SourceAccount::Root);
let hex_id = derive_account_id::<T::SourceChainAccountId>(source_chain, SourceAccount::Root);
let target_id = T::AccountIdConverter::convert(hex_id);
log::trace!(target: "runtime::bridge-dispatch", "Root Account: {:?}", &target_id);
target_id
}
CallOrigin::TargetAccount(source_account_id, target_public, target_signature) => {
let digest = account_ownership_digest(&call, source_account_id, message.spec_version, bridge);
let digest = account_ownership_digest(
&call,
source_account_id,
message.spec_version,
source_chain,
target_chain,
);
let target_account = target_public.into_account();
if !target_signature.verify(&digest[..], &target_account) {
log::trace!(
target: "runtime::bridge-dispatch",
"Message {:?}/{:?}: origin proof is invalid. Expected account: {:?} from signature: {:?}",
bridge,
source_chain,
id,
target_account,
target_signature,
);
Self::deposit_event(RawEvent::MessageSignatureMismatch(bridge, id));
return;
Self::deposit_event(RawEvent::MessageSignatureMismatch(source_chain, id));
return dispatch_result;
}
log::trace!(target: "runtime::bridge-dispatch", "Target Account: {:?}", &target_account);
target_account
}
CallOrigin::SourceAccount(source_account_id) => {
let hex_id = derive_account_id(bridge, SourceAccount::Account(source_account_id));
let hex_id = derive_account_id(source_chain, SourceAccount::Account(source_account_id));
let target_id = T::AccountIdConverter::convert(hex_id);
log::trace!(target: "runtime::bridge-dispatch", "Source Account: {:?}", &target_id);
target_id
@@ -208,12 +248,12 @@ impl<T: Config<I>, I: Instance> MessageDispatch<T::MessageId> for Pallet<T, I> {
log::trace!(
target: "runtime::bridge-dispatch",
"Message {:?}/{:?}: the call ({:?}) is rejected by filter",
bridge,
source_chain,
id,
call,
);
Self::deposit_event(RawEvent::MessageCallRejected(bridge, id));
return;
Self::deposit_event(RawEvent::MessageCallRejected(source_chain, id));
return dispatch_result;
}
// verify weight
@@ -225,41 +265,67 @@ impl<T: Config<I>, I: Instance> MessageDispatch<T::MessageId> for Pallet<T, I> {
log::trace!(
target: "runtime::bridge-dispatch",
"Message {:?}/{:?}: passed weight is too low. Expected at least {:?}, got {:?}",
bridge,
source_chain,
id,
expected_weight,
message.weight,
);
Self::deposit_event(RawEvent::MessageWeightMismatch(
bridge,
source_chain,
id,
expected_weight,
message.weight,
));
return;
return dispatch_result;
}
// pay dispatch fee right before dispatch
let pay_dispatch_fee_at_target_chain = message.dispatch_fee_payment == DispatchFeePayment::AtTargetChain;
if pay_dispatch_fee_at_target_chain && pay_dispatch_fee(&origin_account, message.weight).is_err() {
log::trace!(
target: "runtime::bridge-dispatch",
"Failed to pay dispatch fee for dispatching message {:?}/{:?} with weight {}",
source_chain,
id,
message.weight,
);
Self::deposit_event(RawEvent::MessageDispatchPaymentFailed(
source_chain,
id,
origin_account,
message.weight,
));
return dispatch_result;
}
dispatch_result.dispatch_fee_paid_during_dispatch = pay_dispatch_fee_at_target_chain;
// finally dispatch message
let origin = RawOrigin::Signed(origin_account).into();
log::trace!(target: "runtime::bridge-dispatch", "Message being dispatched is: {:.4096?}", &call);
let dispatch_result = call.dispatch(origin);
let actual_call_weight = extract_actual_weight(&dispatch_result, &dispatch_info);
let result = call.dispatch(origin);
let actual_call_weight = extract_actual_weight(&result, &dispatch_info);
dispatch_result.dispatch_result = result.is_ok();
dispatch_result.unspent_weight = message.weight.saturating_sub(actual_call_weight);
log::trace!(
target: "runtime::bridge-dispatch",
"Message {:?}/{:?} has been dispatched. Weight: {} of {}. Result: {:?}",
bridge,
"Message {:?}/{:?} has been dispatched. Weight: {} of {}. Result: {:?}. Call dispatch result: {:?}",
source_chain,
id,
actual_call_weight,
dispatch_result.unspent_weight,
message.weight,
dispatch_result,
result,
);
Self::deposit_event(RawEvent::MessageDispatched(
bridge,
source_chain,
id,
dispatch_result.map(drop).map_err(|e| e.error),
result.map(drop).map_err(|e| e.error),
));
dispatch_result
}
}
@@ -290,7 +356,7 @@ where
}
CallOrigin::SourceAccount(ref source_account_id) => {
ensure!(
sender_origin == &RawOrigin::Signed(source_account_id.clone()),
sender_origin == &RawOrigin::Signed(source_account_id.clone()) || sender_origin == &RawOrigin::Root,
BadOrigin
);
Ok(Some(source_account_id.clone()))
@@ -303,23 +369,24 @@ where
/// The byte vector returned by this function will be signed with a target chain account
/// private key. This way, the owner of `source_account_id` on the source chain proves that
/// the target chain account private key is also under his control.
pub fn account_ownership_digest<Call, AccountId, SpecVersion, BridgeId>(
pub fn account_ownership_digest<Call, AccountId, SpecVersion>(
call: &Call,
source_account_id: AccountId,
target_spec_version: SpecVersion,
source_instance_id: BridgeId,
source_chain_id: ChainId,
target_chain_id: ChainId,
) -> Vec<u8>
where
Call: Encode,
AccountId: Encode,
SpecVersion: Encode,
BridgeId: Encode,
{
let mut proof = Vec::new();
call.encode_to(&mut proof);
source_account_id.encode_to(&mut proof);
target_spec_version.encode_to(&mut proof);
source_instance_id.encode_to(&mut proof);
source_chain_id.encode_to(&mut proof);
target_chain_id.encode_to(&mut proof);
proof
}
@@ -342,6 +409,9 @@ mod tests {
type AccountId = u64;
type MessageId = [u8; 4];
const SOURCE_CHAIN_ID: ChainId = *b"srce";
const TARGET_CHAIN_ID: ChainId = *b"trgt";
#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq)]
pub struct TestAccountPublic(AccountId);
@@ -463,31 +533,32 @@ mod tests {
fn prepare_message(
origin: CallOrigin<AccountId, TestAccountPublic, TestSignature>,
call: Call,
) -> <Pallet<TestRuntime> as MessageDispatch<<TestRuntime as Config>::MessageId>>::Message {
) -> <Pallet<TestRuntime> as MessageDispatch<AccountId, <TestRuntime as Config>::MessageId>>::Message {
MessagePayload {
spec_version: TEST_SPEC_VERSION,
weight: TEST_WEIGHT,
origin,
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
call: EncodedCall(call.encode()),
}
}
fn prepare_root_message(
call: Call,
) -> <Pallet<TestRuntime> as MessageDispatch<<TestRuntime as Config>::MessageId>>::Message {
) -> <Pallet<TestRuntime> as MessageDispatch<AccountId, <TestRuntime as Config>::MessageId>>::Message {
prepare_message(CallOrigin::SourceRoot, call)
}
fn prepare_target_message(
call: Call,
) -> <Pallet<TestRuntime> as MessageDispatch<<TestRuntime as Config>::MessageId>>::Message {
) -> <Pallet<TestRuntime> as MessageDispatch<AccountId, <TestRuntime as Config>::MessageId>>::Message {
let origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(1));
prepare_message(origin, call)
}
fn prepare_source_message(
call: Call,
) -> <Pallet<TestRuntime> as MessageDispatch<<TestRuntime as Config>::MessageId>>::Message {
) -> <Pallet<TestRuntime> as MessageDispatch<AccountId, <TestRuntime as Config>::MessageId>>::Message {
let origin = CallOrigin::SourceAccount(1);
prepare_message(origin, call)
}
@@ -495,23 +566,25 @@ mod tests {
#[test]
fn should_fail_on_spec_version_mismatch() {
new_test_ext().execute_with(|| {
let bridge = b"ethb".to_owned();
let id = [0; 4];
const BAD_SPEC_VERSION: SpecVersion = 99;
let mut message =
prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
let weight = message.weight;
message.spec_version = BAD_SPEC_VERSION;
System::set_block_number(1);
Dispatch::dispatch(bridge, id, Ok(message));
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
assert_eq!(result.unspent_weight, weight);
assert!(!result.dispatch_result);
assert_eq!(
System::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageVersionSpecMismatch(
bridge,
SOURCE_CHAIN_ID,
id,
TEST_SPEC_VERSION,
BAD_SPEC_VERSION
@@ -525,21 +598,25 @@ mod tests {
#[test]
fn should_fail_on_weight_mismatch() {
new_test_ext().execute_with(|| {
let bridge = b"ethb".to_owned();
let id = [0; 4];
let mut message =
prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
message.weight = 0;
message.weight = 7;
System::set_block_number(1);
Dispatch::dispatch(bridge, id, Ok(message));
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
assert_eq!(result.unspent_weight, 7);
assert!(!result.dispatch_result);
assert_eq!(
System::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageWeightMismatch(
bridge, id, 1345000, 0,
SOURCE_CHAIN_ID,
id,
1038000,
7,
)),
topics: vec![],
}],
@@ -550,7 +627,6 @@ mod tests {
#[test]
fn should_fail_on_signature_mismatch() {
new_test_ext().execute_with(|| {
let bridge = b"ethb".to_owned();
let id = [0; 4];
let call_origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(99));
@@ -558,16 +634,20 @@ mod tests {
call_origin,
Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])),
);
let weight = message.weight;
System::set_block_number(1);
Dispatch::dispatch(bridge, id, Ok(message));
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
assert_eq!(result.unspent_weight, weight);
assert!(!result.dispatch_result);
assert_eq!(
System::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageSignatureMismatch(
bridge, id
SOURCE_CHAIN_ID,
id
)),
topics: vec![],
}],
@@ -578,17 +658,19 @@ mod tests {
#[test]
fn should_emit_event_for_rejected_messages() {
new_test_ext().execute_with(|| {
let bridge = b"ethb".to_owned();
let id = [0; 4];
System::set_block_number(1);
Dispatch::dispatch(bridge, id, Err(()));
Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Err(()), |_, _| unreachable!());
assert_eq!(
System::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageRejected(bridge, id)),
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageRejected(
SOURCE_CHAIN_ID,
id
)),
topics: vec![],
}],
);
@@ -598,22 +680,25 @@ mod tests {
#[test]
fn should_fail_on_call_decode() {
new_test_ext().execute_with(|| {
let bridge = b"ethb".to_owned();
let id = [0; 4];
let mut message =
prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
let weight = message.weight;
message.call.0 = vec![];
System::set_block_number(1);
Dispatch::dispatch(bridge, id, Ok(message));
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
assert_eq!(result.unspent_weight, weight);
assert!(!result.dispatch_result);
assert_eq!(
System::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageCallDecodeFailed(
bridge, id
SOURCE_CHAIN_ID,
id
)),
topics: vec![],
}],
@@ -624,7 +709,6 @@ mod tests {
#[test]
fn should_emit_event_for_rejected_calls() {
new_test_ext().execute_with(|| {
let bridge = b"ethb".to_owned();
let id = [0; 4];
let call = Call::System(<frame_system::Call<TestRuntime>>::fill_block(Perbill::from_percent(75)));
@@ -633,13 +717,18 @@ mod tests {
message.weight = weight;
System::set_block_number(1);
Dispatch::dispatch(bridge, id, Ok(message));
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
assert_eq!(result.unspent_weight, weight);
assert!(!result.dispatch_result);
assert_eq!(
System::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageCallRejected(bridge, id)),
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageCallRejected(
SOURCE_CHAIN_ID,
id
)),
topics: vec![],
}],
);
@@ -647,21 +736,113 @@ mod tests {
}
#[test]
fn should_dispatch_bridge_message_from_root_origin() {
fn should_emit_event_for_unpaid_calls() {
new_test_ext().execute_with(|| {
let bridge = b"ethb".to_owned();
let id = [0; 4];
let message = prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
let mut message =
prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
let weight = message.weight;
message.dispatch_fee_payment = DispatchFeePayment::AtTargetChain;
System::set_block_number(1);
Dispatch::dispatch(bridge, id, Ok(message));
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| Err(()));
assert_eq!(result.unspent_weight, weight);
assert!(!result.dispatch_result);
assert_eq!(
System::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageDispatchPaymentFailed(
SOURCE_CHAIN_ID,
id,
AccountIdConverter::convert(derive_account_id::<AccountId>(
SOURCE_CHAIN_ID,
SourceAccount::Root
)),
TEST_WEIGHT,
)),
topics: vec![],
}],
);
});
}
#[test]
fn should_dispatch_calls_paid_at_target_chain() {
new_test_ext().execute_with(|| {
let id = [0; 4];
let mut message =
prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
message.dispatch_fee_payment = DispatchFeePayment::AtTargetChain;
System::set_block_number(1);
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| Ok(()));
assert!(result.dispatch_fee_paid_during_dispatch);
assert!(result.dispatch_result);
assert_eq!(
System::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageDispatched(
bridge,
SOURCE_CHAIN_ID,
id,
Ok(())
)),
topics: vec![],
}],
);
});
}
#[test]
fn should_return_dispatch_failed_flag_if_dispatch_happened_but_failed() {
new_test_ext().execute_with(|| {
let id = [0; 4];
let call = Call::System(<frame_system::Call<TestRuntime>>::set_heap_pages(1));
let message = prepare_target_message(call);
System::set_block_number(1);
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
assert!(!result.dispatch_fee_paid_during_dispatch);
assert!(!result.dispatch_result);
assert_eq!(
System::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageDispatched(
SOURCE_CHAIN_ID,
id,
Err(sp_runtime::DispatchError::BadOrigin)
)),
topics: vec![],
}],
);
})
}
#[test]
fn should_dispatch_bridge_message_from_root_origin() {
new_test_ext().execute_with(|| {
let id = [0; 4];
let message = prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
System::set_block_number(1);
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
assert!(!result.dispatch_fee_paid_during_dispatch);
assert!(result.dispatch_result);
assert_eq!(
System::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageDispatched(
SOURCE_CHAIN_ID,
id,
Ok(())
)),
@@ -675,20 +856,21 @@ mod tests {
fn should_dispatch_bridge_message_from_target_origin() {
new_test_ext().execute_with(|| {
let id = [0; 4];
let bridge = b"ethb".to_owned();
let call = Call::System(<frame_system::Call<TestRuntime>>::remark(vec![]));
let message = prepare_target_message(call);
System::set_block_number(1);
Dispatch::dispatch(bridge, id, Ok(message));
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
assert!(!result.dispatch_fee_paid_during_dispatch);
assert!(result.dispatch_result);
assert_eq!(
System::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageDispatched(
bridge,
SOURCE_CHAIN_ID,
id,
Ok(())
)),
@@ -702,20 +884,21 @@ mod tests {
fn should_dispatch_bridge_message_from_source_origin() {
new_test_ext().execute_with(|| {
let id = [0; 4];
let bridge = b"ethb".to_owned();
let call = Call::System(<frame_system::Call<TestRuntime>>::remark(vec![]));
let message = prepare_source_message(call);
System::set_block_number(1);
Dispatch::dispatch(bridge, id, Ok(message));
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
assert!(!result.dispatch_fee_paid_during_dispatch);
assert!(result.dispatch_result);
assert_eq!(
System::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageDispatched(
bridge,
SOURCE_CHAIN_ID,
id,
Ok(())
)),
@@ -782,10 +965,7 @@ mod tests {
Err(BadOrigin)
));
// If we try and send the message from Root, it is also rejected
assert!(matches!(
verify_message_origin(&RawOrigin::Root, &message),
Err(BadOrigin)
));
// The Root account is allowed to assume any expected origin account
assert!(matches!(verify_message_origin(&RawOrigin::Root, &message), Ok(Some(1))));
}
}