mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 19:51:02 +00:00
Pre-dispatch call filter (#687)
* pre-dispatch call filter * swap filter <-> weight * clippy * fmt
This commit is contained in:
committed by
Bastian Köcher
parent
a9e607c9a2
commit
8ee90afae6
@@ -215,6 +215,7 @@ impl pallet_bridge_call_dispatch::Config for Runtime {
|
||||
type Event = Event;
|
||||
type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce);
|
||||
type Call = Call;
|
||||
type CallFilter = ();
|
||||
type EncodedCall = crate::rialto_messages::FromRialtoEncodedCall;
|
||||
type SourceChainAccountId = bp_rialto::AccountId;
|
||||
type TargetChainAccountPublic = MultiSigner;
|
||||
|
||||
@@ -266,6 +266,7 @@ impl pallet_bridge_call_dispatch::Config for Runtime {
|
||||
type Event = Event;
|
||||
type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce);
|
||||
type Call = Call;
|
||||
type CallFilter = ();
|
||||
type EncodedCall = crate::millau_messages::FromMillauEncodedCall;
|
||||
type SourceChainAccountId = bp_millau::AccountId;
|
||||
type TargetChainAccountPublic = MultiSigner;
|
||||
|
||||
@@ -31,7 +31,7 @@ use frame_support::{
|
||||
decl_event, decl_module, decl_storage,
|
||||
dispatch::{Dispatchable, Parameter},
|
||||
ensure,
|
||||
traits::Get,
|
||||
traits::{Filter, Get},
|
||||
weights::{extract_actual_weight, GetDispatchInfo},
|
||||
RuntimeDebug,
|
||||
};
|
||||
@@ -134,6 +134,11 @@ pub trait Config<I = DefaultInstance>: frame_system::Config {
|
||||
Origin = <Self as frame_system::Config>::Origin,
|
||||
PostInfo = frame_support::dispatch::PostDispatchInfo,
|
||||
>;
|
||||
/// Pre-dispatch filter for incoming calls.
|
||||
///
|
||||
/// The pallet will filter all incoming calls right before they're dispatched. If this filter
|
||||
/// rejects the call, special event (`Event::MessageCallRejected`) is emitted.
|
||||
type CallFilter: Filter<<Self as Config<I>>::Call>;
|
||||
/// The type that is used to wrap the `Self::Call` when it is moved over bridge.
|
||||
///
|
||||
/// The idea behind this is to avoid `Call` conversion/decoding until we'll be sure
|
||||
@@ -172,6 +177,8 @@ decl_event!(
|
||||
MessageDispatched(InstanceId, MessageId, DispatchResult),
|
||||
/// We have failed to decode Call from the message.
|
||||
MessageCallDecodeFailed(InstanceId, MessageId),
|
||||
/// The call from the message has been rejected by the call filter.
|
||||
MessageCallRejected(InstanceId, MessageId),
|
||||
/// Phantom member, never used. Needed to handle multiple pallet instances.
|
||||
_Dummy(PhantomData<I>),
|
||||
}
|
||||
@@ -269,6 +276,18 @@ impl<T: Config<I>, I: Instance> MessageDispatch<T::MessageId> for Module<T, I> {
|
||||
}
|
||||
};
|
||||
|
||||
// filter the call
|
||||
if !T::CallFilter::filter(&call) {
|
||||
frame_support::debug::trace!(
|
||||
"Message {:?}/{:?}: the call ({:?}) is rejected by filter",
|
||||
bridge,
|
||||
id,
|
||||
call,
|
||||
);
|
||||
Self::deposit_event(RawEvent::MessageCallRejected(bridge, id));
|
||||
return;
|
||||
}
|
||||
|
||||
// verify weight
|
||||
// (we want passed weight to be at least equal to pre-dispatch weight of the call
|
||||
// because otherwise Calls may be dispatched at lower price)
|
||||
@@ -488,6 +507,7 @@ mod tests {
|
||||
type TargetChainAccountPublic = TestAccountPublic;
|
||||
type TargetChainSignature = TestSignature;
|
||||
type Call = Call;
|
||||
type CallFilter = TestCallFilter;
|
||||
type EncodedCall = EncodedCall;
|
||||
type AccountIdConverter = AccountIdConverter;
|
||||
}
|
||||
@@ -501,6 +521,14 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TestCallFilter;
|
||||
|
||||
impl Filter<Call> for TestCallFilter {
|
||||
fn filter(call: &Call) -> bool {
|
||||
!matches!(*call, Call::System(frame_system::Call::fill_block(_)))
|
||||
}
|
||||
}
|
||||
|
||||
const TEST_SPEC_VERSION: SpecVersion = 0;
|
||||
const TEST_WEIGHT: Weight = 1_000_000_000;
|
||||
|
||||
@@ -668,6 +696,31 @@ 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)));
|
||||
let weight = call.get_dispatch_info().weight;
|
||||
let mut message = prepare_root_message(call);
|
||||
message.weight = weight;
|
||||
|
||||
System::set_block_number(1);
|
||||
CallDispatch::dispatch(bridge, id, Ok(message));
|
||||
|
||||
assert_eq!(
|
||||
System::events(),
|
||||
vec![EventRecord {
|
||||
phase: Phase::Initialization,
|
||||
event: TestEvent::call_dispatch(Event::<TestRuntime>::MessageCallRejected(bridge, id)),
|
||||
topics: vec![],
|
||||
}],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_dispatch_bridge_message_from_root_origin() {
|
||||
new_test_ext().execute_with(|| {
|
||||
|
||||
Reference in New Issue
Block a user