mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 03:31:10 +00:00
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user