Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Use a BoundedVec in ValidationResult #6603

Merged
merged 10 commits into from
Feb 16, 2023
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions node/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ sp-consensus-vrf = { git = "https://github.com/paritytech/substrate", branch = "
sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-maybe-compressed-blob = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
polkadot-parachain = { path = "../../parachain", default-features = false }
schnorrkel = "0.9.1"
thiserror = "1.0.31"
Expand Down
11 changes: 8 additions & 3 deletions node/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,12 @@ use polkadot_primitives::{
pub use sp_consensus_babe::{
AllowedSlots as BabeAllowedSlots, BabeEpochConfiguration, Epoch as BabeEpoch,
};
use sp_core::bounded::BoundedVec as CoreBoundedVec;
use sp_runtime::traits::ConstU32;

pub use polkadot_parachain::primitives::BlockData;
pub use polkadot_parachain::primitives::{
BlockData, MAX_HORIZONTAL_MESSAGE_NUM, MAX_UPWARD_MESSAGE_NUM,
};

pub mod approval;

Expand Down Expand Up @@ -314,9 +318,10 @@ impl MaybeCompressedPoV {
#[cfg(not(target_os = "unknown"))]
pub struct Collation<BlockNumber = polkadot_primitives::BlockNumber> {
/// Messages destined to be interpreted by the Relay chain itself.
pub upward_messages: Vec<UpwardMessage>,
pub upward_messages: CoreBoundedVec<UpwardMessage, ConstU32<MAX_UPWARD_MESSAGE_NUM>>,
mrcnski marked this conversation as resolved.
Show resolved Hide resolved
/// The horizontal messages sent by the parachain.
pub horizontal_messages: Vec<OutboundHrmpMessage<ParaId>>,
pub horizontal_messages:
CoreBoundedVec<OutboundHrmpMessage<ParaId>, ConstU32<MAX_HORIZONTAL_MESSAGE_NUM>>,
/// New validation code.
pub new_validation_code: Option<ValidationCode>,
/// The head-data produced as a result of execution.
Expand Down
20 changes: 16 additions & 4 deletions parachain/src/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ use sp_std::vec::Vec;
use frame_support::weights::Weight;
use parity_scale_codec::{CompactAs, Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_core::{RuntimeDebug, TypeId};
use sp_runtime::traits::Hash as _;
use sp_core::{bounded::BoundedVec, RuntimeDebug, TypeId};
use sp_runtime::traits::{ConstU32, Hash as _};

#[cfg(feature = "std")]
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -346,6 +346,17 @@ impl XcmpMessageHandler for () {
}
}

/// Maximum number of HRMP messages allowed per candidate.
///
/// We also use this as a generous limit, which still prevents possible memory exhaustion, from
/// malicious parachains that may otherwise return a huge amount of messages in `ValidationResult`.
pub const MAX_HORIZONTAL_MESSAGE_NUM: u32 = 16 * 1024;
/// Maximum number of UMP messages allowed per candidate.
///
/// We also use this as a generous limit, which still prevents possible memory exhaustion, from
/// malicious parachains that may otherwise return a huge amount of messages in `ValidationResult`.
pub const MAX_UPWARD_MESSAGE_NUM: u32 = 16 * 1024;

/// Validation parameters for evaluating the parachain validity function.
// TODO: balance downloads (https://github.com/paritytech/polkadot/issues/220)
#[derive(PartialEq, Eq, Decode, Clone)]
Expand All @@ -371,9 +382,10 @@ pub struct ValidationResult {
/// An update to the validation code that should be scheduled in the relay chain.
pub new_validation_code: Option<ValidationCode>,
/// Upward messages send by the Parachain.
pub upward_messages: Vec<UpwardMessage>,
pub upward_messages: BoundedVec<UpwardMessage, ConstU32<MAX_UPWARD_MESSAGE_NUM>>,
mrcnski marked this conversation as resolved.
Show resolved Hide resolved
/// Outbound horizontal messages sent by the parachain.
pub horizontal_messages: Vec<OutboundHrmpMessage<Id>>,
pub horizontal_messages:
BoundedVec<OutboundHrmpMessage<Id>, ConstU32<MAX_HORIZONTAL_MESSAGE_NUM>>,
/// Number of downward messages that were processed by the Parachain.
///
/// It is expected that the Parachain processes them from first to last.
Expand Down
26 changes: 20 additions & 6 deletions primitives/src/v2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ use sp_std::{

use application_crypto::KeyTypeId;
use inherents::InherentIdentifier;
use primitives::RuntimeDebug;
use runtime_primitives::traits::{AppVerify, Header as HeaderT};
use primitives::{bounded::BoundedVec, RuntimeDebug};
use runtime_primitives::traits::{AppVerify, ConstU32, Header as HeaderT};
use sp_arithmetic::traits::{BaseArithmetic, Saturating};

pub use runtime_primitives::traits::{BlakeTwo256, Hash as HashT};
Expand All @@ -44,7 +44,7 @@ pub use polkadot_core_primitives::{
// Export some polkadot-parachain primitives
pub use polkadot_parachain::primitives::{
HeadData, HrmpChannelId, Id, UpwardMessage, ValidationCode, ValidationCodeHash,
LOWEST_PUBLIC_ID, LOWEST_USER_ID,
LOWEST_PUBLIC_ID, LOWEST_USER_ID, MAX_HORIZONTAL_MESSAGE_NUM, MAX_UPWARD_MESSAGE_NUM,
};

#[cfg(feature = "std")]
Expand Down Expand Up @@ -593,12 +593,13 @@ impl<H: Encode, N: Encode> PersistedValidationData<H, N> {

/// Commitments made in a `CandidateReceipt`. Many of these are outputs of validation.
#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(Hash, Default))]
#[cfg_attr(feature = "std", derive(Default))]
pub struct CandidateCommitments<N = BlockNumber> {
/// Messages destined to be interpreted by the Relay chain itself.
pub upward_messages: Vec<UpwardMessage>,
pub upward_messages: BoundedVec<UpwardMessage, ConstU32<MAX_UPWARD_MESSAGE_NUM>>,
/// Horizontal messages sent by the parachain.
pub horizontal_messages: Vec<OutboundHrmpMessage<Id>>,
pub horizontal_messages:
BoundedVec<OutboundHrmpMessage<Id>, ConstU32<MAX_HORIZONTAL_MESSAGE_NUM>>,
/// New validation code.
pub new_validation_code: Option<ValidationCode>,
/// The head-data produced as a result of execution.
Expand All @@ -609,6 +610,19 @@ pub struct CandidateCommitments<N = BlockNumber> {
pub hrmp_watermark: N,
}

// Custom implementation of `Hash`, since `BoundedVec` does not implement it.
#[cfg(feature = "std")]
impl sp_std::hash::Hash for CandidateCommitments {
fn hash<H: sp_std::hash::Hasher>(&self, state: &mut H) {
mrcnski marked this conversation as resolved.
Show resolved Hide resolved
self.upward_messages.as_slice().hash(state);
self.horizontal_messages.as_slice().hash(state);
self.new_validation_code.hash(state);
sp_std::hash::Hash::hash(&self.head_data, state);
self.processed_downward_messages.hash(state);
self.hrmp_watermark.hash(state);
}
}

impl CandidateCommitments {
/// Compute the blake2-256 hash of the commitments.
pub fn hash(&self) -> Hash {
Expand Down
1 change: 1 addition & 0 deletions runtime/parachains/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ primitives = { package = "polkadot-primitives", path = "../../primitives", defau
rand = { version = "0.8.5", default-features = false }
rand_chacha = { version = "0.3.1", default-features = false }
static_assertions = { version = "1.1.0", optional = true }
polkadot-parachain = { path = "../../parachain", default-features = false }
polkadot-runtime-metrics = { path = "../metrics", default-features = false}

[dev-dependencies]
Expand Down
19 changes: 18 additions & 1 deletion runtime/parachains/src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::shared;
use frame_support::{pallet_prelude::*, weights::constants::WEIGHT_REF_TIME_PER_MILLIS};
use frame_system::pallet_prelude::*;
use parity_scale_codec::{Decode, Encode};
use polkadot_parachain::primitives::{MAX_HORIZONTAL_MESSAGE_NUM, MAX_UPWARD_MESSAGE_NUM};
use primitives::{Balance, SessionIndex, MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, MAX_POV_SIZE};
use sp_runtime::traits::Zero;
use sp_std::prelude::*;
Expand Down Expand Up @@ -322,8 +323,12 @@ pub enum InconsistentError<BlockNumber> {
},
/// `validation_upgrade_delay` is less than or equal 1.
ValidationUpgradeDelayIsTooLow { validation_upgrade_delay: BlockNumber },
/// Maximum UMP message size (`MAX_UPWARD_MESSAGE_SIZE_BOUND`) exceeded.
/// Maximum UMP message size ([`MAX_UPWARD_MESSAGE_SIZE_BOUND`]) exceeded.
MaxUpwardMessageSizeExceeded { max_message_size: u32 },
/// Maximum HRMP message num ([`MAX_HORIZONTAL_MESSAGE_NUM`]) exceeded.
MaxHorizontalMessageNumExceeded { max_message_num: u32 },
/// Maximum UMP message num ([`MAX_UPWARD_MESSAGE_NUM`]) exceeded.
MaxUpwardMessageNumExceeded { max_message_num: u32 },
/// Maximum number of HRMP outbound channels exceeded.
MaxHrmpOutboundChannelsExceeded,
/// Maximum number of HRMP inbound channels exceeded.
Expand Down Expand Up @@ -396,6 +401,18 @@ where
})
}

if self.hrmp_max_message_num_per_candidate > MAX_HORIZONTAL_MESSAGE_NUM {
return Err(MaxHorizontalMessageNumExceeded {
max_message_num: self.hrmp_max_message_num_per_candidate,
})
}

if self.max_upward_message_num_per_candidate > MAX_UPWARD_MESSAGE_NUM {
return Err(MaxUpwardMessageNumExceeded {
max_message_num: self.max_upward_message_num_per_candidate,
})
}

if self.hrmp_max_parachain_outbound_channels > crate::hrmp::HRMP_MAX_OUTBOUND_CHANNELS_BOUND
{
return Err(MaxHrmpOutboundChannelsExceeded)
Expand Down
11 changes: 9 additions & 2 deletions runtime/parachains/src/hrmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,16 @@ use crate::{
use frame_support::{pallet_prelude::*, traits::ReservableCurrency};
use frame_system::pallet_prelude::*;
use parity_scale_codec::{Decode, Encode};
use polkadot_parachain::primitives::MAX_HORIZONTAL_MESSAGE_NUM;
use primitives::{
Balance, Hash, HrmpChannelId, Id as ParaId, InboundHrmpMessage, OutboundHrmpMessage,
SessionIndex,
};
use scale_info::TypeInfo;
use sp_runtime::traits::{AccountIdConversion, BlakeTwo256, Hash as HashT, UniqueSaturatedInto};
use sp_core::bounded::BoundedVec;
use sp_runtime::traits::{
AccountIdConversion, BlakeTwo256, ConstU32, Hash as HashT, UniqueSaturatedInto,
};
use sp_std::{
collections::{btree_map::BTreeMap, btree_set::BTreeSet},
fmt, mem,
Expand Down Expand Up @@ -1059,7 +1063,10 @@ impl<T: Config> Pallet<T> {
/// Returns the amount of weight consumed.
pub(crate) fn queue_outbound_hrmp(
sender: ParaId,
out_hrmp_msgs: Vec<OutboundHrmpMessage<ParaId>>,
out_hrmp_msgs: BoundedVec<
OutboundHrmpMessage<ParaId>,
ConstU32<MAX_HORIZONTAL_MESSAGE_NUM>,
>,
) -> Weight {
let mut weight = Weight::zero();
let now = <frame_system::Pallet<T>>::block_number();
Expand Down
7 changes: 5 additions & 2 deletions runtime/parachains/src/ump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,18 @@ use crate::{
};
use frame_support::{pallet_prelude::*, traits::EnsureOrigin};
use frame_system::pallet_prelude::*;
use polkadot_parachain::primitives::MAX_UPWARD_MESSAGE_NUM;
use primitives::{Id as ParaId, UpwardMessage};
use sp_core::bounded::BoundedVec;
use sp_runtime::traits::ConstU32;
use sp_std::{collections::btree_map::BTreeMap, fmt, marker::PhantomData, mem, prelude::*};
use xcm::latest::Outcome;

pub use pallet::*;

/// Maximum value that `config.max_upward_message_size` can be set to
///
/// This is used for benchmarking sanely bounding relevant storate items. It is expected from the `configurations`
/// This is used for benchmarking sanely bounding relevant storage items. It is expected from the `configurations`
/// pallet to check these values before setting.
pub const MAX_UPWARD_MESSAGE_SIZE_BOUND: u32 = 50 * 1024;
/// Maximum amount of overweight messages that can exist in the queue at any given time.
Expand Down Expand Up @@ -472,7 +475,7 @@ impl<T: Config> Pallet<T> {
/// Enqueues `upward_messages` from a `para`'s accepted candidate block.
pub(crate) fn receive_upward_messages(
para: ParaId,
upward_messages: Vec<UpwardMessage>,
upward_messages: BoundedVec<UpwardMessage, ConstU32<MAX_UPWARD_MESSAGE_NUM>>,
) -> Weight {
let mut weight = Weight::zero();

Expand Down