mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-19 04:11:09 +00:00
Reduce the number of macros used for SignedExtensions
Reduce the number of macros used for SignedExtensions Signed-off-by: Serban Iorga <serban@parity.io>
This commit is contained in:
committed by
Bastian Köcher
parent
057fd6cab2
commit
5d9bd1d0b5
@@ -78,7 +78,7 @@ pub use frame_support::{
|
|||||||
constants::WEIGHT_PER_SECOND, ConstantMultiplier, DispatchClass, IdentityFee,
|
constants::WEIGHT_PER_SECOND, ConstantMultiplier, DispatchClass, IdentityFee,
|
||||||
RuntimeDbWeight, Weight,
|
RuntimeDbWeight, Weight,
|
||||||
},
|
},
|
||||||
StorageValue,
|
RuntimeDebug, StorageValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use frame_system::Call as SystemCall;
|
pub use frame_system::Call as SystemCall;
|
||||||
@@ -89,6 +89,7 @@ pub use pallet_bridge_parachains::Call as BridgeParachainsCall;
|
|||||||
pub use pallet_sudo::Call as SudoCall;
|
pub use pallet_sudo::Call as SudoCall;
|
||||||
pub use pallet_timestamp::Call as TimestampCall;
|
pub use pallet_timestamp::Call as TimestampCall;
|
||||||
|
|
||||||
|
use bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages;
|
||||||
#[cfg(any(feature = "std", test))]
|
#[cfg(any(feature = "std", test))]
|
||||||
pub use sp_runtime::BuildStorage;
|
pub use sp_runtime::BuildStorage;
|
||||||
pub use sp_runtime::{Perbill, Permill};
|
pub use sp_runtime::{Perbill, Permill};
|
||||||
@@ -592,21 +593,14 @@ construct_runtime!(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
pallet_bridge_grandpa::declare_bridge_reject_obsolete_grandpa_header! {
|
generate_bridge_reject_obsolete_headers_and_messages! {
|
||||||
Runtime,
|
Call, AccountId,
|
||||||
Call::BridgeRialtoGrandpa => RialtoGrandpaInstance,
|
// Grandpa
|
||||||
Call::BridgeWestendGrandpa => WestendGrandpaInstance
|
BridgeRialtoGrandpa, BridgeWestendGrandpa,
|
||||||
}
|
// Parachains
|
||||||
|
BridgeRialtoParachains,
|
||||||
pallet_bridge_parachains::declare_bridge_reject_obsolete_parachain_header! {
|
//Messages
|
||||||
Runtime,
|
BridgeRialtoMessages, BridgeRialtoParachainMessages
|
||||||
Call::BridgeRialtoParachains => WithRialtoParachainsInstance
|
|
||||||
}
|
|
||||||
|
|
||||||
bridge_runtime_common::declare_bridge_reject_obsolete_messages! {
|
|
||||||
Runtime,
|
|
||||||
Call::BridgeRialtoMessages => WithRialtoMessagesInstance,
|
|
||||||
Call::BridgeRialtoParachainMessages => WithRialtoParachainMessagesInstance
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The address format for describing accounts.
|
/// The address format for describing accounts.
|
||||||
@@ -629,9 +623,7 @@ pub type SignedExtra = (
|
|||||||
frame_system::CheckNonce<Runtime>,
|
frame_system::CheckNonce<Runtime>,
|
||||||
frame_system::CheckWeight<Runtime>,
|
frame_system::CheckWeight<Runtime>,
|
||||||
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
|
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
|
||||||
BridgeRejectObsoleteGrandpaHeader,
|
BridgeRejectObsoleteHeadersAndMessages,
|
||||||
BridgeRejectObsoleteParachainHeader,
|
|
||||||
BridgeRejectObsoleteMessages,
|
|
||||||
);
|
);
|
||||||
/// The payload being signed in transactions.
|
/// The payload being signed in transactions.
|
||||||
pub type SignedPayload = generic::SignedPayload<Call, SignedExtra>;
|
pub type SignedPayload = generic::SignedPayload<Call, SignedExtra>;
|
||||||
|
|||||||
@@ -18,6 +18,9 @@
|
|||||||
|
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
use bp_runtime::FilterCall;
|
||||||
|
use sp_runtime::transaction_validity::TransactionValidity;
|
||||||
|
|
||||||
pub mod messages;
|
pub mod messages;
|
||||||
pub mod messages_api;
|
pub mod messages_api;
|
||||||
pub mod messages_benchmarking;
|
pub mod messages_benchmarking;
|
||||||
@@ -26,3 +29,167 @@ pub mod parachains_benchmarking;
|
|||||||
|
|
||||||
#[cfg(feature = "integrity-test")]
|
#[cfg(feature = "integrity-test")]
|
||||||
pub mod integrity;
|
pub mod integrity;
|
||||||
|
|
||||||
|
/// A duplication of the `FilterCall` trait.
|
||||||
|
///
|
||||||
|
/// We need this trait in order to be able to implement it for the messages pallet,
|
||||||
|
/// since the implementation is done outside of the pallet crate.
|
||||||
|
pub trait BridgeRuntimeFilterCall<Call> {
|
||||||
|
/// Checks if a runtime call is valid.
|
||||||
|
fn validate(call: &Call) -> TransactionValidity;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Call, T, I> BridgeRuntimeFilterCall<Call> for pallet_bridge_grandpa::Pallet<T, I>
|
||||||
|
where
|
||||||
|
pallet_bridge_grandpa::Pallet<T, I>: FilterCall<Call>,
|
||||||
|
{
|
||||||
|
fn validate(call: &Call) -> TransactionValidity {
|
||||||
|
<pallet_bridge_grandpa::Pallet<T, I> as FilterCall<Call>>::validate(call)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Call, T, I> BridgeRuntimeFilterCall<Call> for pallet_bridge_parachains::Pallet<T, I>
|
||||||
|
where
|
||||||
|
pallet_bridge_parachains::Pallet<T, I>: FilterCall<Call>,
|
||||||
|
{
|
||||||
|
fn validate(call: &Call) -> TransactionValidity {
|
||||||
|
<pallet_bridge_parachains::Pallet<T, I> as FilterCall<Call>>::validate(call)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Declares a runtime-specific `BridgeRejectObsoleteHeadersAndMessages` signed extension.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
///
|
||||||
|
/// ```nocompile
|
||||||
|
/// generate_bridge_reject_obsolete_headers_and_messages!{
|
||||||
|
/// Call, AccountId
|
||||||
|
/// BridgeRialtoGrandpa, BridgeWestendGrandpa,
|
||||||
|
/// BridgeRialtoParachains
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// The goal of this extension is to avoid "mining" transactions that provide outdated bridged
|
||||||
|
/// headers and messages. Without that extension, even honest relayers may lose their funds if
|
||||||
|
/// there are multiple relays running and submitting the same information.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! generate_bridge_reject_obsolete_headers_and_messages {
|
||||||
|
($call:ty, $account_id:ty, $($filter_call:ty),*) => {
|
||||||
|
#[derive(Clone, codec::Decode, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)]
|
||||||
|
pub struct BridgeRejectObsoleteHeadersAndMessages;
|
||||||
|
impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteHeadersAndMessages {
|
||||||
|
const IDENTIFIER: &'static str = "BridgeRejectObsoleteHeadersAndMessages";
|
||||||
|
type AccountId = $account_id;
|
||||||
|
type Call = $call;
|
||||||
|
type AdditionalSigned = ();
|
||||||
|
type Pre = ();
|
||||||
|
|
||||||
|
fn additional_signed(&self) -> sp_std::result::Result<
|
||||||
|
(),
|
||||||
|
sp_runtime::transaction_validity::TransactionValidityError,
|
||||||
|
> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(
|
||||||
|
&self,
|
||||||
|
_who: &Self::AccountId,
|
||||||
|
call: &Self::Call,
|
||||||
|
_info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
|
||||||
|
_len: usize,
|
||||||
|
) -> sp_runtime::transaction_validity::TransactionValidity {
|
||||||
|
let valid = sp_runtime::transaction_validity::ValidTransaction::default();
|
||||||
|
$(
|
||||||
|
let valid = valid
|
||||||
|
.combine_with(<$filter_call as $crate::BridgeRuntimeFilterCall<$call>>::validate(call)?);
|
||||||
|
)*
|
||||||
|
Ok(valid)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pre_dispatch(
|
||||||
|
self,
|
||||||
|
who: &Self::AccountId,
|
||||||
|
call: &Self::Call,
|
||||||
|
info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
|
||||||
|
len: usize,
|
||||||
|
) -> Result<Self::Pre, sp_runtime::transaction_validity::TransactionValidityError> {
|
||||||
|
self.validate(who, call, info, len).map(drop)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::BridgeRuntimeFilterCall;
|
||||||
|
use frame_support::{assert_err, assert_ok};
|
||||||
|
use sp_runtime::{
|
||||||
|
traits::SignedExtension,
|
||||||
|
transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct MockCall {
|
||||||
|
data: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl sp_runtime::traits::Dispatchable for MockCall {
|
||||||
|
type Origin = ();
|
||||||
|
type Config = ();
|
||||||
|
type Info = ();
|
||||||
|
type PostInfo = ();
|
||||||
|
|
||||||
|
fn dispatch(
|
||||||
|
self,
|
||||||
|
_origin: Self::Origin,
|
||||||
|
) -> sp_runtime::DispatchResultWithInfo<Self::PostInfo> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FirstFilterCall;
|
||||||
|
impl BridgeRuntimeFilterCall<MockCall> for FirstFilterCall {
|
||||||
|
fn validate(call: &MockCall) -> TransactionValidity {
|
||||||
|
if call.data <= 1 {
|
||||||
|
return InvalidTransaction::Custom(1).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ValidTransaction { priority: 1, ..Default::default() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SecondFilterCall;
|
||||||
|
impl BridgeRuntimeFilterCall<MockCall> for SecondFilterCall {
|
||||||
|
fn validate(call: &MockCall) -> TransactionValidity {
|
||||||
|
if call.data <= 2 {
|
||||||
|
return InvalidTransaction::Custom(2).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ValidTransaction { priority: 2, ..Default::default() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test() {
|
||||||
|
generate_bridge_reject_obsolete_headers_and_messages!(
|
||||||
|
MockCall,
|
||||||
|
(),
|
||||||
|
FirstFilterCall,
|
||||||
|
SecondFilterCall
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_err!(
|
||||||
|
BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 1 }, &(), 0),
|
||||||
|
InvalidTransaction::Custom(1)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_err!(
|
||||||
|
BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 2 }, &(), 0),
|
||||||
|
InvalidTransaction::Custom(2)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_ok!(
|
||||||
|
BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 3 }, &(), 0),
|
||||||
|
ValidTransaction { priority: 3, ..Default::default() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,136 +14,100 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// 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/>.
|
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
/// Declares a runtime-specific `BridgeRejectObsoleteMessages` and
|
use crate::{
|
||||||
/// `BridgeRejectObsoleteMessageConfirmations` signed extensions.
|
messages::{
|
||||||
///
|
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
|
||||||
/// ## Example
|
},
|
||||||
///
|
BridgeRuntimeFilterCall,
|
||||||
/// ```nocompile
|
};
|
||||||
/// bridge_runtime_common::declare_bridge_reject_obsolete_messages!{
|
use frame_support::{dispatch::CallableCallFor, traits::IsSubType};
|
||||||
/// Runtime,
|
use pallet_bridge_messages::{Config, Pallet};
|
||||||
/// Call::BridgeRialtoMessages => WithRialtoMessagesInstance,
|
use sp_runtime::transaction_validity::TransactionValidity;
|
||||||
/// Call::BridgeRialtoParachainMessages => WithRialtoParachainMessagesInstance,
|
|
||||||
/// }
|
/// Validate messages in order to avoid "mining" messages delivery and delivery confirmation
|
||||||
/// ```
|
/// transactions, that are delivering outdated messages/confirmations. Without this validation,
|
||||||
///
|
|
||||||
/// The goal of this extension is to avoid "mining" messages delivery and delivery confirmation
|
|
||||||
/// transactions, that are delivering outdated messages/confirmations. Without that extension,
|
|
||||||
/// even honest relayers may lose their funds if there are multiple relays running and submitting
|
/// even honest relayers may lose their funds if there are multiple relays running and submitting
|
||||||
/// the same messages/confirmations.
|
/// the same messages/confirmations.
|
||||||
#[macro_export]
|
impl<
|
||||||
macro_rules! declare_bridge_reject_obsolete_messages {
|
BridgedHeaderHash,
|
||||||
($runtime:ident, $($call:path => $instance:ty),*) => {
|
SourceHeaderChain: bp_messages::target_chain::SourceHeaderChain<
|
||||||
/// Transaction-with-obsolete-messages check that will reject transaction if
|
<T as Config<I>>::InboundMessageFee,
|
||||||
/// it submits obsolete messages/confirmations.
|
MessagesProof = FromBridgedChainMessagesProof<BridgedHeaderHash>,
|
||||||
#[derive(Clone, codec::Decode, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)]
|
>,
|
||||||
pub struct BridgeRejectObsoleteMessages;
|
TargetHeaderChain: bp_messages::source_chain::TargetHeaderChain<
|
||||||
|
<T as Config<I>>::OutboundPayload,
|
||||||
|
<T as frame_system::Config>::AccountId,
|
||||||
|
MessagesDeliveryProof = FromBridgedChainMessagesDeliveryProof<BridgedHeaderHash>,
|
||||||
|
>,
|
||||||
|
Call: IsSubType<CallableCallFor<Pallet<T, I>, T>>,
|
||||||
|
T: frame_system::Config<Call = Call>
|
||||||
|
+ Config<I, SourceHeaderChain = SourceHeaderChain, TargetHeaderChain = TargetHeaderChain>,
|
||||||
|
I: 'static,
|
||||||
|
> BridgeRuntimeFilterCall<Call> for Pallet<T, I>
|
||||||
|
{
|
||||||
|
fn validate(call: &Call) -> TransactionValidity {
|
||||||
|
match call.is_sub_type() {
|
||||||
|
Some(pallet_bridge_messages::Call::<T, I>::receive_messages_proof {
|
||||||
|
ref proof,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
let inbound_lane_data =
|
||||||
|
pallet_bridge_messages::InboundLanes::<T, I>::get(&proof.lane);
|
||||||
|
if proof.nonces_end <= inbound_lane_data.last_delivered_nonce() {
|
||||||
|
log::trace!(
|
||||||
|
target: pallet_bridge_messages::LOG_TARGET,
|
||||||
|
"Rejecting obsolete messages delivery transaction: \
|
||||||
|
lane {:?}, bundled {:?}, best {:?}",
|
||||||
|
proof.lane,
|
||||||
|
proof.nonces_end,
|
||||||
|
inbound_lane_data.last_delivered_nonce(),
|
||||||
|
);
|
||||||
|
|
||||||
impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteMessages {
|
return sp_runtime::transaction_validity::InvalidTransaction::Stale.into()
|
||||||
const IDENTIFIER: &'static str = "BridgeRejectObsoleteMessages";
|
|
||||||
type AccountId = <$runtime as frame_system::Config>::AccountId;
|
|
||||||
type Call = <$runtime as frame_system::Config>::Call;
|
|
||||||
type AdditionalSigned = ();
|
|
||||||
type Pre = ();
|
|
||||||
|
|
||||||
fn additional_signed(&self) -> sp_std::result::Result<
|
|
||||||
(),
|
|
||||||
sp_runtime::transaction_validity::TransactionValidityError,
|
|
||||||
> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate(
|
|
||||||
&self,
|
|
||||||
_who: &Self::AccountId,
|
|
||||||
call: &Self::Call,
|
|
||||||
_info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
|
|
||||||
_len: usize,
|
|
||||||
) -> sp_runtime::transaction_validity::TransactionValidity {
|
|
||||||
match *call {
|
|
||||||
$(
|
|
||||||
$call(pallet_bridge_messages::Call::<$runtime, $instance>::receive_messages_proof {
|
|
||||||
ref proof,
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
let nonces_end = proof.nonces_end;
|
|
||||||
|
|
||||||
let inbound_lane_data = pallet_bridge_messages::InboundLanes::<$runtime, $instance>::get(&proof.lane);
|
|
||||||
if proof.nonces_end <= inbound_lane_data.last_delivered_nonce() {
|
|
||||||
log::trace!(
|
|
||||||
target: pallet_bridge_messages::LOG_TARGET,
|
|
||||||
"Rejecting obsolete messages delivery transaction: lane {:?}, bundled {:?}, best {:?}",
|
|
||||||
proof.lane,
|
|
||||||
proof.nonces_end,
|
|
||||||
inbound_lane_data.last_delivered_nonce(),
|
|
||||||
);
|
|
||||||
|
|
||||||
return sp_runtime::transaction_validity::InvalidTransaction::Stale.into();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(sp_runtime::transaction_validity::ValidTransaction::default())
|
|
||||||
},
|
|
||||||
$call(pallet_bridge_messages::Call::<$runtime, $instance>::receive_messages_delivery_proof {
|
|
||||||
ref proof,
|
|
||||||
ref relayers_state,
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
let latest_delivered_nonce = relayers_state.last_delivered_nonce;
|
|
||||||
|
|
||||||
let outbound_lane_data = pallet_bridge_messages::OutboundLanes::<$runtime, $instance>::get(&proof.lane);
|
|
||||||
if latest_delivered_nonce <= outbound_lane_data.latest_received_nonce {
|
|
||||||
log::trace!(
|
|
||||||
target: pallet_bridge_messages::LOG_TARGET,
|
|
||||||
"Rejecting obsolete messages confirmation transaction: lane {:?}, bundled {:?}, best {:?}",
|
|
||||||
proof.lane,
|
|
||||||
latest_delivered_nonce,
|
|
||||||
outbound_lane_data.latest_received_nonce,
|
|
||||||
);
|
|
||||||
|
|
||||||
return sp_runtime::transaction_validity::InvalidTransaction::Stale.into();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(sp_runtime::transaction_validity::ValidTransaction::default())
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
_ => Ok(sp_runtime::transaction_validity::ValidTransaction::default()),
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
Some(pallet_bridge_messages::Call::<T, I>::receive_messages_delivery_proof {
|
||||||
|
ref proof,
|
||||||
|
ref relayers_state,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
let latest_delivered_nonce = relayers_state.last_delivered_nonce;
|
||||||
|
|
||||||
fn pre_dispatch(
|
let outbound_lane_data =
|
||||||
self,
|
pallet_bridge_messages::OutboundLanes::<T, I>::get(&proof.lane);
|
||||||
who: &Self::AccountId,
|
if latest_delivered_nonce <= outbound_lane_data.latest_received_nonce {
|
||||||
call: &Self::Call,
|
log::trace!(
|
||||||
info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
|
target: pallet_bridge_messages::LOG_TARGET,
|
||||||
len: usize,
|
"Rejecting obsolete messages confirmation transaction: \
|
||||||
) -> Result<Self::Pre, sp_runtime::transaction_validity::TransactionValidityError> {
|
lane {:?}, bundled {:?}, best {:?}",
|
||||||
self.validate(who, call, info, len).map(drop)
|
proof.lane,
|
||||||
}
|
latest_delivered_nonce,
|
||||||
|
outbound_lane_data.latest_received_nonce,
|
||||||
|
);
|
||||||
|
|
||||||
fn post_dispatch(
|
return sp_runtime::transaction_validity::InvalidTransaction::Stale.into()
|
||||||
_maybe_pre: Option<Self::Pre>,
|
}
|
||||||
_info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
|
},
|
||||||
_post_info: &sp_runtime::traits::PostDispatchInfoOf<Self::Call>,
|
_ => {},
|
||||||
_len: usize,
|
|
||||||
_result: &sp_runtime::DispatchResult,
|
|
||||||
) -> Result<(), sp_runtime::transaction_validity::TransactionValidityError> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
Ok(sp_runtime::transaction_validity::ValidTransaction::default())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use bp_messages::UnrewardedRelayersState;
|
use bp_messages::UnrewardedRelayersState;
|
||||||
use frame_support::weights::{DispatchClass, DispatchInfo, Pays};
|
|
||||||
use millau_runtime::{
|
use millau_runtime::{
|
||||||
bridge_runtime_common::messages::{
|
bridge_runtime_common::{
|
||||||
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
|
messages::{
|
||||||
|
source::FromBridgedChainMessagesDeliveryProof,
|
||||||
|
target::FromBridgedChainMessagesProof,
|
||||||
|
},
|
||||||
|
BridgeRuntimeFilterCall,
|
||||||
},
|
},
|
||||||
BridgeRejectObsoleteMessages, Call, Runtime, WithRialtoMessagesInstance,
|
Call, Runtime, WithRialtoMessagesInstance,
|
||||||
};
|
};
|
||||||
use sp_runtime::traits::SignedExtension;
|
|
||||||
|
|
||||||
fn deliver_message_10() {
|
fn deliver_message_10() {
|
||||||
pallet_bridge_messages::InboundLanes::<Runtime, WithRialtoMessagesInstance>::insert(
|
pallet_bridge_messages::InboundLanes::<Runtime, WithRialtoMessagesInstance>::insert(
|
||||||
@@ -156,13 +120,9 @@ mod tests {
|
|||||||
nonces_start: bp_messages::MessageNonce,
|
nonces_start: bp_messages::MessageNonce,
|
||||||
nonces_end: bp_messages::MessageNonce,
|
nonces_end: bp_messages::MessageNonce,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
BridgeRejectObsoleteMessages
|
pallet_bridge_messages::Pallet::<Runtime, WithRialtoMessagesInstance>::validate(
|
||||||
.validate(
|
&Call::BridgeRialtoMessages(
|
||||||
&[0u8; 32].into(),
|
pallet_bridge_messages::Call::<Runtime, ()>::receive_messages_proof {
|
||||||
&Call::BridgeRialtoMessages(pallet_bridge_messages::Call::<
|
|
||||||
Runtime,
|
|
||||||
WithRialtoMessagesInstance,
|
|
||||||
>::receive_messages_proof {
|
|
||||||
relayer_id_at_bridged_chain: [0u8; 32].into(),
|
relayer_id_at_bridged_chain: [0u8; 32].into(),
|
||||||
messages_count: (nonces_end - nonces_start + 1) as u32,
|
messages_count: (nonces_end - nonces_start + 1) as u32,
|
||||||
dispatch_weight: 0,
|
dispatch_weight: 0,
|
||||||
@@ -173,11 +133,10 @@ mod tests {
|
|||||||
nonces_start,
|
nonces_start,
|
||||||
nonces_end,
|
nonces_end,
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
&DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: Pays::Yes },
|
),
|
||||||
0,
|
)
|
||||||
)
|
.is_ok()
|
||||||
.is_ok()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -222,27 +181,23 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn validate_message_confirmation(last_delivered_nonce: bp_messages::MessageNonce) -> bool {
|
fn validate_message_confirmation(last_delivered_nonce: bp_messages::MessageNonce) -> bool {
|
||||||
BridgeRejectObsoleteMessages
|
pallet_bridge_messages::Pallet::<Runtime, WithRialtoMessagesInstance>::validate(
|
||||||
.validate(
|
&Call::BridgeRialtoMessages(pallet_bridge_messages::Call::<
|
||||||
&[0u8; 32].into(),
|
Runtime,
|
||||||
&Call::BridgeRialtoMessages(pallet_bridge_messages::Call::<
|
WithRialtoMessagesInstance,
|
||||||
Runtime,
|
>::receive_messages_delivery_proof {
|
||||||
WithRialtoMessagesInstance,
|
proof: FromBridgedChainMessagesDeliveryProof {
|
||||||
>::receive_messages_delivery_proof {
|
bridged_header_hash: Default::default(),
|
||||||
proof: FromBridgedChainMessagesDeliveryProof {
|
storage_proof: Vec::new(),
|
||||||
bridged_header_hash: Default::default(),
|
lane: [0, 0, 0, 0],
|
||||||
storage_proof: Vec::new(),
|
},
|
||||||
lane: [0, 0, 0, 0],
|
relayers_state: UnrewardedRelayersState {
|
||||||
},
|
last_delivered_nonce,
|
||||||
relayers_state: UnrewardedRelayersState {
|
..Default::default()
|
||||||
last_delivered_nonce,
|
},
|
||||||
..Default::default()
|
}),
|
||||||
},
|
)
|
||||||
}),
|
.is_ok()
|
||||||
&DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: Pays::Yes },
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
.is_ok()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -14,132 +14,68 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// 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/>.
|
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
/// Declares a runtime-specific `BridgeRejectObsoleteGrandpaHeader` signed extension.
|
use crate::{Config, Pallet};
|
||||||
///
|
use bp_runtime::FilterCall;
|
||||||
/// ## Example
|
use frame_support::{dispatch::CallableCallFor, traits::IsSubType};
|
||||||
///
|
use sp_runtime::{
|
||||||
/// ```nocompile
|
traits::Header,
|
||||||
/// pallet_bridge_grandpa::declare_bridge_reject_obsolete_grandpa_header!{
|
transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction},
|
||||||
/// Runtime,
|
};
|
||||||
/// Call::BridgeRialtoGrandpa => RialtoGrandpaInstance,
|
|
||||||
/// Call::BridgeWestendGrandpa => WestendGrandpaInstance,
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// The goal of this extension is to avoid "mining" transactions that provide
|
|
||||||
/// outdated bridged chain headers. Without that extension, even honest relayers
|
|
||||||
/// may lose their funds if there are multiple relays running and submitting the
|
|
||||||
/// same information.
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! declare_bridge_reject_obsolete_grandpa_header {
|
|
||||||
($runtime:ident, $($call:path => $instance:ty),*) => {
|
|
||||||
/// Transaction-with-obsolete-bridged-header check that will reject transaction if
|
|
||||||
/// it submits obsolete bridged header.
|
|
||||||
#[derive(Clone, codec::Decode, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)]
|
|
||||||
pub struct BridgeRejectObsoleteGrandpaHeader;
|
|
||||||
|
|
||||||
impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteGrandpaHeader {
|
/// Validate Grandpa headers in order to avoid "mining" transactions that provide outdated
|
||||||
const IDENTIFIER: &'static str = "BridgeRejectObsoleteGrandpaHeader";
|
/// bridged chain headers. Without this validation, even honest relayers may lose their funds
|
||||||
type AccountId = <$runtime as frame_system::Config>::AccountId;
|
/// if there are multiple relays running and submitting the same information.
|
||||||
type Call = <$runtime as frame_system::Config>::Call;
|
impl<
|
||||||
type AdditionalSigned = ();
|
Call: IsSubType<CallableCallFor<Pallet<T, I>, T>>,
|
||||||
type Pre = ();
|
T: frame_system::Config<Call = Call> + Config<I>,
|
||||||
|
I: 'static,
|
||||||
|
> FilterCall<Call> for Pallet<T, I>
|
||||||
|
{
|
||||||
|
fn validate(call: &<T as frame_system::Config>::Call) -> TransactionValidity {
|
||||||
|
let bundled_block_number = match call.is_sub_type() {
|
||||||
|
Some(crate::Call::<T, I>::submit_finality_proof { ref finality_target, .. }) =>
|
||||||
|
*finality_target.number(),
|
||||||
|
_ => return Ok(ValidTransaction::default()),
|
||||||
|
};
|
||||||
|
|
||||||
fn additional_signed(&self) -> sp_std::result::Result<
|
let best_finalized = crate::BestFinalized::<T, I>::get();
|
||||||
(),
|
let best_finalized_number = match best_finalized {
|
||||||
sp_runtime::transaction_validity::TransactionValidityError,
|
Some((best_finalized_number, _)) => best_finalized_number,
|
||||||
> {
|
None => return InvalidTransaction::Call.into(),
|
||||||
Ok(())
|
};
|
||||||
}
|
|
||||||
|
|
||||||
fn validate(
|
if best_finalized_number >= bundled_block_number {
|
||||||
&self,
|
log::trace!(
|
||||||
_who: &Self::AccountId,
|
target: crate::LOG_TARGET,
|
||||||
call: &Self::Call,
|
"Rejecting obsolete bridged header: bundled {:?}, best {:?}",
|
||||||
_info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
|
bundled_block_number,
|
||||||
_len: usize,
|
best_finalized_number,
|
||||||
) -> sp_runtime::transaction_validity::TransactionValidity {
|
);
|
||||||
match *call {
|
|
||||||
$(
|
|
||||||
$call($crate::Call::<$runtime, $instance>::submit_finality_proof { ref finality_target, ..}) => {
|
|
||||||
use sp_runtime::traits::Header as HeaderT;
|
|
||||||
|
|
||||||
let bundled_block_number = *finality_target.number();
|
return InvalidTransaction::Stale.into()
|
||||||
|
|
||||||
let best_finalized = $crate::BestFinalized::<$runtime, $instance>::get();
|
|
||||||
let best_finalized_number = match best_finalized {
|
|
||||||
Some((best_finalized_number, _)) => best_finalized_number,
|
|
||||||
None => return sp_runtime::transaction_validity::InvalidTransaction::Call.into(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if best_finalized_number < bundled_block_number {
|
|
||||||
Ok(sp_runtime::transaction_validity::ValidTransaction::default())
|
|
||||||
} else {
|
|
||||||
log::trace!(
|
|
||||||
target: $crate::LOG_TARGET,
|
|
||||||
"Rejecting obsolete bridged header: bundled {:?}, best {:?}",
|
|
||||||
bundled_block_number,
|
|
||||||
best_finalized_number,
|
|
||||||
);
|
|
||||||
|
|
||||||
sp_runtime::transaction_validity::InvalidTransaction::Stale.into()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)*
|
|
||||||
_ => Ok(sp_runtime::transaction_validity::ValidTransaction::default()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pre_dispatch(
|
|
||||||
self,
|
|
||||||
who: &Self::AccountId,
|
|
||||||
call: &Self::Call,
|
|
||||||
info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::Pre, sp_runtime::transaction_validity::TransactionValidityError> {
|
|
||||||
self.validate(who, call, info, len).map(drop)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn post_dispatch(
|
|
||||||
_maybe_pre: Option<Self::Pre>,
|
|
||||||
_info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
|
|
||||||
_post_info: &sp_runtime::traits::PostDispatchInfoOf<Self::Call>,
|
|
||||||
_len: usize,
|
|
||||||
_result: &sp_runtime::DispatchResult,
|
|
||||||
) -> Result<(), sp_runtime::transaction_validity::TransactionValidityError> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
Ok(ValidTransaction::default())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use super::FilterCall;
|
||||||
use crate::{
|
use crate::{
|
||||||
mock::{run_test, test_header, Call, TestNumber, TestRuntime},
|
mock::{run_test, test_header, Call, TestNumber, TestRuntime},
|
||||||
BestFinalized,
|
BestFinalized,
|
||||||
};
|
};
|
||||||
use bp_test_utils::make_default_justification;
|
use bp_test_utils::make_default_justification;
|
||||||
use frame_support::weights::{DispatchClass, DispatchInfo, Pays};
|
|
||||||
use sp_runtime::traits::SignedExtension;
|
|
||||||
|
|
||||||
declare_bridge_reject_obsolete_grandpa_header! {
|
|
||||||
TestRuntime,
|
|
||||||
Call::Grandpa => ()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate_block_submit(num: TestNumber) -> bool {
|
fn validate_block_submit(num: TestNumber) -> bool {
|
||||||
BridgeRejectObsoleteGrandpaHeader
|
crate::Pallet::<TestRuntime>::validate(&Call::Grandpa(
|
||||||
.validate(
|
crate::Call::<TestRuntime, ()>::submit_finality_proof {
|
||||||
&42,
|
finality_target: Box::new(test_header(num)),
|
||||||
&Call::Grandpa(crate::Call::<TestRuntime, ()>::submit_finality_proof {
|
justification: make_default_justification(&test_header(num)),
|
||||||
finality_target: Box::new(test_header(num)),
|
},
|
||||||
justification: make_default_justification(&test_header(num)),
|
))
|
||||||
}),
|
.is_ok()
|
||||||
&DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: Pays::Yes },
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
.is_ok()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_to_header_10() {
|
fn sync_to_header_10() {
|
||||||
|
|||||||
@@ -14,154 +14,98 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// 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/>.
|
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
/// Declares a runtime-specific `BridgeRejectObsoleteParachainHeader` signed extension.
|
use crate::{Config, Pallet, RelayBlockHash, RelayBlockHasher, RelayBlockNumber};
|
||||||
///
|
use bp_runtime::FilterCall;
|
||||||
/// ## Example
|
use frame_support::{dispatch::CallableCallFor, traits::IsSubType};
|
||||||
///
|
use sp_runtime::transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction};
|
||||||
/// ```nocompile
|
|
||||||
/// pallet_bridge_grandpa::declare_bridge_reject_obsolete_parachain_header!{
|
/// Validate parachain heads in order to avoid "mining" transactions that provide
|
||||||
/// Runtime,
|
/// outdated bridged parachain heads. Without this validation, even honest relayers
|
||||||
/// Call::BridgeRialtoParachains => RialtoGrandpaInstance,
|
|
||||||
/// Call::BridgeWestendParachains => WestendGrandpaInstance,
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// The goal of this extension is to avoid "mining" transactions that provide
|
|
||||||
/// outdated bridged parachain heads. Without that extension, even honest relayers
|
|
||||||
/// may lose their funds if there are multiple relays running and submitting the
|
/// may lose their funds if there are multiple relays running and submitting the
|
||||||
/// same information.
|
/// same information.
|
||||||
///
|
///
|
||||||
/// This extension only works with transactions that are updating single parachain
|
/// This validation only works with transactions that are updating single parachain
|
||||||
/// head. We can't use unbounded validation - it may take too long and either break
|
/// head. We can't use unbounded validation - it may take too long and either break
|
||||||
/// block production, or "eat" significant portion of block production time literally
|
/// block production, or "eat" significant portion of block production time literally
|
||||||
/// for nothing. In addition, the single-parachain-head-per-transaction is how the
|
/// for nothing. In addition, the single-parachain-head-per-transaction is how the
|
||||||
/// pallet will be used in our environment.
|
/// pallet will be used in our environment.
|
||||||
#[macro_export]
|
impl<
|
||||||
macro_rules! declare_bridge_reject_obsolete_parachain_header {
|
Call: IsSubType<CallableCallFor<Pallet<T, I>, T>>,
|
||||||
($runtime:ident, $($call:path => $instance:ty),*) => {
|
T: frame_system::Config<Call = Call> + Config<I>,
|
||||||
/// Transaction-with-obsolete-bridged-parachain-header check that will reject transaction if
|
I: 'static,
|
||||||
/// it submits obsolete bridged parachain header.
|
> FilterCall<Call> for Pallet<T, I>
|
||||||
#[derive(Clone, codec::Decode, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)]
|
where
|
||||||
pub struct BridgeRejectObsoleteParachainHeader;
|
<T as pallet_bridge_grandpa::Config<T::BridgesGrandpaPalletInstance>>::BridgedChain:
|
||||||
|
bp_runtime::Chain<
|
||||||
|
BlockNumber = RelayBlockNumber,
|
||||||
|
Hash = RelayBlockHash,
|
||||||
|
Hasher = RelayBlockHasher,
|
||||||
|
>,
|
||||||
|
{
|
||||||
|
fn validate(call: &Call) -> TransactionValidity {
|
||||||
|
let (bundled_relay_block_number, parachains) = match call.is_sub_type() {
|
||||||
|
Some(crate::Call::<T, I>::submit_parachain_heads {
|
||||||
|
ref at_relay_block,
|
||||||
|
ref parachains,
|
||||||
|
..
|
||||||
|
}) if parachains.len() == 1 => (at_relay_block.0, parachains),
|
||||||
|
_ => return Ok(ValidTransaction::default()),
|
||||||
|
};
|
||||||
|
|
||||||
impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteParachainHeader {
|
let (parachain, parachain_head_hash) =
|
||||||
const IDENTIFIER: &'static str = "BridgeRejectObsoleteParachainHeader";
|
parachains.get(0).expect("verified by match condition; qed");
|
||||||
type AccountId = <$runtime as frame_system::Config>::AccountId;
|
let best_parachain_head = crate::BestParaHeads::<T, I>::get(parachain);
|
||||||
type Call = <$runtime as frame_system::Config>::Call;
|
|
||||||
type AdditionalSigned = ();
|
|
||||||
type Pre = ();
|
|
||||||
|
|
||||||
fn additional_signed(&self) -> sp_std::result::Result<
|
match best_parachain_head {
|
||||||
(),
|
Some(best_parachain_head)
|
||||||
sp_runtime::transaction_validity::TransactionValidityError,
|
if best_parachain_head.at_relay_block_number >= bundled_relay_block_number =>
|
||||||
> {
|
{
|
||||||
Ok(())
|
log::trace!(
|
||||||
}
|
target: crate::LOG_TARGET,
|
||||||
|
"Rejecting obsolete parachain-head {:?} transaction: \
|
||||||
fn validate(
|
bundled relay block number: {:?} \
|
||||||
&self,
|
best relay block number: {:?}",
|
||||||
_who: &Self::AccountId,
|
parachain,
|
||||||
call: &Self::Call,
|
bundled_relay_block_number,
|
||||||
_info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
|
best_parachain_head.at_relay_block_number,
|
||||||
_len: usize,
|
);
|
||||||
) -> sp_runtime::transaction_validity::TransactionValidity {
|
InvalidTransaction::Stale.into()
|
||||||
match *call {
|
},
|
||||||
$(
|
Some(best_parachain_head) if best_parachain_head.head_hash == *parachain_head_hash => {
|
||||||
$call($crate::Call::<$runtime, $instance>::submit_parachain_heads {
|
log::trace!(
|
||||||
ref at_relay_block,
|
target: crate::LOG_TARGET,
|
||||||
ref parachains,
|
"Rejecting obsolete parachain-head {:?} transaction: head hash {:?}",
|
||||||
..
|
parachain,
|
||||||
}) if parachains.len() == 1 => {
|
best_parachain_head.head_hash,
|
||||||
let (parachain, parachain_head_hash) = parachains.get(0).expect("verified by match condition; qed");
|
);
|
||||||
|
InvalidTransaction::Stale.into()
|
||||||
let bundled_relay_block_number = at_relay_block.0;
|
},
|
||||||
|
_ => Ok(ValidTransaction::default()),
|
||||||
let best_parachain_head = $crate::BestParaHeads::<$runtime, $instance>::get(parachain);
|
|
||||||
|
|
||||||
match best_parachain_head {
|
|
||||||
Some(best_parachain_head) if best_parachain_head.at_relay_block_number
|
|
||||||
>= bundled_relay_block_number => {
|
|
||||||
log::trace!(
|
|
||||||
target: $crate::LOG_TARGET,
|
|
||||||
"Rejecting obsolete parachain-head {:?} transaction: bundled relay block number: \
|
|
||||||
{:?} best relay block number: {:?}",
|
|
||||||
parachain,
|
|
||||||
bundled_relay_block_number,
|
|
||||||
best_parachain_head.at_relay_block_number,
|
|
||||||
);
|
|
||||||
sp_runtime::transaction_validity::InvalidTransaction::Stale.into()
|
|
||||||
}
|
|
||||||
Some(best_parachain_head) if best_parachain_head.head_hash == *parachain_head_hash => {
|
|
||||||
log::trace!(
|
|
||||||
target: $crate::LOG_TARGET,
|
|
||||||
"Rejecting obsolete parachain-head {:?} transaction: head hash {:?}",
|
|
||||||
parachain,
|
|
||||||
best_parachain_head.head_hash,
|
|
||||||
);
|
|
||||||
sp_runtime::transaction_validity::InvalidTransaction::Stale.into()
|
|
||||||
}
|
|
||||||
_ => Ok(sp_runtime::transaction_validity::ValidTransaction::default()),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)*
|
|
||||||
_ => Ok(sp_runtime::transaction_validity::ValidTransaction::default()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pre_dispatch(
|
|
||||||
self,
|
|
||||||
who: &Self::AccountId,
|
|
||||||
call: &Self::Call,
|
|
||||||
info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::Pre, sp_runtime::transaction_validity::TransactionValidityError> {
|
|
||||||
self.validate(who, call, info, len).map(drop)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn post_dispatch(
|
|
||||||
_maybe_pre: Option<Self::Pre>,
|
|
||||||
_info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
|
|
||||||
_post_info: &sp_runtime::traits::PostDispatchInfoOf<Self::Call>,
|
|
||||||
_len: usize,
|
|
||||||
_result: &sp_runtime::DispatchResult,
|
|
||||||
) -> Result<(), sp_runtime::transaction_validity::TransactionValidityError> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
|
extension::FilterCall,
|
||||||
mock::{run_test, Call, TestRuntime},
|
mock::{run_test, Call, TestRuntime},
|
||||||
BestParaHead, BestParaHeads, RelayBlockNumber,
|
BestParaHead, BestParaHeads, RelayBlockNumber,
|
||||||
};
|
};
|
||||||
use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId};
|
use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId};
|
||||||
use frame_support::weights::{DispatchClass, DispatchInfo, Pays};
|
|
||||||
use sp_runtime::traits::SignedExtension;
|
|
||||||
|
|
||||||
declare_bridge_reject_obsolete_parachain_header! {
|
|
||||||
TestRuntime,
|
|
||||||
Call::Parachains => ()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate_submit_parachain_heads(
|
fn validate_submit_parachain_heads(
|
||||||
num: RelayBlockNumber,
|
num: RelayBlockNumber,
|
||||||
parachains: Vec<(ParaId, ParaHash)>,
|
parachains: Vec<(ParaId, ParaHash)>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
BridgeRejectObsoleteParachainHeader
|
crate::Pallet::<TestRuntime>::validate(&Call::Parachains(
|
||||||
.validate(
|
crate::Call::<TestRuntime, ()>::submit_parachain_heads {
|
||||||
&42,
|
at_relay_block: (num, Default::default()),
|
||||||
&Call::Parachains(crate::Call::<TestRuntime, ()>::submit_parachain_heads {
|
parachains,
|
||||||
at_relay_block: (num, Default::default()),
|
parachain_heads_proof: ParaHeadsProof(Vec::new()),
|
||||||
parachains,
|
},
|
||||||
parachain_heads_proof: ParaHeadsProof(Vec::new()),
|
))
|
||||||
}),
|
.is_ok()
|
||||||
&DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: Pays::Yes },
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
.is_ok()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_to_relay_header_10() {
|
fn sync_to_relay_header_10() {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ pub use chain::{
|
|||||||
};
|
};
|
||||||
pub use frame_support::storage::storage_prefix as storage_value_final_key;
|
pub use frame_support::storage::storage_prefix as storage_value_final_key;
|
||||||
use num_traits::{CheckedSub, One};
|
use num_traits::{CheckedSub, One};
|
||||||
|
use sp_runtime::transaction_validity::TransactionValidity;
|
||||||
pub use storage_proof::{
|
pub use storage_proof::{
|
||||||
Error as StorageProofError, ProofSize as StorageProofSize, StorageProofChecker,
|
Error as StorageProofError, ProofSize as StorageProofSize, StorageProofChecker,
|
||||||
};
|
};
|
||||||
@@ -400,6 +401,12 @@ pub trait OwnedBridgeModule<T: frame_system::Config> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A trait for querying whether a runtime call is valid.
|
||||||
|
pub trait FilterCall<Call> {
|
||||||
|
/// Checks if a runtime call is valid.
|
||||||
|
fn validate(call: &Call) -> TransactionValidity;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -114,9 +114,7 @@ impl TransactionSignScheme for Millau {
|
|||||||
frame_system::CheckNonce::<millau_runtime::Runtime>::from(param.unsigned.nonce),
|
frame_system::CheckNonce::<millau_runtime::Runtime>::from(param.unsigned.nonce),
|
||||||
frame_system::CheckWeight::<millau_runtime::Runtime>::new(),
|
frame_system::CheckWeight::<millau_runtime::Runtime>::new(),
|
||||||
pallet_transaction_payment::ChargeTransactionPayment::<millau_runtime::Runtime>::from(param.unsigned.tip),
|
pallet_transaction_payment::ChargeTransactionPayment::<millau_runtime::Runtime>::from(param.unsigned.tip),
|
||||||
millau_runtime::BridgeRejectObsoleteGrandpaHeader,
|
millau_runtime::BridgeRejectObsoleteHeadersAndMessages,
|
||||||
millau_runtime::BridgeRejectObsoleteParachainHeader,
|
|
||||||
millau_runtime::BridgeRejectObsoleteMessages,
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(),
|
(),
|
||||||
@@ -128,8 +126,6 @@ impl TransactionSignScheme for Millau {
|
|||||||
(),
|
(),
|
||||||
(),
|
(),
|
||||||
(),
|
(),
|
||||||
(),
|
|
||||||
(),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload));
|
let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload));
|
||||||
|
|||||||
Reference in New Issue
Block a user