Newer
Older
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use crate::Trait;
use bp_message_lane::{
source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain},
target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain},
InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce,
use codec::{Decode, Encode};
use frame_support::{impl_outer_event, impl_outer_origin, parameter_types, weights::Weight};
use sp_core::H256;
use sp_runtime::{
testing::Header as SubstrateHeader,
traits::{BlakeTwo256, IdentityLookup},
Perbill,
};
use std::collections::BTreeMap;
pub type AccountId = u64;
pub type TestPayload = (u64, Weight);
pub type TestMessageFee = u64;
pub type TestRelayer = u64;
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct TestRuntime;
mod message_lane {
pub use crate::Event;
}
impl_outer_event! {
pub enum TestEvent for TestRuntime {
frame_system<T>,
}
}
impl_outer_origin! {
pub enum Origin for TestRuntime where system = frame_system {}
}
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const MaximumBlockWeight: Weight = 1024;
pub const MaximumBlockLength: u32 = 2 * 1024;
pub const AvailableBlockRatio: Perbill = Perbill::one();
}
impl frame_system::Trait for TestRuntime {
type Origin = Origin;
type Index = u64;
type Call = ();
type BlockNumber = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = AccountId;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = SubstrateHeader;
type Event = TestEvent;
type BlockHashCount = BlockHashCount;
type MaximumBlockWeight = MaximumBlockWeight;
type DbWeight = ();
type BlockExecutionWeight = ();
type ExtrinsicBaseWeight = ();
type MaximumExtrinsicWeight = MaximumBlockWeight;
type AvailableBlockRatio = AvailableBlockRatio;
type MaximumBlockLength = MaximumBlockLength;
type Version = ();
type AccountData = ();
type OnNewAccount = ();
type OnKilledAccount = ();
type BaseCallFilter = ();
type SystemWeightInfo = ();
}
parameter_types! {
pub const MaxMessagesToPruneAtOnce: u64 = 10;
pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 16;
}
impl Trait for TestRuntime {
type Event = TestEvent;
type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce;
type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane;
type OutboundPayload = TestPayload;
type OutboundMessageFee = TestMessageFee;
type InboundPayload = TestPayload;
type InboundMessageFee = TestMessageFee;
type InboundRelayer = TestRelayer;
type TargetHeaderChain = TestTargetHeaderChain;
type LaneMessageVerifier = TestLaneMessageVerifier;
type MessageDeliveryAndDispatchPayment = TestMessageDeliveryAndDispatchPayment;
type SourceHeaderChain = TestSourceHeaderChain;
type MessageDispatch = TestMessageDispatch;
/// Account id of test relayer.
pub const TEST_RELAYER_A: AccountId = 100;
/// Account id of additional test relayer - B.
pub const TEST_RELAYER_B: AccountId = 101;
/// Account id of additional test relayer - C.
pub const TEST_RELAYER_C: AccountId = 102;
/// Error that is returned by all test implementations.
pub const TEST_ERROR: &str = "Test error";
/// Lane that we're using in tests.
pub const TEST_LANE_ID: LaneId = [0, 0, 0, 1];
/// Regular message payload.
pub const REGULAR_PAYLOAD: TestPayload = (0, 50);
/// Payload that is rejected by `TestTargetHeaderChain`.
pub const PAYLOAD_REJECTED_BY_TARGET_CHAIN: TestPayload = (1, 50);
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/// Vec of proved messages, grouped by lane.
pub type MessagesByLaneVec = Vec<(LaneId, ProvedLaneMessages<Message<TestMessageFee>>)>;
/// Test messages proof.
#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq)]
pub struct TestMessagesProof {
pub result: Result<MessagesByLaneVec, ()>,
}
impl From<Result<Vec<Message<TestMessageFee>>, ()>> for TestMessagesProof {
fn from(result: Result<Vec<Message<TestMessageFee>>, ()>) -> Self {
Self {
result: result.map(|messages| {
let mut messages_by_lane: BTreeMap<LaneId, ProvedLaneMessages<Message<TestMessageFee>>> =
BTreeMap::new();
for message in messages {
messages_by_lane
.entry(message.key.lane_id)
.or_default()
.messages
.push(message);
}
messages_by_lane.into_iter().collect()
}),
}
}
}
/// Target header chain that is used in tests.
#[derive(Debug, Default)]
pub struct TestTargetHeaderChain;
impl TargetHeaderChain<TestPayload, TestRelayer> for TestTargetHeaderChain {
type Error = &'static str;
type MessagesDeliveryProof = Result<(LaneId, InboundLaneData<TestRelayer>), ()>;
fn verify_message(payload: &TestPayload) -> Result<(), Self::Error> {
if *payload == PAYLOAD_REJECTED_BY_TARGET_CHAIN {
Err(TEST_ERROR)
} else {
Ok(())
}
}
fn verify_messages_delivery_proof(
proof: Self::MessagesDeliveryProof,
) -> Result<(LaneId, InboundLaneData<TestRelayer>), Self::Error> {
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
proof.map_err(|_| TEST_ERROR)
}
}
/// Lane message verifier that is used in tests.
#[derive(Debug, Default)]
pub struct TestLaneMessageVerifier;
impl LaneMessageVerifier<AccountId, TestPayload, TestMessageFee> for TestLaneMessageVerifier {
type Error = &'static str;
fn verify_message(
_submitter: &AccountId,
delivery_and_dispatch_fee: &TestMessageFee,
_lane: &LaneId,
_payload: &TestPayload,
) -> Result<(), Self::Error> {
if *delivery_and_dispatch_fee != 0 {
Ok(())
} else {
Err(TEST_ERROR)
}
}
}
/// Message fee payment system that is used in tests.
#[derive(Debug, Default)]
pub struct TestMessageDeliveryAndDispatchPayment;
impl TestMessageDeliveryAndDispatchPayment {
/// Reject all payments.
pub fn reject_payments() {
frame_support::storage::unhashed::put(b":reject-message-fee:", &true);
}
/// Returns true if given fee has been paid by given submitter.
pub fn is_fee_paid(submitter: AccountId, fee: TestMessageFee) -> bool {
frame_support::storage::unhashed::get(b":message-fee:") == Some((submitter, fee))
}
/// Returns true if given relayer has been rewarded with given balance. The reward-paid flag is
/// cleared after the call.
pub fn is_reward_paid(relayer: AccountId, fee: TestMessageFee) -> bool {
let key = (b":relayer-reward:", relayer, fee).encode();
frame_support::storage::unhashed::take::<bool>(&key).is_some()
}
}
impl MessageDeliveryAndDispatchPayment<AccountId, TestMessageFee> for TestMessageDeliveryAndDispatchPayment {
type Error = &'static str;
fn pay_delivery_and_dispatch_fee(submitter: &AccountId, fee: &TestMessageFee) -> Result<(), Self::Error> {
if frame_support::storage::unhashed::get(b":reject-message-fee:") == Some(true) {
return Err(TEST_ERROR);
}
frame_support::storage::unhashed::put(b":message-fee:", &(submitter, fee));
Ok(())
}
fn pay_relayer_reward(_confirmation_relayer: &AccountId, relayer: &AccountId, fee: &TestMessageFee) {
let key = (b":relayer-reward:", relayer, fee).encode();
frame_support::storage::unhashed::put(&key, &true);
}
}
/// Source header chain that is used in tests.
#[derive(Debug)]
pub struct TestSourceHeaderChain;
impl SourceHeaderChain<TestMessageFee> for TestSourceHeaderChain {
type Error = &'static str;
type MessagesProof = TestMessagesProof;
fn verify_messages_proof(
proof: Self::MessagesProof,
) -> Result<ProvedMessages<Message<TestMessageFee>>, Self::Error> {
proof
.result
.map(|proof| proof.into_iter().collect())
.map_err(|_| TEST_ERROR)
}
}
/// Source header chain that is used in tests.
#[derive(Debug)]
pub struct TestMessageDispatch;
impl MessageDispatch<TestMessageFee> for TestMessageDispatch {
type DispatchPayload = TestPayload;
fn dispatch_weight(message: &DispatchMessage<TestPayload, TestMessageFee>) -> Weight {
match message.data.payload.as_ref() {
Ok(payload) => payload.1,
Err(_) => 0,
}
fn dispatch(_message: DispatchMessage<TestPayload, TestMessageFee>) {}
}
/// Return test lane message with given nonce and payload.
pub fn message(nonce: MessageNonce, payload: TestPayload) -> Message<TestMessageFee> {
Message {
key: MessageKey {
lane_id: TEST_LANE_ID,
nonce,
},
data: message_data(payload),
}
}
/// Return message data with valid fee for given payload.
pub fn message_data(payload: TestPayload) -> MessageData<TestMessageFee> {
MessageData {
payload: payload.encode(),
fee: 1,
}
/// Run message lane test.
pub fn run_test<T>(test: impl FnOnce() -> T) -> T {
let t = frame_system::GenesisConfig::default()
.build_storage::<TestRuntime>()
.unwrap();
let mut ext = sp_io::TestExternalities::new(t);
ext.execute_with(test)