mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 09:51:02 +00:00
committed by
Bastian Köcher
parent
1dbfab83b4
commit
8c6dfc41c5
@@ -24,7 +24,7 @@ pub use bp_runtime::{RangeInclusiveExt, UnderlyingChainOf, UnderlyingChainProvid
|
|||||||
|
|
||||||
use bp_header_chain::HeaderChain;
|
use bp_header_chain::HeaderChain;
|
||||||
use bp_messages::{
|
use bp_messages::{
|
||||||
source_chain::{LaneMessageVerifier, TargetHeaderChain},
|
source_chain::TargetHeaderChain,
|
||||||
target_chain::{ProvedLaneMessages, ProvedMessages, SourceHeaderChain},
|
target_chain::{ProvedLaneMessages, ProvedMessages, SourceHeaderChain},
|
||||||
InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData,
|
InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData,
|
||||||
VerificationError,
|
VerificationError,
|
||||||
@@ -120,42 +120,6 @@ pub mod source {
|
|||||||
pub type ParsedMessagesDeliveryProofFromBridgedChain<B> =
|
pub type ParsedMessagesDeliveryProofFromBridgedChain<B> =
|
||||||
(LaneId, InboundLaneData<AccountIdOf<ThisChain<B>>>);
|
(LaneId, InboundLaneData<AccountIdOf<ThisChain<B>>>);
|
||||||
|
|
||||||
/// Message verifier that is doing all basic checks.
|
|
||||||
///
|
|
||||||
/// This verifier assumes following:
|
|
||||||
///
|
|
||||||
/// - all message lanes are equivalent, so all checks are the same;
|
|
||||||
///
|
|
||||||
/// Following checks are made:
|
|
||||||
///
|
|
||||||
/// - message is rejected if its lane is currently blocked;
|
|
||||||
/// - message is rejected if there are too many pending (undelivered) messages at the outbound
|
|
||||||
/// lane;
|
|
||||||
/// - check that the sender has rights to dispatch the call on target chain using provided
|
|
||||||
/// dispatch origin;
|
|
||||||
/// - check that the sender has paid enough funds for both message delivery and dispatch.
|
|
||||||
#[derive(RuntimeDebug)]
|
|
||||||
pub struct FromThisChainMessageVerifier<B>(PhantomData<B>);
|
|
||||||
|
|
||||||
impl<B> LaneMessageVerifier<FromThisChainMessagePayload> for FromThisChainMessageVerifier<B>
|
|
||||||
where
|
|
||||||
B: MessageBridge,
|
|
||||||
{
|
|
||||||
fn verify_message(
|
|
||||||
_lane: &LaneId,
|
|
||||||
_lane_outbound_data: &OutboundLaneData,
|
|
||||||
_payload: &FromThisChainMessagePayload,
|
|
||||||
) -> Result<(), VerificationError> {
|
|
||||||
// IMPORTANT: any error that is returned here is fatal for the bridge, because
|
|
||||||
// this code is executed at the bridge hub and message sender actually lives
|
|
||||||
// at some sibling parachain. So we are failing **after** the message has been
|
|
||||||
// sent and we can't report it back to sender (unless error report mechanism is
|
|
||||||
// embedded into message and its dispatcher).
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return maximal message size of This -> Bridged chain message.
|
/// Return maximal message size of This -> Bridged chain message.
|
||||||
pub fn maximal_message_size<B: MessageBridge>() -> u32 {
|
pub fn maximal_message_size<B: MessageBridge>() -> u32 {
|
||||||
super::target::maximal_incoming_message_size(
|
super::target::maximal_incoming_message_size(
|
||||||
@@ -185,8 +149,7 @@ pub mod source {
|
|||||||
/// Do basic Bridged-chain specific verification of This -> Bridged chain message.
|
/// Do basic Bridged-chain specific verification of This -> Bridged chain message.
|
||||||
///
|
///
|
||||||
/// Ok result from this function means that the delivery transaction with this message
|
/// Ok result from this function means that the delivery transaction with this message
|
||||||
/// may be 'mined' by the target chain. But the lane may have its own checks (e.g. fee
|
/// may be 'mined' by the target chain.
|
||||||
/// check) that would reject message (see `FromThisChainMessageVerifier`).
|
|
||||||
pub fn verify_chain_message<B: MessageBridge>(
|
pub fn verify_chain_message<B: MessageBridge>(
|
||||||
payload: &FromThisChainMessagePayload,
|
payload: &FromThisChainMessagePayload,
|
||||||
) -> Result<(), VerificationError> {
|
) -> Result<(), VerificationError> {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
use crate::messages::{
|
use crate::messages::{
|
||||||
source::{
|
source::{
|
||||||
FromThisChainMaximalOutboundPayloadSize, FromThisChainMessagePayload,
|
FromThisChainMaximalOutboundPayloadSize, FromThisChainMessagePayload,
|
||||||
FromThisChainMessageVerifier, TargetHeaderChainAdapter,
|
TargetHeaderChainAdapter,
|
||||||
},
|
},
|
||||||
target::{FromBridgedChainMessagePayload, SourceHeaderChainAdapter},
|
target::{FromBridgedChainMessagePayload, SourceHeaderChainAdapter},
|
||||||
BridgedChainWithMessages, HashOf, MessageBridge, ThisChainWithMessages,
|
BridgedChainWithMessages, HashOf, MessageBridge, ThisChainWithMessages,
|
||||||
@@ -213,7 +213,6 @@ impl pallet_bridge_messages::Config for TestRuntime {
|
|||||||
type DeliveryPayments = ();
|
type DeliveryPayments = ();
|
||||||
|
|
||||||
type TargetHeaderChain = TargetHeaderChainAdapter<OnThisChainBridge>;
|
type TargetHeaderChain = TargetHeaderChainAdapter<OnThisChainBridge>;
|
||||||
type LaneMessageVerifier = FromThisChainMessageVerifier<OnThisChainBridge>;
|
|
||||||
type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter<
|
type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter<
|
||||||
TestRuntime,
|
TestRuntime,
|
||||||
(),
|
(),
|
||||||
|
|||||||
@@ -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
|
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.
|
(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
|
The last type is the `pallet_bridge_messages::Config::DeliveryConfirmationPayments`. When confirmation
|
||||||
simplest callback may just accept all messages. But in this case you'll need to answer many questions first. Who will
|
transaction is received, we call the `pay_reward()` method, passing the range of delivered messages.
|
||||||
pay for the delivery and confirmation transaction? Are we sure that someone will ever deliver this message to the
|
You may use the [`pallet-bridge-relayers`](../relayers/) pallet and its
|
||||||
bridged chain? Are we sure that we don't bloat our runtime storage by accepting this message? What if the message is
|
[`DeliveryConfirmationPaymentsAdapter`](../relayers/src/payment_adapter.rs) adapter as a possible
|
||||||
improperly encoded or has some fields set to invalid values? Answering all those (and similar) questions would lead to
|
implementation. It allows you to pay fixed reward for relaying the message and some of its portion
|
||||||
correct implementation.
|
for confirming delivery.
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
### I have a Messages Module in my Runtime, but I Want to Reject all Outbound Messages. What shall I do?
|
### I have a Messages Module in my Runtime, but I Want to Reject all Outbound Messages. What shall I do?
|
||||||
|
|
||||||
|
|||||||
@@ -53,8 +53,7 @@ use crate::{
|
|||||||
|
|
||||||
use bp_messages::{
|
use bp_messages::{
|
||||||
source_chain::{
|
source_chain::{
|
||||||
DeliveryConfirmationPayments, LaneMessageVerifier, OnMessagesDelivered,
|
DeliveryConfirmationPayments, OnMessagesDelivered, SendMessageArtifacts, TargetHeaderChain,
|
||||||
SendMessageArtifacts, TargetHeaderChain,
|
|
||||||
},
|
},
|
||||||
target_chain::{
|
target_chain::{
|
||||||
DeliveryPayments, DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages,
|
DeliveryPayments, DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages,
|
||||||
@@ -155,8 +154,6 @@ pub mod pallet {
|
|||||||
|
|
||||||
/// Target header chain.
|
/// Target header chain.
|
||||||
type TargetHeaderChain: TargetHeaderChain<Self::OutboundPayload, Self::AccountId>;
|
type TargetHeaderChain: TargetHeaderChain<Self::OutboundPayload, Self::AccountId>;
|
||||||
/// Message payload verifier.
|
|
||||||
type LaneMessageVerifier: LaneMessageVerifier<Self::OutboundPayload>;
|
|
||||||
/// Delivery confirmation payments.
|
/// Delivery confirmation payments.
|
||||||
type DeliveryConfirmationPayments: DeliveryConfirmationPayments<Self::AccountId>;
|
type DeliveryConfirmationPayments: DeliveryConfirmationPayments<Self::AccountId>;
|
||||||
/// Delivery confirmation callback.
|
/// Delivery confirmation callback.
|
||||||
@@ -723,20 +720,8 @@ fn send_message<T: Config<I>, I: 'static>(
|
|||||||
Error::<T, I>::MessageRejectedByChainVerifier(err)
|
Error::<T, I>::MessageRejectedByChainVerifier(err)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// 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
|
// finally, save message in outbound storage and emit event
|
||||||
|
let mut lane = outbound_lane::<T, I>(lane_id);
|
||||||
let encoded_payload = payload.encode();
|
let encoded_payload = payload.encode();
|
||||||
let encoded_payload_len = encoded_payload.len();
|
let encoded_payload_len = encoded_payload.len();
|
||||||
let nonce = lane
|
let nonce = lane
|
||||||
@@ -1151,21 +1136,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]
|
#[test]
|
||||||
fn receive_messages_proof_works() {
|
fn receive_messages_proof_works() {
|
||||||
run_test(|| {
|
run_test(|| {
|
||||||
|
|||||||
@@ -21,15 +21,13 @@ use crate::Config;
|
|||||||
|
|
||||||
use bp_messages::{
|
use bp_messages::{
|
||||||
calc_relayers_rewards,
|
calc_relayers_rewards,
|
||||||
source_chain::{
|
source_chain::{DeliveryConfirmationPayments, OnMessagesDelivered, TargetHeaderChain},
|
||||||
DeliveryConfirmationPayments, LaneMessageVerifier, OnMessagesDelivered, TargetHeaderChain,
|
|
||||||
},
|
|
||||||
target_chain::{
|
target_chain::{
|
||||||
DeliveryPayments, DispatchMessage, DispatchMessageData, MessageDispatch,
|
DeliveryPayments, DispatchMessage, DispatchMessageData, MessageDispatch,
|
||||||
ProvedLaneMessages, ProvedMessages, SourceHeaderChain,
|
ProvedLaneMessages, ProvedMessages, SourceHeaderChain,
|
||||||
},
|
},
|
||||||
DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload,
|
DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload,
|
||||||
OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState, VerificationError,
|
UnrewardedRelayer, UnrewardedRelayersState, VerificationError,
|
||||||
};
|
};
|
||||||
use bp_runtime::{messages::MessageDispatchResult, Size};
|
use bp_runtime::{messages::MessageDispatchResult, Size};
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
@@ -50,8 +48,6 @@ pub type Balance = u64;
|
|||||||
pub struct TestPayload {
|
pub struct TestPayload {
|
||||||
/// Field that may be used to identify messages.
|
/// Field that may be used to identify messages.
|
||||||
pub id: u64,
|
pub id: u64,
|
||||||
/// Reject this message by lane verifier?
|
|
||||||
pub reject_by_lane_verifier: bool,
|
|
||||||
/// Dispatch weight that is declared by the message sender.
|
/// Dispatch weight that is declared by the message sender.
|
||||||
pub declared_weight: Weight,
|
pub declared_weight: Weight,
|
||||||
/// Message dispatch result.
|
/// Message dispatch result.
|
||||||
@@ -120,7 +116,6 @@ impl Config for TestRuntime {
|
|||||||
type DeliveryPayments = TestDeliveryPayments;
|
type DeliveryPayments = TestDeliveryPayments;
|
||||||
|
|
||||||
type TargetHeaderChain = TestTargetHeaderChain;
|
type TargetHeaderChain = TestTargetHeaderChain;
|
||||||
type LaneMessageVerifier = TestLaneMessageVerifier;
|
|
||||||
type DeliveryConfirmationPayments = TestDeliveryConfirmationPayments;
|
type DeliveryConfirmationPayments = TestDeliveryConfirmationPayments;
|
||||||
type OnMessagesDelivered = TestOnMessagesDelivered;
|
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.
|
/// Reward payments at the target chain during delivery transaction.
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct TestDeliveryPayments;
|
pub struct TestDeliveryPayments;
|
||||||
@@ -438,7 +415,6 @@ pub fn inbound_message_data(payload: TestPayload) -> DispatchMessageData<TestPay
|
|||||||
pub const fn message_payload(id: u64, declared_weight: u64) -> TestPayload {
|
pub const fn message_payload(id: u64, declared_weight: u64) -> TestPayload {
|
||||||
TestPayload {
|
TestPayload {
|
||||||
id,
|
id,
|
||||||
reject_by_lane_verifier: false,
|
|
||||||
declared_weight: Weight::from_parts(declared_weight, 0),
|
declared_weight: Weight::from_parts(declared_weight, 0),
|
||||||
dispatch_result: dispatch_result(0),
|
dispatch_result: dispatch_result(0),
|
||||||
extra: Vec::new(),
|
extra: Vec::new(),
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
//! Primitives of messages module, that are used on the source chain.
|
//! Primitives of messages module, that are used on the source chain.
|
||||||
|
|
||||||
use crate::{InboundLaneData, LaneId, MessageNonce, OutboundLaneData, VerificationError};
|
use crate::{InboundLaneData, LaneId, MessageNonce, VerificationError};
|
||||||
|
|
||||||
use crate::UnrewardedRelayer;
|
use crate::UnrewardedRelayer;
|
||||||
use bp_runtime::Size;
|
use bp_runtime::Size;
|
||||||
@@ -64,24 +64,6 @@ pub trait TargetHeaderChain<Payload, AccountId> {
|
|||||||
) -> Result<(LaneId, InboundLaneData<AccountId>), VerificationError>;
|
) -> Result<(LaneId, InboundLaneData<AccountId>), VerificationError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lane message verifier.
|
|
||||||
///
|
|
||||||
/// Runtime developer may implement any additional validation logic over message-lane mechanism.
|
|
||||||
/// E.g. if lanes should have some security (e.g. you can only accept Lane1 messages from
|
|
||||||
/// Submitter1, Lane2 messages for those who has submitted first message to this lane, disable
|
|
||||||
/// Lane3 until some block, ...), then it may be built using this verifier.
|
|
||||||
///
|
|
||||||
/// Any fee requirements should also be enforced here.
|
|
||||||
pub trait LaneMessageVerifier<Payload> {
|
|
||||||
/// Verify message payload and return Ok(()) if message is valid and allowed to be sent over the
|
|
||||||
/// lane.
|
|
||||||
fn verify_message(
|
|
||||||
lane: &LaneId,
|
|
||||||
outbound_data: &OutboundLaneData,
|
|
||||||
payload: &Payload,
|
|
||||||
) -> Result<(), VerificationError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Manages payments that are happening at the source chain during delivery confirmation
|
/// Manages payments that are happening at the source chain during delivery confirmation
|
||||||
/// transaction.
|
/// transaction.
|
||||||
pub trait DeliveryConfirmationPayments<AccountId> {
|
pub trait DeliveryConfirmationPayments<AccountId> {
|
||||||
@@ -161,7 +143,7 @@ impl<Payload> MessagesBridge<Payload> for NoopMessagesBridge {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Structure that may be used in place of `TargetHeaderChain`, `LaneMessageVerifier` and
|
/// Structure that may be used in place of `TargetHeaderChain` and
|
||||||
/// `MessageDeliveryAndDispatchPayment` on chains, where outbound messages are forbidden.
|
/// `MessageDeliveryAndDispatchPayment` on chains, where outbound messages are forbidden.
|
||||||
pub struct ForbidOutboundMessages;
|
pub struct ForbidOutboundMessages;
|
||||||
|
|
||||||
@@ -183,16 +165,6 @@ impl<Payload, AccountId> TargetHeaderChain<Payload, AccountId> for ForbidOutboun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Payload> LaneMessageVerifier<Payload> for ForbidOutboundMessages {
|
|
||||||
fn verify_message(
|
|
||||||
_lane: &LaneId,
|
|
||||||
_outbound_data: &OutboundLaneData,
|
|
||||||
_payload: &Payload,
|
|
||||||
) -> Result<(), VerificationError> {
|
|
||||||
Err(VerificationError::Other(ALL_OUTBOUND_MESSAGES_REJECTED))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<AccountId> DeliveryConfirmationPayments<AccountId> for ForbidOutboundMessages {
|
impl<AccountId> DeliveryConfirmationPayments<AccountId> for ForbidOutboundMessages {
|
||||||
type Error = &'static str;
|
type Error = &'static str;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user