mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-20 22:05:42 +00:00
reject too large (by size) messages (#551)
This commit is contained in:
committed by
Bastian Köcher
parent
f1949c6342
commit
81a3e7cce3
@@ -153,7 +153,7 @@ parameter_types! {
|
|||||||
pub const ExtrinsicBaseWeight: Weight = 10_000_000;
|
pub const ExtrinsicBaseWeight: Weight = 10_000_000;
|
||||||
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(bp_millau::AVAILABLE_BLOCK_RATIO);
|
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(bp_millau::AVAILABLE_BLOCK_RATIO);
|
||||||
pub MaximumExtrinsicWeight: Weight = bp_millau::MAXIMUM_EXTRINSIC_WEIGHT;
|
pub MaximumExtrinsicWeight: Weight = bp_millau::MAXIMUM_EXTRINSIC_WEIGHT;
|
||||||
pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
|
pub const MaximumBlockLength: u32 = bp_millau::MAXIMUM_BLOCK_SIZE;
|
||||||
pub const Version: RuntimeVersion = VERSION;
|
pub const Version: RuntimeVersion = VERSION;
|
||||||
pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight {
|
pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight {
|
||||||
read: 60_000_000, // ~0.06 ms = ~60 µs
|
read: 60_000_000, // ~0.06 ms = ~60 µs
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ impl MessageBridge for WithRialtoMessageBridge {
|
|||||||
type ThisChain = Millau;
|
type ThisChain = Millau;
|
||||||
type BridgedChain = Rialto;
|
type BridgedChain = Rialto;
|
||||||
|
|
||||||
|
fn maximal_extrinsic_size_on_target_chain() -> u32 {
|
||||||
|
bp_rialto::MAXIMUM_EXTRINSIC_SIZE
|
||||||
|
}
|
||||||
|
|
||||||
fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive<Weight> {
|
fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive<Weight> {
|
||||||
// we don't want to relay too large messages + keep reserve for future upgrades
|
// we don't want to relay too large messages + keep reserve for future upgrades
|
||||||
let upper_limit = bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT / 2;
|
let upper_limit = bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT / 2;
|
||||||
@@ -167,12 +171,7 @@ impl TargetHeaderChain<ToRialtoMessagePayload, bp_rialto::AccountId> for Rialto
|
|||||||
type MessagesDeliveryProof = ToRialtoMessagesDeliveryProof;
|
type MessagesDeliveryProof = ToRialtoMessagesDeliveryProof;
|
||||||
|
|
||||||
fn verify_message(payload: &ToRialtoMessagePayload) -> Result<(), Self::Error> {
|
fn verify_message(payload: &ToRialtoMessagePayload) -> Result<(), Self::Error> {
|
||||||
let weight_limits = WithRialtoMessageBridge::weight_limits_of_message_on_bridged_chain(&payload.call);
|
messages::source::verify_chain_message::<WithRialtoMessageBridge>(payload)
|
||||||
if !weight_limits.contains(&payload.weight) {
|
|
||||||
return Err("Incorrect message weight declared");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_messages_delivery_proof(
|
fn verify_messages_delivery_proof(
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ parameter_types! {
|
|||||||
pub const ExtrinsicBaseWeight: Weight = 10_000_000;
|
pub const ExtrinsicBaseWeight: Weight = 10_000_000;
|
||||||
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(bp_rialto::AVAILABLE_BLOCK_RATIO);
|
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(bp_rialto::AVAILABLE_BLOCK_RATIO);
|
||||||
pub MaximumExtrinsicWeight: Weight = bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT;
|
pub MaximumExtrinsicWeight: Weight = bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT;
|
||||||
pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
|
pub const MaximumBlockLength: u32 = bp_rialto::MAXIMUM_BLOCK_SIZE;
|
||||||
pub const Version: RuntimeVersion = VERSION;
|
pub const Version: RuntimeVersion = VERSION;
|
||||||
pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight {
|
pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight {
|
||||||
read: 60_000_000, // ~0.06 ms = ~60 µs
|
read: 60_000_000, // ~0.06 ms = ~60 µs
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ impl MessageBridge for WithMillauMessageBridge {
|
|||||||
type ThisChain = Rialto;
|
type ThisChain = Rialto;
|
||||||
type BridgedChain = Millau;
|
type BridgedChain = Millau;
|
||||||
|
|
||||||
|
fn maximal_extrinsic_size_on_target_chain() -> u32 {
|
||||||
|
bp_millau::MAXIMUM_EXTRINSIC_SIZE
|
||||||
|
}
|
||||||
|
|
||||||
fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive<Weight> {
|
fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive<Weight> {
|
||||||
// we don't want to relay too large messages + keep reserve for future upgrades
|
// we don't want to relay too large messages + keep reserve for future upgrades
|
||||||
let upper_limit = bp_millau::MAXIMUM_EXTRINSIC_WEIGHT / 2;
|
let upper_limit = bp_millau::MAXIMUM_EXTRINSIC_WEIGHT / 2;
|
||||||
@@ -167,12 +171,7 @@ impl TargetHeaderChain<ToMillauMessagePayload, bp_millau::AccountId> for Millau
|
|||||||
type MessagesDeliveryProof = ToMillauMessagesDeliveryProof;
|
type MessagesDeliveryProof = ToMillauMessagesDeliveryProof;
|
||||||
|
|
||||||
fn verify_message(payload: &ToMillauMessagePayload) -> Result<(), Self::Error> {
|
fn verify_message(payload: &ToMillauMessagePayload) -> Result<(), Self::Error> {
|
||||||
let weight_limits = WithMillauMessageBridge::weight_limits_of_message_on_bridged_chain(&payload.call);
|
messages::source::verify_chain_message::<WithMillauMessageBridge>(payload)
|
||||||
if !weight_limits.contains(&payload.weight) {
|
|
||||||
return Err("Incorrect message weight declared");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_messages_delivery_proof(
|
fn verify_messages_delivery_proof(
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ pub trait MessageBridge {
|
|||||||
/// Bridged chain in context of message bridge.
|
/// Bridged chain in context of message bridge.
|
||||||
type BridgedChain: ChainWithMessageLanes;
|
type BridgedChain: ChainWithMessageLanes;
|
||||||
|
|
||||||
|
/// Maximal extrinsic size on target chain.
|
||||||
|
fn maximal_extrinsic_size_on_target_chain() -> u32;
|
||||||
|
|
||||||
/// Returns feasible weights range for given message payload on the target chain.
|
/// Returns feasible weights range for given message payload on the target chain.
|
||||||
///
|
///
|
||||||
/// If message is being sent with the weight that is out of this range, then it
|
/// If message is being sent with the weight that is out of this range, then it
|
||||||
@@ -98,7 +101,7 @@ pub trait ChainWithMessageLanes {
|
|||||||
/// `frame_support::weight::Weight`. But since the meaning of weight on different chains
|
/// `frame_support::weight::Weight`. But since the meaning of weight on different chains
|
||||||
/// may be different, the `WeightOf<>` construct is used to avoid confusion between
|
/// may be different, the `WeightOf<>` construct is used to avoid confusion between
|
||||||
/// different weights.
|
/// different weights.
|
||||||
type Weight: From<frame_support::weights::Weight>;
|
type Weight: From<frame_support::weights::Weight> + PartialOrd;
|
||||||
/// Type of balances that is used on the chain.
|
/// Type of balances that is used on the chain.
|
||||||
type Balance: Decode + CheckedAdd + CheckedDiv + CheckedMul + PartialOrd + From<u32> + Copy;
|
type Balance: Decode + CheckedAdd + CheckedDiv + CheckedMul + PartialOrd + From<u32> + Copy;
|
||||||
|
|
||||||
@@ -171,6 +174,36 @@ pub mod source {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Do basic Bridged-chain specific verification of This -> Bridged chain 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
|
||||||
|
/// check) that would reject message (see `FromThisChainMessageVerifier`).
|
||||||
|
pub fn verify_chain_message<B: MessageBridge>(
|
||||||
|
payload: &FromThisChainMessagePayload<B>,
|
||||||
|
) -> Result<(), &'static str> {
|
||||||
|
let weight_limits = B::weight_limits_of_message_on_bridged_chain(&payload.call);
|
||||||
|
if !weight_limits.contains(&payload.weight.into()) {
|
||||||
|
return Err("Incorrect message weight declared");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The maximal size of extrinsic at Substrate-based chain depends on the
|
||||||
|
// `frame_system::Trait::MaximumBlockLength` and `frame_system::Trait::AvailableBlockRatio`
|
||||||
|
// constants. This check is here to be sure that the lane won't stuck because message is too
|
||||||
|
// large to fit into delivery transaction.
|
||||||
|
//
|
||||||
|
// **IMPORTANT NOTE**: the delivery transaction contains storage proof of the message, not
|
||||||
|
// the message itself. The proof is always larger than the message. But unless chain state
|
||||||
|
// is enormously large, it should be several dozens/hundreds of bytes. The delivery
|
||||||
|
// transaction also contains signatures and signed extensions. Because of this, we reserve
|
||||||
|
// 1/3 of the the maximal extrinsic weight for this data.
|
||||||
|
if payload.call.len() > B::maximal_extrinsic_size_on_target_chain() as usize * 2 / 3 {
|
||||||
|
return Err("The message is too large to be sent over the lane");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Estimate delivery and dispatch fee that must be paid for delivering a message to the Bridged chain.
|
/// Estimate delivery and dispatch fee that must be paid for delivering a message to the Bridged chain.
|
||||||
///
|
///
|
||||||
/// The fee is paid in This chain Balance, but we use Bridged chain balance to avoid additional conversions.
|
/// The fee is paid in This chain Balance, but we use Bridged chain balance to avoid additional conversions.
|
||||||
@@ -511,6 +544,8 @@ mod tests {
|
|||||||
const THIS_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 2;
|
const THIS_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 2;
|
||||||
const BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 4;
|
const BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 4;
|
||||||
const THIS_CHAIN_TO_BRIDGED_CHAIN_BALANCE_RATE: u32 = 6;
|
const THIS_CHAIN_TO_BRIDGED_CHAIN_BALANCE_RATE: u32 = 6;
|
||||||
|
const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: Weight = 2048;
|
||||||
|
const BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE: u32 = 1024;
|
||||||
|
|
||||||
/// Bridge that is deployed on ThisChain and allows sending/receiving messages to/from BridgedChain;
|
/// Bridge that is deployed on ThisChain and allows sending/receiving messages to/from BridgedChain;
|
||||||
struct OnThisChainBridge;
|
struct OnThisChainBridge;
|
||||||
@@ -522,8 +557,13 @@ mod tests {
|
|||||||
type ThisChain = ThisChain;
|
type ThisChain = ThisChain;
|
||||||
type BridgedChain = BridgedChain;
|
type BridgedChain = BridgedChain;
|
||||||
|
|
||||||
fn weight_limits_of_message_on_bridged_chain(_message_payload: &[u8]) -> RangeInclusive<Weight> {
|
fn maximal_extrinsic_size_on_target_chain() -> u32 {
|
||||||
unreachable!()
|
BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE
|
||||||
|
}
|
||||||
|
|
||||||
|
fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive<Weight> {
|
||||||
|
let begin = std::cmp::min(BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, message_payload.len() as Weight);
|
||||||
|
begin..=BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT
|
||||||
}
|
}
|
||||||
|
|
||||||
fn weight_of_delivery_transaction() -> Weight {
|
fn weight_of_delivery_transaction() -> Weight {
|
||||||
@@ -561,6 +601,10 @@ mod tests {
|
|||||||
type ThisChain = BridgedChain;
|
type ThisChain = BridgedChain;
|
||||||
type BridgedChain = ThisChain;
|
type BridgedChain = ThisChain;
|
||||||
|
|
||||||
|
fn maximal_extrinsic_size_on_target_chain() -> u32 {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
fn weight_limits_of_message_on_bridged_chain(_message_payload: &[u8]) -> RangeInclusive<Weight> {
|
fn weight_limits_of_message_on_bridged_chain(_message_payload: &[u8]) -> RangeInclusive<Weight> {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@@ -773,6 +817,66 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn verify_chain_message_rejects_message_with_too_small_declared_weight() {
|
||||||
|
assert!(
|
||||||
|
source::verify_chain_message::<OnThisChainBridge>(&source::FromThisChainMessagePayload::<
|
||||||
|
OnThisChainBridge,
|
||||||
|
> {
|
||||||
|
spec_version: 1,
|
||||||
|
weight: 5,
|
||||||
|
origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot,
|
||||||
|
call: vec![1, 2, 3, 4, 5, 6],
|
||||||
|
},)
|
||||||
|
.is_err()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn verify_chain_message_rejects_message_with_too_large_declared_weight() {
|
||||||
|
assert!(
|
||||||
|
source::verify_chain_message::<OnThisChainBridge>(&source::FromThisChainMessagePayload::<
|
||||||
|
OnThisChainBridge,
|
||||||
|
> {
|
||||||
|
spec_version: 1,
|
||||||
|
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + 1,
|
||||||
|
origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot,
|
||||||
|
call: vec![1, 2, 3, 4, 5, 6],
|
||||||
|
},)
|
||||||
|
.is_err()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn verify_chain_message_rejects_message_too_large_message() {
|
||||||
|
assert!(
|
||||||
|
source::verify_chain_message::<OnThisChainBridge>(&source::FromThisChainMessagePayload::<
|
||||||
|
OnThisChainBridge,
|
||||||
|
> {
|
||||||
|
spec_version: 1,
|
||||||
|
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT,
|
||||||
|
origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot,
|
||||||
|
call: vec![0; BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE as usize * 2 / 3 + 1],
|
||||||
|
},)
|
||||||
|
.is_err()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn verify_chain_message_accepts_maximal_message() {
|
||||||
|
assert_eq!(
|
||||||
|
source::verify_chain_message::<OnThisChainBridge>(&source::FromThisChainMessagePayload::<
|
||||||
|
OnThisChainBridge,
|
||||||
|
> {
|
||||||
|
spec_version: 1,
|
||||||
|
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT,
|
||||||
|
origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot,
|
||||||
|
call: vec![0; BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE as usize * 2 / 3],
|
||||||
|
},),
|
||||||
|
Ok(()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct TestMessageProofParser {
|
struct TestMessageProofParser {
|
||||||
failing: bool,
|
failing: bool,
|
||||||
|
|||||||
@@ -75,6 +75,10 @@ pub const AVAILABLE_BLOCK_RATIO: u32 = 75;
|
|||||||
/// Maximal weight of single Millau extrinsic (65% of maximum block weight = 75% for regular
|
/// Maximal weight of single Millau extrinsic (65% of maximum block weight = 75% for regular
|
||||||
/// transactions minus 10% for initialization).
|
/// transactions minus 10% for initialization).
|
||||||
pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT / 100 * (AVAILABLE_BLOCK_RATIO as Weight - 10);
|
pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT / 100 * (AVAILABLE_BLOCK_RATIO as Weight - 10);
|
||||||
|
/// Maximal size of Millau block.
|
||||||
|
pub const MAXIMUM_BLOCK_SIZE: u32 = 2 * 1024 * 1024;
|
||||||
|
/// Maximal size of single normal Millau extrinsic (75% of maximal block size).
|
||||||
|
pub const MAXIMUM_EXTRINSIC_SIZE: u32 = MAXIMUM_BLOCK_SIZE / 100 * AVAILABLE_BLOCK_RATIO;
|
||||||
|
|
||||||
// TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78
|
// TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78
|
||||||
/// Maximal number of messages in single delivery transaction.
|
/// Maximal number of messages in single delivery transaction.
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ pub const AVAILABLE_BLOCK_RATIO: u32 = 75;
|
|||||||
/// Maximal weight of single Rialto extrinsic (65% of maximum block weight = 75% for regular
|
/// Maximal weight of single Rialto extrinsic (65% of maximum block weight = 75% for regular
|
||||||
/// transactions minus 10% for initialization).
|
/// transactions minus 10% for initialization).
|
||||||
pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT / 100 * (AVAILABLE_BLOCK_RATIO as Weight - 10);
|
pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT / 100 * (AVAILABLE_BLOCK_RATIO as Weight - 10);
|
||||||
|
/// Maximal size of Rialto block.
|
||||||
|
pub const MAXIMUM_BLOCK_SIZE: u32 = 5 * 1024 * 1024;
|
||||||
|
/// Maximal size of single normal Rialto extrinsic (75% of maximal block size).
|
||||||
|
pub const MAXIMUM_EXTRINSIC_SIZE: u32 = MAXIMUM_BLOCK_SIZE / 100 * AVAILABLE_BLOCK_RATIO;
|
||||||
|
|
||||||
// TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78
|
// TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78
|
||||||
/// Maximal number of messages in single delivery transaction.
|
/// Maximal number of messages in single delivery transaction.
|
||||||
|
|||||||
Reference in New Issue
Block a user