mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 17:31:05 +00:00
Support dedicated lanes for pallets (#962)
* pass call origin to the message verifier * is_outbound_lane_enabled -> is_message_accepted * trait SenderOrigin * only accept messages from token swap pallet to token swap lane * tests for edge cases of pay_delivery_and_dispatch_fee * fixed origin verification * fmt * fix benchmarks compilation * fix TODO with None account and non-zero message fee (already covered by tests) * revert cargo fmt changes temporarily
This commit is contained in:
committed by
Bastian Köcher
parent
7b7b8baa60
commit
ed2a3082ef
@@ -22,7 +22,7 @@
|
||||
|
||||
use bp_message_dispatch::MessageDispatch as _;
|
||||
use bp_messages::{
|
||||
source_chain::{LaneMessageVerifier, Sender},
|
||||
source_chain::LaneMessageVerifier,
|
||||
target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages},
|
||||
InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData,
|
||||
};
|
||||
@@ -111,11 +111,13 @@ pub struct MessageTransaction<Weight> {
|
||||
|
||||
/// This chain that has `pallet-bridge-messages` and `dispatch` modules.
|
||||
pub trait ThisChainWithMessages: ChainWithMessages {
|
||||
/// Call origin on the chain.
|
||||
type Origin;
|
||||
/// Call type on the chain.
|
||||
type Call: Encode + Decode;
|
||||
|
||||
/// Are we accepting any messages to the given lane?
|
||||
fn is_outbound_lane_enabled(lane: &LaneId) -> bool;
|
||||
/// Do we accept message sent by given origin to given lane?
|
||||
fn is_message_accepted(origin: &Self::Origin, lane: &LaneId) -> bool;
|
||||
|
||||
/// Maximal number of pending (not yet delivered) messages at This chain.
|
||||
///
|
||||
@@ -173,6 +175,8 @@ pub type SignatureOf<C> = <C as ChainWithMessages>::Signature;
|
||||
pub type WeightOf<C> = <C as ChainWithMessages>::Weight;
|
||||
/// Type of balances that is used on the chain.
|
||||
pub type BalanceOf<C> = <C as ChainWithMessages>::Balance;
|
||||
/// Type of origin that is used on the chain.
|
||||
pub type OriginOf<C> = <C as ThisChainWithMessages>::Origin;
|
||||
/// Type of call that is used on this chain.
|
||||
pub type CallOf<C> = <C as ThisChainWithMessages>::Call;
|
||||
|
||||
@@ -270,7 +274,8 @@ pub mod source {
|
||||
pub struct FromThisChainMessageVerifier<B>(PhantomData<B>);
|
||||
|
||||
/// The error message returned from LaneMessageVerifier when outbound lane is disabled.
|
||||
pub const OUTBOUND_LANE_DISABLED: &str = "The outbound message lane is disabled.";
|
||||
pub const MESSAGE_REJECTED_BY_OUTBOUND_LANE: &str =
|
||||
"The outbound message lane has rejected the message.";
|
||||
/// The error message returned from LaneMessageVerifier when too many pending messages at the
|
||||
/// lane.
|
||||
pub const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane.";
|
||||
@@ -281,26 +286,30 @@ pub mod source {
|
||||
|
||||
impl<B>
|
||||
LaneMessageVerifier<
|
||||
OriginOf<ThisChain<B>>,
|
||||
AccountIdOf<ThisChain<B>>,
|
||||
FromThisChainMessagePayload<B>,
|
||||
BalanceOf<ThisChain<B>>,
|
||||
> for FromThisChainMessageVerifier<B>
|
||||
where
|
||||
B: MessageBridge,
|
||||
// matches requirements from the `frame_system::Config::Origin`
|
||||
OriginOf<ThisChain<B>>: Clone
|
||||
+ Into<Result<frame_system::RawOrigin<AccountIdOf<ThisChain<B>>>, OriginOf<ThisChain<B>>>>,
|
||||
AccountIdOf<ThisChain<B>>: PartialEq + Clone,
|
||||
{
|
||||
type Error = &'static str;
|
||||
|
||||
fn verify_message(
|
||||
submitter: &Sender<AccountIdOf<ThisChain<B>>>,
|
||||
submitter: &OriginOf<ThisChain<B>>,
|
||||
delivery_and_dispatch_fee: &BalanceOf<ThisChain<B>>,
|
||||
lane: &LaneId,
|
||||
lane_outbound_data: &OutboundLaneData,
|
||||
payload: &FromThisChainMessagePayload<B>,
|
||||
) -> Result<(), Self::Error> {
|
||||
// reject message if lane is blocked
|
||||
if !ThisChain::<B>::is_outbound_lane_enabled(lane) {
|
||||
return Err(OUTBOUND_LANE_DISABLED)
|
||||
if !ThisChain::<B>::is_message_accepted(submitter, lane) {
|
||||
return Err(MESSAGE_REJECTED_BY_OUTBOUND_LANE)
|
||||
}
|
||||
|
||||
// reject message if there are too many pending messages at this lane
|
||||
@@ -314,8 +323,23 @@ pub mod source {
|
||||
|
||||
// Do the dispatch-specific check. We assume that the target chain uses
|
||||
// `Dispatch`, so we verify the message accordingly.
|
||||
pallet_bridge_dispatch::verify_message_origin(submitter, payload)
|
||||
.map_err(|_| BAD_ORIGIN)?;
|
||||
let raw_origin_or_err: Result<
|
||||
frame_system::RawOrigin<AccountIdOf<ThisChain<B>>>,
|
||||
OriginOf<ThisChain<B>>,
|
||||
> = submitter.clone().into();
|
||||
match raw_origin_or_err {
|
||||
Ok(raw_origin) =>
|
||||
pallet_bridge_dispatch::verify_message_origin(&raw_origin, payload)
|
||||
.map(drop)
|
||||
.map_err(|_| BAD_ORIGIN)?,
|
||||
Err(_) => {
|
||||
// so what it means that we've failed to convert origin to the
|
||||
// `frame_system::RawOrigin`? now it means that the custom pallet origin has
|
||||
// been used to send the message. Do we need to verify it? The answer is no,
|
||||
// because pallet may craft any origin (e.g. root) && we can't verify whether it
|
||||
// is valid, or not.
|
||||
},
|
||||
};
|
||||
|
||||
let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::<B>(
|
||||
payload,
|
||||
@@ -854,6 +878,18 @@ mod tests {
|
||||
#[codec(index = 84)]
|
||||
Mint,
|
||||
}
|
||||
#[derive(Clone, Debug)]
|
||||
struct ThisChainOrigin(Result<frame_system::RawOrigin<ThisChainAccountId>, ()>);
|
||||
|
||||
impl From<ThisChainOrigin>
|
||||
for Result<frame_system::RawOrigin<ThisChainAccountId>, ThisChainOrigin>
|
||||
{
|
||||
fn from(
|
||||
origin: ThisChainOrigin,
|
||||
) -> Result<frame_system::RawOrigin<ThisChainAccountId>, ThisChainOrigin> {
|
||||
origin.clone().0.map_err(|_| origin)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Decode, Encode)]
|
||||
struct BridgedChainAccountId(u32);
|
||||
@@ -863,6 +899,18 @@ mod tests {
|
||||
struct BridgedChainSignature(u32);
|
||||
#[derive(Debug, PartialEq, Decode, Encode)]
|
||||
enum BridgedChainCall {}
|
||||
#[derive(Clone, Debug)]
|
||||
struct BridgedChainOrigin;
|
||||
|
||||
impl From<BridgedChainOrigin>
|
||||
for Result<frame_system::RawOrigin<BridgedChainAccountId>, BridgedChainOrigin>
|
||||
{
|
||||
fn from(
|
||||
_origin: BridgedChainOrigin,
|
||||
) -> Result<frame_system::RawOrigin<BridgedChainAccountId>, BridgedChainOrigin> {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_wrapped_balance {
|
||||
($name:ident) => {
|
||||
@@ -940,9 +988,10 @@ mod tests {
|
||||
}
|
||||
|
||||
impl ThisChainWithMessages for ThisChain {
|
||||
type Origin = ThisChainOrigin;
|
||||
type Call = ThisChainCall;
|
||||
|
||||
fn is_outbound_lane_enabled(lane: &LaneId) -> bool {
|
||||
fn is_message_accepted(_send_origin: &Self::Origin, lane: &LaneId) -> bool {
|
||||
lane == TEST_LANE_ID
|
||||
}
|
||||
|
||||
@@ -1000,9 +1049,10 @@ mod tests {
|
||||
}
|
||||
|
||||
impl ThisChainWithMessages for BridgedChain {
|
||||
type Origin = BridgedChainOrigin;
|
||||
type Call = BridgedChainCall;
|
||||
|
||||
fn is_outbound_lane_enabled(_lane: &LaneId) -> bool {
|
||||
fn is_message_accepted(_send_origin: &Self::Origin, _lane: &LaneId) -> bool {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
@@ -1141,7 +1191,7 @@ mod tests {
|
||||
// and now check that the verifier checks the fee
|
||||
assert_eq!(
|
||||
source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
|
||||
&Sender::Root,
|
||||
&ThisChainOrigin(Ok(frame_system::RawOrigin::Root)),
|
||||
&ThisChainBalance(1),
|
||||
TEST_LANE_ID,
|
||||
&test_lane_outbound_data(),
|
||||
@@ -1150,7 +1200,7 @@ mod tests {
|
||||
Err(source::TOO_LOW_FEE)
|
||||
);
|
||||
assert!(source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
|
||||
&Sender::Root,
|
||||
&ThisChainOrigin(Ok(frame_system::RawOrigin::Root)),
|
||||
&ThisChainBalance(1_000_000),
|
||||
TEST_LANE_ID,
|
||||
&test_lane_outbound_data(),
|
||||
@@ -1173,7 +1223,7 @@ mod tests {
|
||||
// and now check that the verifier checks the fee
|
||||
assert_eq!(
|
||||
source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
|
||||
&Sender::Signed(ThisChainAccountId(0)),
|
||||
&ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(0)))),
|
||||
&ThisChainBalance(1_000_000),
|
||||
TEST_LANE_ID,
|
||||
&test_lane_outbound_data(),
|
||||
@@ -1183,7 +1233,7 @@ mod tests {
|
||||
);
|
||||
assert_eq!(
|
||||
source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
|
||||
&Sender::None,
|
||||
&ThisChainOrigin(Ok(frame_system::RawOrigin::None)),
|
||||
&ThisChainBalance(1_000_000),
|
||||
TEST_LANE_ID,
|
||||
&test_lane_outbound_data(),
|
||||
@@ -1192,7 +1242,7 @@ mod tests {
|
||||
Err(source::BAD_ORIGIN)
|
||||
);
|
||||
assert!(source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
|
||||
&Sender::Root,
|
||||
&ThisChainOrigin(Ok(frame_system::RawOrigin::Root)),
|
||||
&ThisChainBalance(1_000_000),
|
||||
TEST_LANE_ID,
|
||||
&test_lane_outbound_data(),
|
||||
@@ -1215,7 +1265,7 @@ mod tests {
|
||||
// and now check that the verifier checks the fee
|
||||
assert_eq!(
|
||||
source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
|
||||
&Sender::Signed(ThisChainAccountId(0)),
|
||||
&ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(0)))),
|
||||
&ThisChainBalance(1_000_000),
|
||||
TEST_LANE_ID,
|
||||
&test_lane_outbound_data(),
|
||||
@@ -1224,7 +1274,7 @@ mod tests {
|
||||
Err(source::BAD_ORIGIN)
|
||||
);
|
||||
assert!(source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
|
||||
&Sender::Signed(ThisChainAccountId(1)),
|
||||
&ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(1)))),
|
||||
&ThisChainBalance(1_000_000),
|
||||
TEST_LANE_ID,
|
||||
&test_lane_outbound_data(),
|
||||
@@ -1237,13 +1287,13 @@ mod tests {
|
||||
fn message_is_rejected_when_sent_using_disabled_lane() {
|
||||
assert_eq!(
|
||||
source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
|
||||
&Sender::Root,
|
||||
&ThisChainOrigin(Ok(frame_system::RawOrigin::Root)),
|
||||
&ThisChainBalance(1_000_000),
|
||||
b"dsbl",
|
||||
&test_lane_outbound_data(),
|
||||
®ular_outbound_message_payload(),
|
||||
),
|
||||
Err(source::OUTBOUND_LANE_DISABLED)
|
||||
Err(source::MESSAGE_REJECTED_BY_OUTBOUND_LANE)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1251,7 +1301,7 @@ mod tests {
|
||||
fn message_is_rejected_when_there_are_too_many_pending_messages_at_outbound_lane() {
|
||||
assert_eq!(
|
||||
source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
|
||||
&Sender::Root,
|
||||
&ThisChainOrigin(Ok(frame_system::RawOrigin::Root)),
|
||||
&ThisChainBalance(1_000_000),
|
||||
TEST_LANE_ID,
|
||||
&OutboundLaneData {
|
||||
|
||||
Reference in New Issue
Block a user