diff --git a/crates/subspace-runtime/src/lib.rs b/crates/subspace-runtime/src/lib.rs index b6ad296864f99..2eebaf8a2b575 100644 --- a/crates/subspace-runtime/src/lib.rs +++ b/crates/subspace-runtime/src/lib.rs @@ -28,9 +28,10 @@ use frame_support::{ construct_runtime, parameter_types, weights::{ constants::{RocksDbWeight, WEIGHT_PER_SECOND}, - IdentityFee, Weight, + IdentityFee, }, }; +use frame_system::limits::{BlockLength, BlockWeights}; use pallet_transaction_payment::CurrencyAdapter; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; @@ -110,6 +111,15 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { transaction_version: 1, }; +/// The version information used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } +} + // TODO: Many of below constants should probably be updatable but currently they are not /// Since Subspace is probabilistic this is the average expected block time that @@ -132,17 +142,12 @@ const MILLISECS_PER_BLOCK: u64 = 6000; // Attempting to do so will brick block production. const SLOT_DURATION: u64 = 1000; -// Time is measured by number of blocks. -// pub const MINUTES: BlockNumber = 3_200 / (MILLISECS_PER_BLOCK as BlockNumber); -// pub const HOURS: BlockNumber = MINUTES * 60; -// pub const DAYS: BlockNumber = HOURS * 24; - /// 1 in 6 slots (on average, not counting collisions) will have a block. /// Must match ratio between block and slot duration in constants above. const SLOT_PROBABILITY: (u64, u64) = (1, 6); /// Era duration in blocks. -const ERA_DURATION_IN_BLOCKS: u32 = 2016; +const ERA_DURATION_IN_BLOCKS: BlockNumber = 2016; const EPOCH_DURATION_IN_BLOCKS: BlockNumber = 256; const EPOCH_DURATION_IN_SLOTS: u64 = @@ -156,23 +161,28 @@ pub const SUBSPACE_GENESIS_EPOCH_CONFIG: sp_consensus_subspace::SubspaceEpochCon c: SLOT_PROBABILITY, }; -/// The version information used to identify this runtime when compiled natively. -#[cfg(feature = "std")] -pub fn native_version() -> NativeVersion { - NativeVersion { - runtime_version: VERSION, - can_author_with: Default::default(), - } -} - -const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); - // TODO: Proper value here const CONFIRMATION_DEPTH_K: u32 = 100; -// This is a nice power of 2 for Merkle Tree +/// 128 data records and 128 parity records (as a result of erasure coding) together form a perfect +/// Merkle Tree and will result in witness size of `log2(MERKLE_NUM_LEAVES) * SHA256_HASH_SIZE`. +/// +/// This number is a tradeoff: +/// * as this number goes up, fewer [`RootBlock`]s are required to be stored for verifying archival +/// history of the network, which makes sync quicker and more efficient, but also more data in +/// each [`Piece`] will be occupied with witness, thus wasting space that otherwise could have +/// been used for storing data (record part of a Piece) +/// * as this number goes down, witness get smaller leading to better piece utilization, but the +/// number of root blocks goes up making sync less efficient and less records are needed to be +/// lost before part of the archived history become unrecoverable, reducing reliability of the +/// data stored on the network const MERKLE_NUM_LEAVES: u32 = 256; +/// Size of witness for a segment record (in bytes). const WITNESS_SIZE: u32 = SHA256_HASH_SIZE as u32 * MERKLE_NUM_LEAVES.log2(); +/// Size of a segment record given the global piece size (in bytes). const RECORD_SIZE: u32 = PIECE_SIZE as u32 - WITNESS_SIZE; +/// Recorded History Segment Size includes half of the records (just data records) that will later +/// be erasure coded and together with corresponding witnesses will result in `MERKLE_NUM_LEAVES` +/// pieces of archival history. const RECORDED_HISTORY_SEGMENT_SIZE: u32 = RECORD_SIZE * MERKLE_NUM_LEAVES / 2; const PRE_GENESIS_OBJECT_SIZE: u32 = RECORDED_HISTORY_SEGMENT_SIZE; const PRE_GENESIS_OBJECT_COUNT: u32 = 10; @@ -181,18 +191,23 @@ const PRE_GENESIS_OBJECT_SEED: &[u8] = b"subspace"; // We assume initial plot size starts with the size of pre-genesis history (roughly, there is some // overhead in archiving process) const INITIAL_SOLUTION_RANGE: u64 = u64::MAX - / (PRE_GENESIS_OBJECT_SIZE * PRE_GENESIS_OBJECT_COUNT / PIECE_SIZE as u32) as u64 + / (PRE_GENESIS_OBJECT_SIZE * PRE_GENESIS_OBJECT_COUNT / PIECE_SIZE as u32) as u64 // number of total pieces in pre-genesis. * SLOT_PROBABILITY.0 / SLOT_PROBABILITY.1; +/// A ratio of `Normal` dispatch class within block, for `BlockWeight` and `BlockLength`. +const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); + +/// Maximum block length for non-`Normal` extrinsic is 5 MiB. +const MAX_BLOCK_LENGTH: u32 = 5 * 1024 * 1024; + parameter_types! { pub const Version: RuntimeVersion = VERSION; pub const BlockHashCount: BlockNumber = 2400; /// We allow for 2 seconds of compute with a 6 second average block time. - pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights - ::with_sensible_defaults(2 * WEIGHT_PER_SECOND, NORMAL_DISPATCH_RATIO); - pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength - ::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub SubspaceBlockWeights: BlockWeights = BlockWeights::with_sensible_defaults(2 * WEIGHT_PER_SECOND, NORMAL_DISPATCH_RATIO); + /// We allow for 3.75 MiB for `Normal` extrinsic with 5 MiB maximum block length. + pub SubspaceBlockLength: BlockLength = BlockLength::max_with_normal_ratio(MAX_BLOCK_LENGTH, NORMAL_DISPATCH_RATIO); pub const SS58Prefix: u8 = 42; } @@ -202,9 +217,9 @@ impl frame_system::Config for Runtime { /// The basic call filter to use in dispatchable. type BaseCallFilter = frame_support::traits::Everything; /// Block & extrinsics weights: base values and limits. - type BlockWeights = BlockWeights; + type BlockWeights = SubspaceBlockWeights; /// The maximum length of a block (in bytes). - type BlockLength = BlockLength; + type BlockLength = SubspaceBlockLength; /// The identifier used to distinguish between accounts. type AccountId = AccountId; /// The aggregated dispatch type that is available for extrinsics. @@ -220,7 +235,7 @@ impl frame_system::Config for Runtime { /// The hashing algorithm used. type Hashing = BlakeTwo256; /// The header type. - type Header = generic::Header; + type Header = Header; /// The ubiquitous event type. type Event = Event; /// The ubiquitous origin type. @@ -302,6 +317,7 @@ impl pallet_timestamp::Config for Runtime { } parameter_types! { + // TODO: this depends on the value of our native token? pub const ExistentialDeposit: u128 = 500; pub const MaxLocks: u32 = 50; } @@ -344,11 +360,6 @@ where type OverarchingCall = Call; } -parameter_types! { - pub OffencesWeightSoftLimit: Weight = Perbill::from_percent(60) * - BlockWeights::get().max_block; -} - impl pallet_offences_subspace::Config for Runtime { type Event = Event; type OnOffenceHandler = Subspace; @@ -365,14 +376,19 @@ construct_runtime!( NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, - Subspace: pallet_subspace::{Pallet, Call, Storage, Config, Event, ValidateUnsigned}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, - Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, - OffencesSubspace: pallet_offences_subspace::{Pallet, Storage, Event}, - Feeds: pallet_feeds::{Pallet, Call, Storage, Event}, + System: frame_system::{Pallet, Call, Config, Storage, Event} = 0, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 1, + + Subspace: pallet_subspace::{Pallet, Call, Storage, Config, Event, ValidateUnsigned} = 2, + OffencesSubspace: pallet_offences_subspace::{Pallet, Storage, Event} = 3, + + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event} = 4, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 5, + + Feeds: pallet_feeds::{Pallet, Call, Storage, Event} = 6, + + // Reserve some room for other pallets as we'll remove sudo pallet eventually. + Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event} = 100, } );