mirror of
https://github.com/datahaven-xyz/datahaven
synced 2026-05-24 09:50:01 +00:00
feat: add storage hub runtime (#40)
In this PR we add StorageHub pallets to the runtime. It will only be added if the `storage-hub` feature is activated. --------- Co-authored-by: Gonza Montiel <gonzamontiel@users.noreply.github.com>
This commit is contained in:
parent
a7d45969d5
commit
3ea6e57b66
9 changed files with 1950 additions and 214 deletions
911
operator/Cargo.lock
generated
911
operator/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -67,6 +67,7 @@ serde = { version = "1.0.197", default-features = false, features = ["derive"] }
|
|||
serde-big-array = { version = "0.3.2" }
|
||||
serde_json = { version = "1.0.127", default-features = false }
|
||||
sha3 = { version = "0.10", default-features = false }
|
||||
smallvec = "1.11.0"
|
||||
ssz_rs = { version = "0.9.0", default-features = false }
|
||||
ssz_rs_derive = { version = "0.9.0", default-features = false }
|
||||
static_assertions = { version = "1.1.0", default-features = false }
|
||||
|
|
@ -214,3 +215,31 @@ fc-mapping-sync = { git = "https://github.com/polkadot-evm/frontier", branch = "
|
|||
fc-rpc = { git = "https://github.com/polkadot-evm/frontier", branch = "stable2412", default-features = false }
|
||||
fc-rpc-core = { git = "https://github.com/polkadot-evm/frontier", branch = "stable2412", default-features = false }
|
||||
fc-storage = { git = "https://github.com/polkadot-evm/frontier", branch = "stable2412", default-features = false }
|
||||
|
||||
# StorageHub
|
||||
storage-hub-runtime = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
pallet-bucket-nfts = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
pallet-cr-randomness = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
pallet-file-system = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
pallet-file-system-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
pallet-payment-streams = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
pallet-payment-streams-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
pallet-proofs-dealer = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
pallet-proofs-dealer-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
pallet-randomness = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
pallet-storage-providers = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
pallet-storage-providers-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
shp-constants = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
shp-file-metadata = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
shp-traits = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
shp-treasury-funding = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
shp-forest-verifier = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
shp-file-key-verifier = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
shp-data-price-updater = { git = "https://github.com/Moonsong-Labs/storage-hub.git", rev = "e32b6a8fbbdf241d19d211c3325be7329869b85d", default-features = false }
|
||||
|
||||
pallet-nfts = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2412", default-features = false }
|
||||
# TODO: Change sp-trie to the next stable version when it's released with the applied fix of this [PR](https://github.com/paritytech/polkadot-sdk/pull/6486)
|
||||
sp-trie = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2412", default-features = false }
|
||||
|
||||
num-bigint = { version = "0.4.3", default-features = false }
|
||||
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ pub fn run() -> sc_cli::Result<()> {
|
|||
None => {
|
||||
let runner = cli.create_runner(&cli.run)?;
|
||||
runner.run_node_until_exit(|config| async move {
|
||||
match config.network.network_backend.unwrap_or_default() {
|
||||
match config.network.network_backend {
|
||||
sc_network::config::NetworkBackendType::Libp2p => match config.chain_spec {
|
||||
ref spec if spec.is_mainnet() => {
|
||||
service::new_full::<
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ frame-try-runtime = { workspace = true, optional = true }
|
|||
hex = { workspace = true }
|
||||
hex-literal = { workspace = true }
|
||||
log = { workspace = true }
|
||||
num-bigint = { workspace = true, optional = true }
|
||||
pallet-authorship = { workspace = true }
|
||||
pallet-babe = { workspace = true }
|
||||
pallet-balances = { workspace = true }
|
||||
|
|
@ -68,6 +69,7 @@ scale-info = { workspace = true, features = ["derive", "serde"] }
|
|||
serde_json = { workspace = true, default-features = false, features = [
|
||||
"alloc",
|
||||
] }
|
||||
smallvec = { workspace = true }
|
||||
snowbridge-beacon-primitives = { workspace = true }
|
||||
snowbridge-core = { workspace = true }
|
||||
snowbridge-inbound-queue-primitives = { workspace = true }
|
||||
|
|
@ -102,6 +104,28 @@ xcm = { workspace = true }
|
|||
xcm-builder = { workspace = true }
|
||||
xcm-executor = { workspace = true }
|
||||
|
||||
# StorageHub
|
||||
pallet-bucket-nfts = { workspace = true, optional = true }
|
||||
pallet-nfts = { workspace = true, optional = true }
|
||||
pallet-cr-randomness = { workspace = true, optional = true }
|
||||
pallet-file-system = { workspace = true, optional = true }
|
||||
pallet-file-system-runtime-api = { workspace = true, optional = true }
|
||||
pallet-payment-streams = { workspace = true, optional = true }
|
||||
pallet-payment-streams-runtime-api = { workspace = true, optional = true }
|
||||
pallet-proofs-dealer = { workspace = true, optional = true }
|
||||
pallet-proofs-dealer-runtime-api = { workspace = true, optional = true }
|
||||
pallet-randomness = { workspace = true, optional = true }
|
||||
pallet-storage-providers = { workspace = true, optional = true }
|
||||
pallet-storage-providers-runtime-api = { workspace = true, optional = true }
|
||||
shp-constants = { workspace = true, optional = true }
|
||||
shp-file-metadata = { workspace = true, optional = true }
|
||||
shp-traits = { workspace = true, optional = true }
|
||||
shp-treasury-funding = { workspace = true, optional = true }
|
||||
shp-forest-verifier = { workspace = true, optional = true }
|
||||
shp-file-key-verifier = { workspace = true, optional = true }
|
||||
shp-data-price-updater = { workspace = true, optional = true }
|
||||
sp-trie = { workspace = true, optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
substrate-wasm-builder = { workspace = true, optional = true, default-features = true }
|
||||
|
||||
|
|
@ -118,6 +142,29 @@ snowbridge-pallet-system-v2 = { workspace = true }
|
|||
snowbridge-outbound-queue-primitives = { workspace = true }
|
||||
|
||||
[features]
|
||||
storage-hub = [
|
||||
"dep:num-bigint",
|
||||
"dep:pallet-bucket-nfts",
|
||||
"dep:pallet-nfts",
|
||||
"dep:pallet-cr-randomness",
|
||||
"dep:pallet-file-system",
|
||||
"dep:pallet-file-system-runtime-api",
|
||||
"dep:pallet-payment-streams",
|
||||
"dep:pallet-payment-streams-runtime-api",
|
||||
"dep:pallet-proofs-dealer",
|
||||
"dep:pallet-proofs-dealer-runtime-api",
|
||||
"dep:pallet-randomness",
|
||||
"dep:pallet-storage-providers",
|
||||
"dep:pallet-storage-providers-runtime-api",
|
||||
"dep:shp-constants",
|
||||
"dep:shp-file-metadata",
|
||||
"dep:shp-traits",
|
||||
"dep:shp-treasury-funding",
|
||||
"dep:shp-forest-verifier",
|
||||
"dep:shp-file-key-verifier",
|
||||
"dep:shp-data-price-updater",
|
||||
"dep:sp-trie"
|
||||
]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"codec/std",
|
||||
|
|
@ -196,6 +243,33 @@ std = [
|
|||
"substrate-wasm-builder",
|
||||
"pallet-outbound-commitment-store/std",
|
||||
"pallet-datahaven-native-transfer/std",
|
||||
|
||||
# StorageHub
|
||||
"pallet-authorship/std",
|
||||
"pallet-balances/std",
|
||||
"pallet-bucket-nfts/std",
|
||||
"pallet-nfts/std",
|
||||
"pallet-cr-randomness/std",
|
||||
"pallet-file-system/std",
|
||||
"pallet-file-system-runtime-api/std",
|
||||
"pallet-payment-streams/std",
|
||||
"pallet-payment-streams-runtime-api/std",
|
||||
"pallet-proofs-dealer/std",
|
||||
"pallet-proofs-dealer-runtime-api/std",
|
||||
"pallet-randomness/std",
|
||||
"pallet-session/std",
|
||||
"pallet-storage-providers/std",
|
||||
"pallet-storage-providers-runtime-api/std",
|
||||
"pallet-sudo/std",
|
||||
"pallet-timestamp/std",
|
||||
"pallet-transaction-payment-rpc-runtime-api/std",
|
||||
"pallet-transaction-payment/std",
|
||||
"shp-constants/std",
|
||||
"shp-file-metadata/std",
|
||||
"shp-forest-verifier/std",
|
||||
"shp-traits/std",
|
||||
"shp-treasury-funding/std",
|
||||
"shp-file-key-verifier/std",
|
||||
]
|
||||
|
||||
runtime-benchmarks = [
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
//
|
||||
// For more information, please refer to <http://unlicense.org>
|
||||
|
||||
#[cfg(feature = "storage-hub")]
|
||||
mod storagehub;
|
||||
|
||||
pub mod runtime_params;
|
||||
|
||||
use super::{
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
use crate::Runtime;
|
||||
use crate::{Balance, BlockNumber, Runtime, NANO_UNIT, UNIT};
|
||||
use frame_support::dynamic_params::{dynamic_pallet_params, dynamic_params};
|
||||
use hex_literal::hex;
|
||||
use sp_core::{ConstU32, H160, H256};
|
||||
use sp_runtime::{BoundedVec, Perbill};
|
||||
use sp_std::vec;
|
||||
|
||||
#[cfg(feature = "storage-hub")]
|
||||
use crate::configs::storagehub::{ChallengeTicksTolerance, ReplicationTargetType, SpMinDeposit};
|
||||
|
||||
#[cfg(not(feature = "storage-hub"))]
|
||||
#[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::<Runtime>)]
|
||||
pub mod dynamic_params {
|
||||
use super::*;
|
||||
|
|
@ -50,6 +54,308 @@ pub mod dynamic_params {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "storage-hub")]
|
||||
#[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::<Runtime>)]
|
||||
pub mod dynamic_params {
|
||||
use super::*;
|
||||
#[dynamic_pallet_params]
|
||||
#[codec(index = 0)]
|
||||
pub mod runtime_config {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[codec(index = 0)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// Set the initial address of the Snowbridge Gateway contract on Ethereum.
|
||||
/// The fact that this is a parameter means that we can set it initially to the zero address,
|
||||
/// and then change it later via governance, to the actual address of the deployed contract.
|
||||
pub static EthereumGatewayAddress: H160 = H160::repeat_byte(0x0);
|
||||
|
||||
#[codec(index = 1)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// Set the initial address of the Rewards Registry contract on Ethereum.
|
||||
/// The fact that this is a parameter means that we can set it initially to the zero address,
|
||||
/// and then change it later via governance, to the actual address of the deployed contract.
|
||||
pub static RewardsRegistryAddress: H160 = H160::repeat_byte(0x0);
|
||||
|
||||
#[codec(index = 2)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// The Selector is the first 4 bytes of the keccak256 hash of the function signature("updateRewardsMerkleRoot(bytes32)")
|
||||
pub static RewardsUpdateSelector: BoundedVec<u8, ConstU32<4>> =
|
||||
BoundedVec::truncate_from(vec![0xdc, 0x3d, 0x04, 0xec]);
|
||||
|
||||
#[codec(index = 3)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// The RewardsAgentOrigin is the hash of the string "external_validators_rewards"
|
||||
/// TODO: Decide which agent origin we want to use. Currently for testing it's the zero hash
|
||||
pub static RewardsAgentOrigin: H256 = H256::from_slice(&hex!(
|
||||
"c505dfb2df107d106d08bd0f1a0acd10052ca9aa078629a4ccfd0c90c6e69b65"
|
||||
));
|
||||
|
||||
// ╔══════════════════════ StorageHub Pallets ═══════════════════════╗
|
||||
|
||||
#[codec(index = 4)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// 20 UNITs
|
||||
pub static SlashAmountPerMaxFileSize: Balance = 20 * UNIT;
|
||||
|
||||
#[codec(index = 5)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// 10k UNITs * [`MinChallengePeriod`] = 10k UNITs * 30 = 300k UNITs
|
||||
///
|
||||
/// This can be interpreted as "a Provider with 10k UNITs of stake would get the minimum challenge period".
|
||||
pub static StakeToChallengePeriod: Balance =
|
||||
10_000 * UNIT * Into::<u128>::into(MinChallengePeriod::get());
|
||||
|
||||
#[codec(index = 6)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// The [`CheckpointChallengePeriod`] is set to be equal to the longest possible challenge period
|
||||
/// (i.e. the [`StakeToChallengePeriod`] divided by the [`SpMinDeposit`]).
|
||||
///
|
||||
// 300k UNITs / 100 UNITs + 50 + 1 = ~3k ticks (i.e. ~5 hours with 6 seconds per tick)
|
||||
pub static CheckpointChallengePeriod: BlockNumber = (StakeToChallengePeriod::get()
|
||||
/ SpMinDeposit::get()).saturating_add(ChallengeTicksTolerance::get() as u128).saturating_add(1)
|
||||
.try_into()
|
||||
.expect(
|
||||
"StakeToChallengePeriod / SpMinDeposit should be a number of ticks that can fit in BlockNumber numerical type",
|
||||
);
|
||||
|
||||
#[codec(index = 7)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// 30 ticks, or 3 minutes with 6 seconds per tick.
|
||||
pub static MinChallengePeriod: BlockNumber = 30;
|
||||
|
||||
#[codec(index = 8)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// Price decreases when system utilisation is below 30%.
|
||||
pub static SystemUtilisationLowerThresholdPercentage: Perbill = Perbill::from_percent(30);
|
||||
|
||||
#[codec(index = 9)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// Price increases when system utilisation is above 95%.
|
||||
pub static SystemUtilisationUpperThresholdPercentage: Perbill = Perbill::from_percent(95);
|
||||
|
||||
#[codec(index = 10)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// 50 [`NANOUNIT`]s is the price per GB of data, per tick.
|
||||
///
|
||||
/// With 6 seconds per tick, this means that over a month, the price of 1 GB is:
|
||||
/// 50e-9 [`UNIT`]s * 10 ticks/min * 60 min/h * 24 h/day * 30 days/month = 21.6e-3 [`UNIT`]s
|
||||
pub static MostlyStablePrice: Balance = 50 * NANO_UNIT;
|
||||
|
||||
#[codec(index = 11)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// [`MostlyStablePrice`] * 10 = 500 [`NANOUNIT`]s
|
||||
pub static MaxPrice: Balance = MostlyStablePrice::get() * 10;
|
||||
|
||||
#[codec(index = 12)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// [`MostlyStablePrice`] / 5 = 10 [`NANOUNIT`]s
|
||||
pub static MinPrice: Balance = MostlyStablePrice::get() / 5;
|
||||
|
||||
#[codec(index = 13)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// u = [`UpperExponentFactor`]
|
||||
/// system_utilisation = 1
|
||||
///
|
||||
/// [`MaxPrice`] = [`MostlyStablePrice`] + u * e ^ ( 1 - [`SystemUtilisationUpperThresholdPercentage`] )
|
||||
///
|
||||
/// 500 = 50 + u * (e ^ (1 - 0.95) - 1)
|
||||
/// u = (500 - 50) / (e ^ (1 - 0.95) - 1) ≈ 8777
|
||||
pub static UpperExponentFactor: u32 = 8777;
|
||||
|
||||
#[codec(index = 14)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// l = [`LowerExponentFactor`]
|
||||
/// system_utilisation = 0
|
||||
///
|
||||
/// [`MinPrice`] = [`MostlyStablePrice`] - u * e ^ ( [`SystemUtilisationLowerThresholdPercentage`] - 0 )
|
||||
///
|
||||
/// 10 = 50 - l * (e ^ (0.3 - 0) - 1)
|
||||
/// l = (50 - 10) / (e ^ (0.3 - 0) - 1) ≈ 114
|
||||
pub static LowerExponentFactor: u32 = 114;
|
||||
|
||||
#[codec(index = 15)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// 0-size bucket fixed rate payment stream representing the price for 1 GB of data.
|
||||
///
|
||||
/// Base rate for a new fixed payment stream established between an MSP and a user.
|
||||
pub static ZeroSizeBucketFixedRate: Balance = 50 * NANO_UNIT;
|
||||
|
||||
#[codec(index = 16)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// Ideal utilisation rate of the system
|
||||
pub static IdealUtilisationRate: Perbill = Perbill::from_percent(85);
|
||||
|
||||
#[codec(index = 17)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// Decay rate of the power of two function that determines the percentage of funds that go to
|
||||
/// the treasury for utilisation rates greater than the ideal.
|
||||
pub static DecayRate: Perbill = Perbill::from_percent(5);
|
||||
|
||||
#[codec(index = 18)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// The minimum treasury cut that can be taken from the amount charged from a payment stream.
|
||||
pub static MinimumTreasuryCut: Perbill = Perbill::from_percent(1);
|
||||
|
||||
#[codec(index = 19)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// The maximum treasury cut that can be taken from the amount charged from a payment stream.
|
||||
pub static MaximumTreasuryCut: Perbill = Perbill::from_percent(5);
|
||||
|
||||
#[codec(index = 20)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// The penalty a BSP must pay when they forcefully stop storing a file.
|
||||
/// We set this to be half of the `SlashAmountPerMaxFileSize` with the rationale that
|
||||
/// for a BSP that has lost this file, it should be more convenient to voluntarily
|
||||
/// show up and pay this penalty in good faith, rather than risking being slashed for
|
||||
/// being unable to submit a proof that should include this file.
|
||||
pub static BspStopStoringFilePenalty: Balance = SlashAmountPerMaxFileSize::get() / 2;
|
||||
|
||||
/// Time-to-live for a provider to top up their deposit to cover a capacity deficit.
|
||||
/// Set to 14_400 relay blocks = 1 day with 6 second timeslots.
|
||||
#[codec(index = 21)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static ProviderTopUpTtl: BlockNumber = 14_400;
|
||||
|
||||
/// The following parameters are the replication targets for the different security levels
|
||||
/// that a storage request (and thus the file it represents) can have.
|
||||
///
|
||||
/// These are associated with the probability that a malicious actor could hold the file hostage by controlling
|
||||
/// all BSPs that volunteered and confirmed storing it.
|
||||
/// The values were calculated from the probabilities derived using binomial distribution calculations,
|
||||
/// where the total number of BSPs is set to 1000, the fraction of malicious BSPs is 1/3, and the target number of BSPs
|
||||
/// is incremented until the probability of all selected BSPs being malicious falls below the required percentage.
|
||||
///
|
||||
/// The formula used is:
|
||||
/// num_bsps = 1000
|
||||
/// fraction_evil = 1/3
|
||||
/// n_evil = int(num_bsps * fraction_evil) // = 333
|
||||
/// target = range(1, num_bsps)
|
||||
/// p_init = target / num_bsps
|
||||
/// prob = binomial_cdf_at_least(n_evil, target, p_init)
|
||||
///
|
||||
/// This ensures that the replication targets were selected optimally to balance security and storage efficiency.
|
||||
/// --------------------------------------------------------------------------------------------------------------------
|
||||
/// The amount of BSPs that a basic security storage request should use as the replication target.
|
||||
///
|
||||
/// This must be the lowest amount of BSPs that guarantee that the probability that a malicious
|
||||
/// actor controlling 1/3 of the BSPs can hold the file hostage by controlling all its
|
||||
/// volunteered BSPs is ~1%.
|
||||
#[codec(index = 22)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static BasicReplicationTarget: ReplicationTargetType = 7;
|
||||
|
||||
/// The amount of BSPs that a standard security storage request should use as the replication target.
|
||||
///
|
||||
/// This must be the lowest amount of BSPs that guarantee that the probability that a malicious
|
||||
/// actor controlling 1/3 of the BSPs can hold the file hostage by controlling all its
|
||||
/// volunteered BSPs is ~0.1%.
|
||||
#[codec(index = 23)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static StandardReplicationTarget: ReplicationTargetType = 12;
|
||||
|
||||
/// The amount of BSPs that a high security storage request should use as the replication target.
|
||||
///
|
||||
/// This must be the lowest amount of BSPs that guarantee that the probability that a malicious
|
||||
/// actor controlling 1/3 of the BSPs can hold the file hostage by controlling all its
|
||||
/// volunteered BSPs is ~0.01%.
|
||||
#[codec(index = 24)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static HighSecurityReplicationTarget: ReplicationTargetType = 17;
|
||||
|
||||
/// The amount of BSPs that a super high security storage request should use as the replication target.
|
||||
///
|
||||
/// This must be the lowest amount of BSPs that guarantee that the probability that a malicious
|
||||
/// actor controlling 1/3 of the BSPs can hold the file hostage by controlling all its
|
||||
/// volunteered BSPs is ~0.001%.
|
||||
#[codec(index = 25)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static SuperHighSecurityReplicationTarget: ReplicationTargetType = 22;
|
||||
|
||||
/// The amount of BSPs that an ultra high security storage request should use as the replication target.
|
||||
///
|
||||
/// This must be the lowest amount of BSPs that guarantee that the probability that a malicious
|
||||
/// actor controlling 1/3 of the BSPs can hold the file hostage by controlling all its
|
||||
/// volunteered BSPs is ~0.0001%.
|
||||
#[codec(index = 26)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static UltraHighSecurityReplicationTarget: ReplicationTargetType = 26;
|
||||
|
||||
/// The maximum amount of BSPs that a user can require a storage request to use as the replication target.
|
||||
///
|
||||
/// This is a safety measure to prevent users from issuing storage requests that are too large and would
|
||||
/// require a large number of BSPs to store the file.
|
||||
#[codec(index = 27)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static MaxReplicationTarget: ReplicationTargetType =
|
||||
UltraHighSecurityReplicationTarget::get()
|
||||
.saturating_mul(150)
|
||||
.saturating_div(100);
|
||||
|
||||
/// The amount of ticks that have to pass for the threshold to volunteer for a specific storage request
|
||||
/// to arrive at its maximum value.
|
||||
///
|
||||
/// This is big enough so volunteering for a storage request is not open to everyone inmediatly, preventing
|
||||
/// a select few BSPs from taking all the requests, while small enough so that storage requests don't take
|
||||
/// too long to be filled.
|
||||
#[codec(index = 28)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static TickRangeToMaximumThreshold: BlockNumber = 3600; // 6 hours with a 6 second block time
|
||||
|
||||
/// The amount of ticks after which a storage request is considered expired and can be removed from storage.
|
||||
///
|
||||
/// It's a function of the TickRangeToMaximumThreshold since it does not make sense for a storage request to
|
||||
/// expire before arriving at its maximum threshold for volunteering.
|
||||
#[codec(index = 29)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static StorageRequestTtl: BlockNumber = TickRangeToMaximumThreshold::get()
|
||||
.saturating_mul(110)
|
||||
.saturating_div(100);
|
||||
|
||||
/// The minimum amount of ticks between a stop storing request from a BSP and that BSP being able to
|
||||
/// confirm to stop storing that file key.
|
||||
///
|
||||
/// It's a function of the checkpoint challenge period since this makes it so BSPs can't avoid checkpoint
|
||||
/// challenges by stopping storing a file key right before the challenge period ends in case they lost it.
|
||||
#[codec(index = 30)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static MinWaitForStopStoring: BlockNumber = CheckpointChallengePeriod::get()
|
||||
.saturating_mul(110)
|
||||
.saturating_div(100);
|
||||
|
||||
#[codec(index = 31)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// 20 ticks, or 2 minutes with 6 seconds per tick.
|
||||
pub static MinSeedPeriod: BlockNumber = 20;
|
||||
|
||||
#[codec(index = 32)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// 10k UNITs * [`MinSeedPeriod`] = 10k UNITs * 20 = 200k UNITs
|
||||
///
|
||||
/// This can be interpreted as "a Provider with 10k UNITs of stake would get the minimum seed period".
|
||||
pub static StakeToSeedPeriod: Balance =
|
||||
10_000 * UNIT * Into::<u128>::into(MinSeedPeriod::get());
|
||||
|
||||
#[codec(index = 33)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// The amount of ticks to charge a user upfront when it tries to issue a new storage request.
|
||||
/// This is done as a deterrent to avoid users spamming the network with huge files but never
|
||||
/// actually planning to store them longterm.
|
||||
///
|
||||
/// 72k ticks = 5 days with 6 seconds per tick.
|
||||
/// This means that a user must pay for 5 days of storage upfront, which gets transferred to the
|
||||
/// treasury. Governance can then decide what to do with the accumulated funds.
|
||||
///
|
||||
/// With a stable price (defined as `MostlyStablePrice` in this file) of 50 NANOUNITs per gigabyte
|
||||
/// per tick and a standard replication target (`StandardReplicationTarget`) of 12 BSPs, the upfront
|
||||
/// cost for the user to issue a storage request for a 1 GB file would be:
|
||||
/// 50 NANOUNITs per gigabyte per tick * 12 BSPs * 72k ticks * 1 GB = 0.0432 UNITs
|
||||
pub static UpfrontTicksToPay: BlockNumber = 72_000;
|
||||
// ╚══════════════════════ StorageHub Pallets ═══════════════════════╝
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
impl Default for RuntimeParameters {
|
||||
fn default() -> Self {
|
||||
|
|
|
|||
610
operator/runtime/stagenet/src/configs/storagehub/mod.rs
Normal file
610
operator/runtime/stagenet/src/configs/storagehub/mod.rs
Normal file
|
|
@ -0,0 +1,610 @@
|
|||
use super::{
|
||||
AccountId, Balance, Balances, BlockNumber, Hash, RuntimeEvent, RuntimeHoldReason, UNIT,
|
||||
};
|
||||
use crate::configs::runtime_params::dynamic_params::runtime_config;
|
||||
use crate::{
|
||||
BucketNfts, Nfts, PaymentStreams, ProofsDealer, Providers, Runtime, Signature, WeightToFee,
|
||||
HOURS,
|
||||
};
|
||||
use core::marker::PhantomData;
|
||||
use datahaven_runtime_common::time::{DAYS, MINUTES};
|
||||
use frame_support::pallet_prelude::DispatchClass;
|
||||
use frame_support::traits::AsEnsureOriginWithArg;
|
||||
use frame_support::{
|
||||
parameter_types,
|
||||
traits::{ConstU128, ConstU32, ConstU64},
|
||||
weights::Weight,
|
||||
};
|
||||
use frame_system::pallet_prelude::BlockNumberFor;
|
||||
use frame_system::EnsureRoot;
|
||||
use frame_system::EnsureSigned;
|
||||
use num_bigint::BigUint;
|
||||
use pallet_nfts::PalletFeatures;
|
||||
use polkadot_runtime_common::prod_or_fast;
|
||||
use shp_data_price_updater::{MostlyStablePriceIndexUpdater, MostlyStablePriceIndexUpdaterConfig};
|
||||
use shp_file_key_verifier::FileKeyVerifier;
|
||||
use shp_file_metadata::{ChunkId, FileMetadata};
|
||||
use shp_forest_verifier::ForestVerifier;
|
||||
use shp_treasury_funding::{
|
||||
LinearThenPowerOfTwoTreasuryCutCalculator, LinearThenPowerOfTwoTreasuryCutCalculatorConfig,
|
||||
};
|
||||
use sp_core::Get;
|
||||
use sp_core::Hasher;
|
||||
use sp_core::H256;
|
||||
use sp_runtime::traits::Convert;
|
||||
use sp_runtime::traits::ConvertBack;
|
||||
use sp_runtime::traits::Verify;
|
||||
use sp_runtime::traits::Zero;
|
||||
use sp_runtime::SaturatedConversion;
|
||||
use sp_runtime::{traits::BlakeTwo256, Perbill};
|
||||
use sp_std::convert::{From, Into};
|
||||
use sp_std::vec;
|
||||
use sp_trie::{LayoutV1, TrieConfiguration, TrieLayout};
|
||||
|
||||
/// Type representing the storage data units in StorageHub.
|
||||
pub type StorageDataUnit = u64;
|
||||
|
||||
pub type StorageProofsMerkleTrieLayout = LayoutV1<BlakeTwo256>;
|
||||
|
||||
pub type Hashing = BlakeTwo256;
|
||||
|
||||
// TODO: remove this and replace with pallet treasury
|
||||
pub struct TreasuryAccount;
|
||||
impl Get<AccountId> for TreasuryAccount {
|
||||
fn get() -> AccountId {
|
||||
AccountId::from([0; 32])
|
||||
}
|
||||
}
|
||||
|
||||
/****** NFTs pallet ******/
|
||||
parameter_types! {
|
||||
pub const CollectionDeposit: Balance = 100 * UNIT;
|
||||
pub const ItemDeposit: Balance = 1 * UNIT;
|
||||
pub const MetadataDepositBase: Balance = 10 * UNIT;
|
||||
pub const MetadataDepositPerByte: Balance = 1 * UNIT;
|
||||
pub const ApprovalsLimit: u32 = 20;
|
||||
pub const ItemAttributesApprovalsLimit: u32 = 20;
|
||||
pub const MaxTips: u32 = 10;
|
||||
pub const MaxDeadlineDuration: BlockNumber = 12 * 30 * DAYS;
|
||||
pub const MaxAttributesPerCall: u32 = 10;
|
||||
pub Features: PalletFeatures = PalletFeatures::all_enabled();
|
||||
}
|
||||
|
||||
impl pallet_nfts::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type CollectionId = u32;
|
||||
type ItemId = u32;
|
||||
type Currency = Balances;
|
||||
type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
|
||||
type ForceOrigin = frame_system::EnsureRoot<AccountId>;
|
||||
type CollectionDeposit = CollectionDeposit;
|
||||
type ItemDeposit = ItemDeposit;
|
||||
type MetadataDepositBase = MetadataDepositBase;
|
||||
type AttributeDepositBase = MetadataDepositBase;
|
||||
type DepositPerByte = MetadataDepositPerByte;
|
||||
type StringLimit = ConstU32<256>;
|
||||
type KeyLimit = ConstU32<64>;
|
||||
type ValueLimit = ConstU32<256>;
|
||||
type ApprovalsLimit = ApprovalsLimit;
|
||||
type ItemAttributesApprovalsLimit = ItemAttributesApprovalsLimit;
|
||||
type MaxTips = MaxTips;
|
||||
type MaxDeadlineDuration = MaxDeadlineDuration;
|
||||
type MaxAttributesPerCall = MaxAttributesPerCall;
|
||||
type Features = Features;
|
||||
type OffchainSignature = Signature;
|
||||
type OffchainPublic = <Signature as Verify>::Signer;
|
||||
type WeightInfo = pallet_nfts::weights::SubstrateWeight<Runtime>;
|
||||
type Locker = ();
|
||||
}
|
||||
/****** ****** ****** ******/
|
||||
|
||||
/****** Relay Randomness pallet ******/
|
||||
impl pallet_randomness::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type BabeDataGetter = BabeDataGetter;
|
||||
type BabeBlockGetter = BlockNumberGetter;
|
||||
type WeightInfo = ();
|
||||
type BabeDataGetterBlockNumber = BlockNumber;
|
||||
}
|
||||
|
||||
pub struct BabeDataGetter;
|
||||
impl pallet_randomness::GetBabeData<u64, Hash> for BabeDataGetter {
|
||||
fn get_epoch_index() -> u64 {
|
||||
todo!("implement `get_epoch_index`");
|
||||
}
|
||||
fn get_epoch_randomness() -> Hash {
|
||||
todo!("implement `get_epoch_randomness`");
|
||||
}
|
||||
fn get_parent_randomness() -> Hash {
|
||||
todo!("implement `get_parent_randomness`");
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BlockNumberGetter {}
|
||||
impl sp_runtime::traits::BlockNumberProvider for BlockNumberGetter {
|
||||
type BlockNumber = BlockNumber;
|
||||
|
||||
fn current_block_number() -> Self::BlockNumber {
|
||||
frame_system::Pallet::<Runtime>::block_number()
|
||||
}
|
||||
}
|
||||
|
||||
/****** ****** ****** ******/
|
||||
|
||||
/****** Storage Providers pallet ******/
|
||||
parameter_types! {
|
||||
pub const SpMinDeposit: Balance = 100 * UNIT;
|
||||
pub const BucketDeposit: Balance = 100 * UNIT;
|
||||
pub const BspSignUpLockPeriod: BlockNumber = 90 * DAYS; // ~3 months
|
||||
pub const MaxBlocksForRandomness: BlockNumber = prod_or_fast!(2 * HOURS, 2 * MINUTES);
|
||||
// TODO: If the next line is uncommented (which should be eventually, replacing the line above), compilation breaks (most likely because of mismatched dependency issues)
|
||||
// pub const MaxBlocksForRandomness: BlockNumber = prod_or_fast!(2 * runtime_constants::time::EPOCH_DURATION_IN_SLOTS, 2 * MINUTES);
|
||||
}
|
||||
|
||||
impl pallet_storage_providers::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = pallet_storage_providers::weights::SubstrateWeight<Runtime>;
|
||||
type ProvidersRandomness = pallet_randomness::RandomnessFromOneEpochAgo<Runtime>;
|
||||
type PaymentStreams = PaymentStreams;
|
||||
type ProofDealer = ProofsDealer;
|
||||
type FileMetadataManager = FileMetadata<
|
||||
{ shp_constants::H_LENGTH },
|
||||
{ shp_constants::FILE_CHUNK_SIZE },
|
||||
{ shp_constants::FILE_SIZE_TO_CHALLENGES },
|
||||
>;
|
||||
type NativeBalance = Balances;
|
||||
type CrRandomness = MockCrRandomness;
|
||||
type RuntimeHoldReason = RuntimeHoldReason;
|
||||
type StorageDataUnit = StorageDataUnit;
|
||||
type StorageDataUnitAndBalanceConvert = StorageDataUnitAndBalanceConverter;
|
||||
type SpCount = u32;
|
||||
type BucketCount = u128;
|
||||
type MerklePatriciaRoot = Hash;
|
||||
type MerkleTrieHashing = Hashing;
|
||||
type ProviderId = Hash;
|
||||
type ProviderIdHashing = Hashing;
|
||||
type ValuePropId = Hash;
|
||||
type ValuePropIdHashing = Hashing;
|
||||
type ReadAccessGroupId = <Self as pallet_nfts::Config>::CollectionId;
|
||||
type ProvidersProofSubmitters = ProofsDealer;
|
||||
type ReputationWeightType = u32;
|
||||
type StorageHubTickGetter = ProofsDealer;
|
||||
type Treasury = TreasuryAccount;
|
||||
type SpMinDeposit = SpMinDeposit;
|
||||
type SpMinCapacity = ConstU64<2>;
|
||||
type DepositPerData = ConstU128<2>;
|
||||
type MaxFileSize = ConstU64<{ u64::MAX }>;
|
||||
type MaxMultiAddressSize = ConstU32<100>;
|
||||
type MaxMultiAddressAmount = ConstU32<5>;
|
||||
type MaxProtocols = ConstU32<100>;
|
||||
type BucketDeposit = BucketDeposit;
|
||||
type BucketNameLimit = ConstU32<100>;
|
||||
type MaxBlocksForRandomness = MaxBlocksForRandomness;
|
||||
type MinBlocksBetweenCapacityChanges = ConstU32<10>;
|
||||
type DefaultMerkleRoot = DefaultMerkleRoot<StorageProofsMerkleTrieLayout>;
|
||||
type SlashAmountPerMaxFileSize = runtime_config::SlashAmountPerMaxFileSize;
|
||||
type StartingReputationWeight = ConstU32<1>;
|
||||
type BspSignUpLockPeriod = BspSignUpLockPeriod;
|
||||
type MaxCommitmentSize = ConstU32<1000>;
|
||||
type ZeroSizeBucketFixedRate = runtime_config::ZeroSizeBucketFixedRate;
|
||||
type ProviderTopUpTtl = runtime_config::ProviderTopUpTtl;
|
||||
type MaxExpiredItemsInBlock = ConstU32<100>;
|
||||
}
|
||||
|
||||
pub struct StorageDataUnitAndBalanceConverter;
|
||||
impl Convert<StorageDataUnit, Balance> for StorageDataUnitAndBalanceConverter {
|
||||
fn convert(data_unit: StorageDataUnit) -> Balance {
|
||||
data_unit.saturated_into()
|
||||
}
|
||||
}
|
||||
impl ConvertBack<StorageDataUnit, Balance> for StorageDataUnitAndBalanceConverter {
|
||||
fn convert_back(balance: Balance) -> StorageDataUnit {
|
||||
balance.saturated_into()
|
||||
}
|
||||
}
|
||||
|
||||
pub type HasherOutT<T> = <<T as TrieLayout>::Hash as Hasher>::Out;
|
||||
pub struct DefaultMerkleRoot<T>(PhantomData<T>);
|
||||
impl<T: TrieConfiguration> Get<HasherOutT<T>> for DefaultMerkleRoot<T> {
|
||||
fn get() -> HasherOutT<T> {
|
||||
sp_trie::empty_trie_root::<T>()
|
||||
}
|
||||
}
|
||||
|
||||
/****** ****** ****** ******/
|
||||
|
||||
/****** Payment Streams pallet ******/
|
||||
parameter_types! {
|
||||
pub const PaymentStreamHoldReason: RuntimeHoldReason = RuntimeHoldReason::PaymentStreams(pallet_payment_streams::HoldReason::PaymentStreamDeposit);
|
||||
pub const UserWithoutFundsCooldown: BlockNumber = 100;
|
||||
}
|
||||
|
||||
impl pallet_payment_streams::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = pallet_payment_streams::weights::SubstrateWeight<Runtime>;
|
||||
type NativeBalance = Balances;
|
||||
type ProvidersPallet = Providers;
|
||||
type RuntimeHoldReason = RuntimeHoldReason;
|
||||
type UserWithoutFundsCooldown = UserWithoutFundsCooldown; // Amount of blocks that a user will have to wait before being able to clear the out of funds flag
|
||||
type NewStreamDeposit = ConstU32<10>; // Amount of blocks that the deposit of a new stream should be able to pay for
|
||||
type Units = StorageDataUnit; // Storage unit
|
||||
type BlockNumberToBalance = BlockNumberToBalance;
|
||||
type ProvidersProofSubmitters = ProofsDealer;
|
||||
type TreasuryCutCalculator = LinearThenPowerOfTwoTreasuryCutCalculator<Runtime, Perbill>;
|
||||
type TreasuryAccount = TreasuryAccount;
|
||||
type MaxUsersToCharge = ConstU32<10>;
|
||||
type BaseDeposit = ConstU128<10>;
|
||||
}
|
||||
|
||||
// Converter from the BlockNumber type to the Balance type for math
|
||||
pub struct BlockNumberToBalance;
|
||||
impl Convert<BlockNumber, Balance> for BlockNumberToBalance {
|
||||
fn convert(block_number: BlockNumber) -> Balance {
|
||||
block_number.into() // In this converter we assume that the block number type is smaller in size than the balance type
|
||||
}
|
||||
}
|
||||
|
||||
impl LinearThenPowerOfTwoTreasuryCutCalculatorConfig<Perbill> for Runtime {
|
||||
type Balance = Balance;
|
||||
type ProvidedUnit = StorageDataUnit;
|
||||
type IdealUtilisationRate = runtime_config::IdealUtilisationRate;
|
||||
type DecayRate = runtime_config::DecayRate;
|
||||
type MinimumCut = runtime_config::MinimumTreasuryCut;
|
||||
type MaximumCut = runtime_config::MaximumTreasuryCut;
|
||||
}
|
||||
/****** ****** ****** ******/
|
||||
|
||||
/****** Proofs Dealer pallet ******/
|
||||
const RANDOM_CHALLENGES_PER_BLOCK: u32 = 10;
|
||||
const MAX_CUSTOM_CHALLENGES_PER_BLOCK: u32 = 10;
|
||||
const TOTAL_MAX_CHALLENGES_PER_BLOCK: u32 =
|
||||
RANDOM_CHALLENGES_PER_BLOCK + MAX_CUSTOM_CHALLENGES_PER_BLOCK;
|
||||
|
||||
parameter_types! {
|
||||
pub const RandomChallengesPerBlock: u32 = RANDOM_CHALLENGES_PER_BLOCK;
|
||||
pub const MaxCustomChallengesPerBlock: u32 = MAX_CUSTOM_CHALLENGES_PER_BLOCK;
|
||||
pub const TotalMaxChallengesPerBlock: u32 = TOTAL_MAX_CHALLENGES_PER_BLOCK;
|
||||
pub const TargetTicksStorageOfSubmitters: u32 = 3;
|
||||
pub const ChallengeHistoryLength: BlockNumber = 100;
|
||||
pub const ChallengesQueueLength: u32 = 100;
|
||||
pub const ChallengesFee: Balance = 1 * UNIT;
|
||||
pub const ChallengeTicksTolerance: u32 = 50;
|
||||
}
|
||||
|
||||
impl pallet_proofs_dealer::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = pallet_proofs_dealer::weights::SubstrateWeight<Runtime>;
|
||||
type ProvidersPallet = Providers;
|
||||
type NativeBalance = Balances;
|
||||
type MerkleTrieHash = Hash;
|
||||
type MerkleTrieHashing = BlakeTwo256;
|
||||
type ForestVerifier = ForestVerifier<StorageProofsMerkleTrieLayout, { BlakeTwo256::LENGTH }>;
|
||||
type KeyVerifier = FileKeyVerifier<
|
||||
StorageProofsMerkleTrieLayout,
|
||||
{ shp_constants::H_LENGTH },
|
||||
{ shp_constants::FILE_CHUNK_SIZE },
|
||||
{ shp_constants::FILE_SIZE_TO_CHALLENGES },
|
||||
>;
|
||||
type StakeToBlockNumber = SaturatingBalanceToBlockNumber;
|
||||
type RandomChallengesPerBlock = RandomChallengesPerBlock;
|
||||
type MaxCustomChallengesPerBlock = MaxCustomChallengesPerBlock;
|
||||
type MaxSubmittersPerTick = MaxSubmittersPerTick;
|
||||
type TargetTicksStorageOfSubmitters = TargetTicksStorageOfSubmitters;
|
||||
type ChallengeHistoryLength = ChallengeHistoryLength;
|
||||
type ChallengesQueueLength = ChallengesQueueLength;
|
||||
type CheckpointChallengePeriod = runtime_config::CheckpointChallengePeriod;
|
||||
type ChallengesFee = ChallengesFee;
|
||||
type Treasury = TreasuryAccount;
|
||||
// TODO: Once the client logic to keep track of CR randomness deadlines and execute their submissions is implemented
|
||||
// AND after the chain has been live for enough time to have enough providers to avoid the commit-reveal randomness being
|
||||
// gameable, the randomness provider should be CrRandomness
|
||||
type RandomnessProvider = pallet_randomness::ParentBlockRandomness<Runtime>;
|
||||
type StakeToChallengePeriod = runtime_config::StakeToChallengePeriod;
|
||||
type MinChallengePeriod = runtime_config::MinChallengePeriod;
|
||||
type ChallengeTicksTolerance = ChallengeTicksTolerance;
|
||||
type BlockFullnessPeriod = ChallengeTicksTolerance; // We purposely set this to `ChallengeTicksTolerance` so that spamming of the chain is evaluated for the same blocks as the tolerance BSPs are given.
|
||||
type BlockFullnessHeadroom = BlockFullnessHeadroom;
|
||||
type MinNotFullBlocksRatio = MinNotFullBlocksRatio;
|
||||
type MaxSlashableProvidersPerTick = MaxSlashableProvidersPerTick;
|
||||
}
|
||||
|
||||
// Converter from the Balance type to the BlockNumber type for math.
|
||||
// It performs a saturated conversion, so that the result is always a valid BlockNumber.
|
||||
pub struct SaturatingBalanceToBlockNumber;
|
||||
impl Convert<Balance, BlockNumberFor<Runtime>> for SaturatingBalanceToBlockNumber {
|
||||
fn convert(block_number: Balance) -> BlockNumberFor<Runtime> {
|
||||
block_number.saturated_into()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MaxSubmittersPerTick;
|
||||
impl Get<u32> for MaxSubmittersPerTick {
|
||||
fn get() -> u32 {
|
||||
let block_weights = <Runtime as frame_system::Config>::BlockWeights::get();
|
||||
|
||||
// Not being able to get the `max_total` weight for the Normal dispatch class is considered
|
||||
// a critical bug. So we set it to be zero, essentially allowing zero submitters per tick.
|
||||
// This value can be read from the constants of a node, but with the current configuration, this is:
|
||||
//
|
||||
// max_total: {
|
||||
// ref_time: 1,500,000,000,000
|
||||
// proof_size: 3,932,160
|
||||
// }
|
||||
let max_weight_for_class = block_weights
|
||||
.get(DispatchClass::Normal)
|
||||
.max_total
|
||||
.unwrap_or(Zero::zero());
|
||||
|
||||
// Get the minimum weight a `submit_proof` extrinsic can have.
|
||||
// This would be the case where the proof is just made up of a single file key proof, that is a
|
||||
// response to all the random challenges. And there are no checkpoint challenges.
|
||||
// With the current benchmarking, this is:
|
||||
//
|
||||
// TODO: UPDATE THIS WITH THE FINAL BENCHMARKING
|
||||
// min_weight_for_submit_proof: {
|
||||
// ref_time: 2,980,252,675
|
||||
// proof_size: 16,056
|
||||
// }
|
||||
let min_weight_for_submit_proof =
|
||||
<pallet_proofs_dealer::weights::SubstrateWeight<Runtime> as pallet_proofs_dealer::weights::WeightInfo>::submit_proof_no_checkpoint_challenges_key_proofs(1);
|
||||
|
||||
// Calculate the maximum number of submit proofs that is possible to have in a block/tick.
|
||||
// With the current values, this would be:
|
||||
//
|
||||
// TODO: UPDATE THIS WITH THE FINAL BENCHMARKING
|
||||
// 244 proof submissions per block (limited by `proof_size`)
|
||||
let max_proof_submissions_per_tick = max_weight_for_class
|
||||
.checked_div_per_component(&min_weight_for_submit_proof)
|
||||
.unwrap_or(0);
|
||||
|
||||
// Saturating u64 to u32 should be enough.
|
||||
max_proof_submissions_per_tick.saturated_into()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BlockFullnessHeadroom;
|
||||
impl Get<Weight> for BlockFullnessHeadroom {
|
||||
fn get() -> Weight {
|
||||
// The block headroom is set to be the maximum benchmarked weight that a `submit_proof` extrinsic can have.
|
||||
// That is, when the proof includes two file key proofs for every single random challenge, and for the maximum
|
||||
// number of checkpoint challenges as well.
|
||||
<pallet_proofs_dealer::weights::SubstrateWeight<Runtime> as pallet_proofs_dealer::weights::WeightInfo>::submit_proof_with_checkpoint_challenges_key_proofs(TOTAL_MAX_CHALLENGES_PER_BLOCK * 2)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MinNotFullBlocksRatio;
|
||||
impl Get<Perbill> for MinNotFullBlocksRatio {
|
||||
fn get() -> Perbill {
|
||||
// This means that we tolerate at most 50% of misbehaving collators.
|
||||
Perbill::from_percent(50)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MaxSlashableProvidersPerTick;
|
||||
impl Get<u32> for MaxSlashableProvidersPerTick {
|
||||
fn get() -> u32 {
|
||||
// With the maximum number of slashable providers per tick being `N`, the absolute maximum
|
||||
// weight that the `on_poll` hook can have, with the current benchmarking, is:
|
||||
//
|
||||
// TODO: UPDATE THIS WITH THE FINAL BENCHMARKING
|
||||
// new_challenges_round_weight: {
|
||||
// ref_time: 576,000,000 + N * 551,601,146
|
||||
// proof_size: 8,523 + N * 3,158
|
||||
// }
|
||||
// new_checkpoint_challenge_round_max_weight: {
|
||||
// ref_time: 587,205,208 + ChallengesQueueLength * 225,083 = 610,554,678
|
||||
// proof_size: 4,787
|
||||
// }
|
||||
// check_spamming_condition_weight: {
|
||||
// ref_time: 313,000,000
|
||||
// proof_size: 6,012
|
||||
// }
|
||||
//
|
||||
// For `N` = 1000, this would be:
|
||||
// max_on_poll_weight: {
|
||||
// ref_time: 313,000,000 + 610,554,678 + 576,000,000 + N * 551,601,146 ≈ 553,100,700,678
|
||||
// proof_size: 6,012 + 4,787 + 8,523 + N * 3,158 ≈ 3,177,322
|
||||
// }
|
||||
//
|
||||
// Consider that the maximum block weight is:
|
||||
// maxBlock: {
|
||||
// ref_time: 2,000,000,000,000
|
||||
// proof_size: 5,242,880
|
||||
// }
|
||||
//
|
||||
// This `on_poll` hook would consume roughly 1/4 of the block `ref_time` and 3/5 of the block `proof_size`.
|
||||
// This is naturally a lot. But it would be a very unlikely scenario.
|
||||
//
|
||||
// This would be the case where all `N` Providers have synchronised their challenge periods
|
||||
// and have the same deadline, plus, all of them missed their proof submissions.
|
||||
// The normal scenario would be that NONE (or just a small number) of the Providers have
|
||||
// missed their proof submissions.
|
||||
let max_slashable_providers_per_tick = 1000;
|
||||
max_slashable_providers_per_tick
|
||||
}
|
||||
}
|
||||
/****** ****** ****** ******/
|
||||
|
||||
/****** File System pallet ******/
|
||||
type ThresholdType = u32;
|
||||
pub type ReplicationTargetType = u32;
|
||||
|
||||
parameter_types! {
|
||||
pub const BaseStorageRequestCreationDeposit: Balance = 1 * UNIT;
|
||||
pub const FileDeletionRequestCreationDeposit: Balance = 1 * UNIT;
|
||||
pub const FileSystemStorageRequestCreationHoldReason: RuntimeHoldReason = RuntimeHoldReason::FileSystem(pallet_file_system::HoldReason::StorageRequestCreationHold);
|
||||
pub const FileSystemFileDeletionRequestHoldReason: RuntimeHoldReason = RuntimeHoldReason::FileSystem(pallet_file_system::HoldReason::FileDeletionRequestHold);
|
||||
}
|
||||
|
||||
impl pallet_file_system::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = pallet_file_system::weights::SubstrateWeight<Runtime>;
|
||||
type Providers = Providers;
|
||||
type ProofDealer = ProofsDealer;
|
||||
type PaymentStreams = PaymentStreams;
|
||||
// TODO: Replace the mocked CR randomness with the actual one when it's ready
|
||||
// type CrRandomness = CrRandomness;
|
||||
type CrRandomness = MockCrRandomness;
|
||||
type UpdateStoragePrice = MostlyStablePriceIndexUpdater<Runtime>;
|
||||
type UserSolvency = PaymentStreams;
|
||||
type Fingerprint = Hash;
|
||||
type ReplicationTargetType = ReplicationTargetType;
|
||||
type ThresholdType = ThresholdType;
|
||||
type ThresholdTypeToTickNumber = ThresholdTypeToBlockNumberConverter;
|
||||
type HashToThresholdType = HashToThresholdTypeConverter;
|
||||
type MerkleHashToRandomnessOutput = MerkleHashToRandomnessOutputConverter;
|
||||
type ChunkIdToMerkleHash = ChunkIdToMerkleHashConverter;
|
||||
type Currency = Balances;
|
||||
type RuntimeHoldReason = RuntimeHoldReason;
|
||||
type Nfts = Nfts;
|
||||
type CollectionInspector = BucketNfts;
|
||||
type BspStopStoringFilePenalty = runtime_config::BspStopStoringFilePenalty;
|
||||
type TreasuryAccount = TreasuryAccount;
|
||||
type MaxBatchConfirmStorageRequests = ConstU32<10>;
|
||||
type MaxFilePathSize = ConstU32<512u32>;
|
||||
type MaxPeerIdSize = ConstU32<100>;
|
||||
type MaxNumberOfPeerIds = ConstU32<5>;
|
||||
type MaxDataServerMultiAddresses = ConstU32<10>;
|
||||
type MaxExpiredItemsInTick = ConstU32<100>;
|
||||
type StorageRequestTtl = runtime_config::StorageRequestTtl;
|
||||
type MoveBucketRequestTtl = ConstU32<40u32>;
|
||||
type MaxUserPendingDeletionRequests = ConstU32<10u32>;
|
||||
type MaxUserPendingMoveBucketRequests = ConstU32<10u32>;
|
||||
type MinWaitForStopStoring = runtime_config::MinWaitForStopStoring;
|
||||
type BaseStorageRequestCreationDeposit = BaseStorageRequestCreationDeposit;
|
||||
type UpfrontTicksToPay = runtime_config::UpfrontTicksToPay;
|
||||
type WeightToFee = WeightToFee;
|
||||
type ReplicationTargetToBalance = ReplicationTargetToBalance;
|
||||
type TickNumberToBalance = TickNumberToBalance;
|
||||
type StorageDataUnitToBalance = StorageDataUnitToBalance;
|
||||
type FileDeletionRequestDeposit = FileDeletionRequestCreationDeposit;
|
||||
type BasicReplicationTarget = runtime_config::BasicReplicationTarget;
|
||||
type StandardReplicationTarget = runtime_config::StandardReplicationTarget;
|
||||
type HighSecurityReplicationTarget = runtime_config::HighSecurityReplicationTarget;
|
||||
type SuperHighSecurityReplicationTarget = runtime_config::SuperHighSecurityReplicationTarget;
|
||||
type UltraHighSecurityReplicationTarget = runtime_config::UltraHighSecurityReplicationTarget;
|
||||
type MaxReplicationTarget = runtime_config::MaxReplicationTarget;
|
||||
type TickRangeToMaximumThreshold = runtime_config::TickRangeToMaximumThreshold;
|
||||
}
|
||||
|
||||
impl MostlyStablePriceIndexUpdaterConfig for Runtime {
|
||||
type Price = Balance;
|
||||
type StorageDataUnit = StorageDataUnit;
|
||||
type LowerThreshold = runtime_config::SystemUtilisationLowerThresholdPercentage;
|
||||
type UpperThreshold = runtime_config::SystemUtilisationUpperThresholdPercentage;
|
||||
type MostlyStablePrice = runtime_config::MostlyStablePrice;
|
||||
type MaxPrice = runtime_config::MaxPrice;
|
||||
type MinPrice = runtime_config::MinPrice;
|
||||
type UpperExponentFactor = runtime_config::UpperExponentFactor;
|
||||
type LowerExponentFactor = runtime_config::LowerExponentFactor;
|
||||
}
|
||||
|
||||
// Converter from the ThresholdType to the BlockNumber type and vice versa.
|
||||
// It performs a saturated conversion, so that the result is always a valid BlockNumber.
|
||||
pub struct ThresholdTypeToBlockNumberConverter;
|
||||
impl Convert<ThresholdType, BlockNumberFor<Runtime>> for ThresholdTypeToBlockNumberConverter {
|
||||
fn convert(threshold: ThresholdType) -> BlockNumberFor<Runtime> {
|
||||
threshold.saturated_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl ConvertBack<ThresholdType, BlockNumberFor<Runtime>> for ThresholdTypeToBlockNumberConverter {
|
||||
fn convert_back(block_number: BlockNumberFor<Runtime>) -> ThresholdType {
|
||||
block_number.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Converter from the [`Hash`] type to the [`ThresholdType`].
|
||||
pub struct HashToThresholdTypeConverter;
|
||||
impl Convert<<Runtime as frame_system::Config>::Hash, ThresholdType>
|
||||
for HashToThresholdTypeConverter
|
||||
{
|
||||
fn convert(hash: <Runtime as frame_system::Config>::Hash) -> ThresholdType {
|
||||
// Get the hash as bytes
|
||||
let hash_bytes = hash.as_ref();
|
||||
|
||||
// Get the 4 least significant bytes of the hash and interpret them as an u32
|
||||
let truncated_hash_bytes: [u8; 4] =
|
||||
hash_bytes[28..].try_into().expect("Hash is 32 bytes; qed");
|
||||
|
||||
ThresholdType::from_be_bytes(truncated_hash_bytes)
|
||||
}
|
||||
}
|
||||
|
||||
// Converter from the MerkleHash (H256) type to the RandomnessOutput (H256) type.
|
||||
pub struct MerkleHashToRandomnessOutputConverter;
|
||||
impl Convert<H256, H256> for MerkleHashToRandomnessOutputConverter {
|
||||
fn convert(hash: H256) -> H256 {
|
||||
hash
|
||||
}
|
||||
}
|
||||
|
||||
// Converter from the ChunkId type to the MerkleHash (H256) type.
|
||||
pub struct ChunkIdToMerkleHashConverter;
|
||||
|
||||
impl Convert<ChunkId, H256> for ChunkIdToMerkleHashConverter {
|
||||
fn convert(chunk_id: ChunkId) -> H256 {
|
||||
let chunk_id_biguint = BigUint::from(chunk_id.as_u64());
|
||||
let mut bytes = chunk_id_biguint.to_bytes_be();
|
||||
|
||||
// Ensure the byte slice is exactly 32 bytes long by padding with leading zeros
|
||||
if bytes.len() < 32 {
|
||||
let mut padded_bytes = vec![0u8; 32 - bytes.len()];
|
||||
padded_bytes.extend(bytes);
|
||||
bytes = padded_bytes;
|
||||
}
|
||||
|
||||
H256::from_slice(&bytes)
|
||||
}
|
||||
}
|
||||
|
||||
// Converter from the ReplicationTargetType type to the Balance type.
|
||||
pub struct ReplicationTargetToBalance;
|
||||
impl Convert<ReplicationTargetType, Balance> for ReplicationTargetToBalance {
|
||||
fn convert(replication_target: ReplicationTargetType) -> Balance {
|
||||
replication_target.into()
|
||||
}
|
||||
}
|
||||
|
||||
// Converter from the TickNumber type to the Balance type.
|
||||
pub type TickNumber = BlockNumber;
|
||||
pub struct TickNumberToBalance;
|
||||
impl Convert<TickNumber, Balance> for TickNumberToBalance {
|
||||
fn convert(tick_number: TickNumber) -> Balance {
|
||||
tick_number.into()
|
||||
}
|
||||
}
|
||||
|
||||
// Converter from the StorageDataUnit type to the Balance type.
|
||||
pub struct StorageDataUnitToBalance;
|
||||
impl Convert<StorageDataUnit, Balance> for StorageDataUnitToBalance {
|
||||
fn convert(storage_data_unit: StorageDataUnit) -> Balance {
|
||||
storage_data_unit.into()
|
||||
}
|
||||
}
|
||||
/****** ****** ****** ******/
|
||||
|
||||
/****** Bucket NFTs pallet ******/
|
||||
impl pallet_bucket_nfts::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = pallet_bucket_nfts::weights::SubstrateWeight<Runtime>;
|
||||
type Buckets = Providers;
|
||||
}
|
||||
/****** ****** ****** ******/
|
||||
|
||||
/****** Commit-Reveal Randomness pallet ******/
|
||||
pub struct MockCrRandomness;
|
||||
impl shp_traits::CommitRevealRandomnessInterface for MockCrRandomness {
|
||||
type ProviderId = Hash;
|
||||
|
||||
fn initialise_randomness_cycle(
|
||||
_who: &Self::ProviderId,
|
||||
) -> frame_support::dispatch::DispatchResult {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn stop_randomness_cycle(_who: &Self::ProviderId) -> frame_support::dispatch::DispatchResult {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
/****** ****** ****** ******/
|
||||
|
|
@ -47,6 +47,14 @@ use sp_version::NativeVersion;
|
|||
use sp_version::RuntimeVersion;
|
||||
use xcm::VersionedLocation;
|
||||
|
||||
// Need by storage hub
|
||||
use frame_support::weights::{
|
||||
constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients,
|
||||
WeightToFeePolynomial,
|
||||
};
|
||||
use smallvec::smallvec;
|
||||
use sp_runtime::Perbill;
|
||||
|
||||
pub use datahaven_runtime_common::{
|
||||
time::EpochDurationInBlocks, AccountId, Address, Balance, BlockNumber, Hash, Header, Nonce,
|
||||
Signature,
|
||||
|
|
@ -132,8 +140,11 @@ pub const SUPPLY_FACTOR: Balance = 1;
|
|||
|
||||
// Unit = the base number of indivisible units for balances
|
||||
pub const UNIT: Balance = 1_000_000_000_000;
|
||||
pub const CENTS: Balance = UNIT / 100;
|
||||
pub const MILLI_UNIT: Balance = 1_000_000_000;
|
||||
pub const MICRO_UNIT: Balance = 1_000_000;
|
||||
pub const NANO_UNIT: Balance = 1_000;
|
||||
pub const PICO_UNIT: Balance = 1;
|
||||
|
||||
pub const STORAGE_BYTE_FEE: Balance = 100 * MICRO_UNIT * SUPPLY_FACTOR;
|
||||
|
||||
|
|
@ -212,8 +223,36 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Handles converting a weight scalar to a fee value, based on the scale and granularity of the
|
||||
/// node's balance type.
|
||||
///
|
||||
/// This should typically create a mapping between the following ranges:
|
||||
/// - `[0, MAXIMUM_BLOCK_WEIGHT]`
|
||||
/// - `[Balance::min, Balance::max]`
|
||||
///
|
||||
/// Yet, it can be used for any other sort of change to weight-fee. Some examples being:
|
||||
/// - Setting it to `0` will essentially disable the weight fee.
|
||||
/// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged.
|
||||
pub struct WeightToFee;
|
||||
impl WeightToFeePolynomial for WeightToFee {
|
||||
type Balance = Balance;
|
||||
fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
|
||||
// in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT:
|
||||
// in our template, we map to 1/10 of that, or 1/10 MILLIUNIT
|
||||
let p = MILLI_UNIT / 10;
|
||||
let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time());
|
||||
smallvec![WeightToFeeCoefficient {
|
||||
degree: 1,
|
||||
negative: false,
|
||||
coeff_frac: Perbill::from_rational(p % q, q),
|
||||
coeff_integer: p / q,
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
// Create the runtime by composing the FRAME pallets that were previously configured.
|
||||
#[frame_support::runtime]
|
||||
#[cfg(not(feature = "storage-hub"))]
|
||||
mod runtime {
|
||||
#[runtime::runtime]
|
||||
#[runtime::derive(
|
||||
|
|
@ -346,6 +385,193 @@ mod runtime {
|
|||
|
||||
// ╔══════════════════════ StorageHub Pallets ═══════════════════════╗
|
||||
// Start with index 80
|
||||
// #[runtime::pallet_index(80)]
|
||||
// pub type Providers = pallet_storage_providers;
|
||||
|
||||
// #[runtime::pallet_index(81)]
|
||||
// pub type FileSystem = pallet_file_system;
|
||||
|
||||
// #[runtime::pallet_index(82)]
|
||||
// pub type ProofsDealer = pallet_proofs_dealer;
|
||||
|
||||
// #[runtime::pallet_index(83)]
|
||||
// pub type Randomness = pallet_randomness;
|
||||
|
||||
// #[runtime::pallet_index(84)]
|
||||
// pub type PaymentStreams = pallet_payment_streams;
|
||||
|
||||
// #[runtime::pallet_index(85)]
|
||||
// pub type BucketNfts = pallet_bucket_nfts;
|
||||
|
||||
// #[runtime::pallet_index(90)]
|
||||
// pub type Nfts = pallet_nfts;
|
||||
// ╚══════════════════════ StorageHub Pallets ═══════════════════════╝
|
||||
|
||||
// ╔═══════════════════ DataHaven-specific Pallets ══════════════════╗
|
||||
// Start with index 100
|
||||
#[runtime::pallet_index(100)]
|
||||
pub type OutboundCommitmentStore = pallet_outbound_commitment_store;
|
||||
|
||||
#[runtime::pallet_index(101)]
|
||||
pub type ExternalValidatorsRewards = pallet_external_validators_rewards;
|
||||
|
||||
#[runtime::pallet_index(102)]
|
||||
pub type DataHavenNativeTransfer = pallet_datahaven_native_transfer;
|
||||
// ╚═══════════════════ DataHaven-specific Pallets ══════════════════╝
|
||||
}
|
||||
|
||||
// Create the runtime by composing the FRAME pallets that were previously configured.
|
||||
#[frame_support::runtime]
|
||||
#[cfg(feature = "storage-hub")]
|
||||
mod runtime {
|
||||
#[runtime::runtime]
|
||||
#[runtime::derive(
|
||||
RuntimeCall,
|
||||
RuntimeEvent,
|
||||
RuntimeError,
|
||||
RuntimeOrigin,
|
||||
RuntimeFreezeReason,
|
||||
RuntimeHoldReason,
|
||||
RuntimeSlashReason,
|
||||
RuntimeLockId,
|
||||
RuntimeTask
|
||||
)]
|
||||
pub struct Runtime;
|
||||
|
||||
// ╔══════════════════ System and Consensus Pallets ═════════════════╗
|
||||
#[runtime::pallet_index(0)]
|
||||
pub type System = frame_system;
|
||||
|
||||
// Babe must be before session.
|
||||
#[runtime::pallet_index(1)]
|
||||
pub type Babe = pallet_babe;
|
||||
|
||||
#[runtime::pallet_index(2)]
|
||||
pub type Timestamp = pallet_timestamp;
|
||||
|
||||
#[runtime::pallet_index(3)]
|
||||
pub type Balances = pallet_balances;
|
||||
|
||||
// Consensus support.
|
||||
// Authorship must be before session in order to note author in the correct session and era.
|
||||
#[runtime::pallet_index(4)]
|
||||
pub type Authorship = pallet_authorship;
|
||||
|
||||
#[runtime::pallet_index(5)]
|
||||
pub type Offences = pallet_offences;
|
||||
|
||||
#[runtime::pallet_index(6)]
|
||||
pub type Historical = pallet_session::historical;
|
||||
|
||||
// External Validators must be before Session.
|
||||
#[runtime::pallet_index(7)]
|
||||
pub type ExternalValidators = pallet_external_validators;
|
||||
|
||||
#[runtime::pallet_index(8)]
|
||||
pub type Session = pallet_session;
|
||||
|
||||
#[runtime::pallet_index(9)]
|
||||
pub type ImOnline = pallet_im_online;
|
||||
|
||||
#[runtime::pallet_index(10)]
|
||||
pub type Grandpa = pallet_grandpa;
|
||||
|
||||
#[runtime::pallet_index(11)]
|
||||
pub type TransactionPayment = pallet_transaction_payment;
|
||||
|
||||
#[runtime::pallet_index(12)]
|
||||
pub type Beefy = pallet_beefy;
|
||||
|
||||
#[runtime::pallet_index(13)]
|
||||
pub type Mmr = pallet_mmr;
|
||||
|
||||
#[runtime::pallet_index(14)]
|
||||
pub type BeefyMmrLeaf = pallet_beefy_mmr;
|
||||
// ╚═════════════════ System and Consensus Pallets ══════════════════╝
|
||||
|
||||
// ╔═════════════════ Polkadot SDK Utility Pallets ══════════════════╗
|
||||
#[runtime::pallet_index(30)]
|
||||
pub type Utility = pallet_utility;
|
||||
|
||||
#[runtime::pallet_index(31)]
|
||||
pub type Scheduler = pallet_scheduler;
|
||||
|
||||
#[runtime::pallet_index(32)]
|
||||
pub type Preimage = pallet_preimage;
|
||||
|
||||
#[runtime::pallet_index(33)]
|
||||
pub type Identity = pallet_identity;
|
||||
|
||||
#[runtime::pallet_index(34)]
|
||||
pub type Multisig = pallet_multisig;
|
||||
|
||||
#[runtime::pallet_index(35)]
|
||||
pub type Parameters = pallet_parameters;
|
||||
|
||||
#[runtime::pallet_index(36)]
|
||||
pub type Sudo = pallet_sudo;
|
||||
// ╚═════════════════ Polkadot SDK Utility Pallets ══════════════════╝
|
||||
|
||||
// ╔════════════════════ Frontier (EVM) Pallets ═════════════════════╗
|
||||
#[runtime::pallet_index(50)]
|
||||
pub type Ethereum = pallet_ethereum;
|
||||
|
||||
#[runtime::pallet_index(51)]
|
||||
pub type Evm = pallet_evm;
|
||||
|
||||
#[runtime::pallet_index(52)]
|
||||
pub type EvmChainId = pallet_evm_chain_id;
|
||||
// ╚════════════════════ Frontier (EVM) Pallets ═════════════════════╝
|
||||
|
||||
// ╔══════════════════════ Snowbridge Pallets ═══════════════════════╗
|
||||
#[runtime::pallet_index(60)]
|
||||
pub type EthereumBeaconClient = snowbridge_pallet_ethereum_client;
|
||||
|
||||
#[runtime::pallet_index(61)]
|
||||
pub type EthereumInboundQueueV2 = snowbridge_pallet_inbound_queue_v2;
|
||||
|
||||
#[runtime::pallet_index(62)]
|
||||
pub type EthereumOutboundQueueV2 = snowbridge_pallet_outbound_queue_v2;
|
||||
|
||||
#[runtime::pallet_index(63)]
|
||||
pub type SnowbridgeSystem = snowbridge_pallet_system;
|
||||
|
||||
#[runtime::pallet_index(64)]
|
||||
pub type SnowbridgeSystemV2 = snowbridge_pallet_system_v2;
|
||||
// ╚══════════════════════ Snowbridge Pallets ═══════════════════════╝
|
||||
|
||||
// ╔════════════ Polkadot SDK Utility Pallets - Block 2 ═════════════╗
|
||||
// The Message Queue pallet has to be after the Snowbridge Outbound
|
||||
// Queue V2 pallet since the former processes messages in its
|
||||
// `on_initialize` hook and the latter clears up messages in
|
||||
// its `on_initialize` hook, so otherwise messages will be cleared
|
||||
// up before they are processed.
|
||||
#[runtime::pallet_index(70)]
|
||||
pub type MessageQueue = pallet_message_queue;
|
||||
// ╚════════════ Polkadot SDK Utility Pallets - Block 2 ═════════════╝
|
||||
|
||||
// ╔══════════════════════ StorageHub Pallets ═══════════════════════╗
|
||||
// Start with index 80
|
||||
#[runtime::pallet_index(80)]
|
||||
pub type Providers = pallet_storage_providers;
|
||||
|
||||
#[runtime::pallet_index(81)]
|
||||
pub type FileSystem = pallet_file_system;
|
||||
|
||||
#[runtime::pallet_index(82)]
|
||||
pub type ProofsDealer = pallet_proofs_dealer;
|
||||
|
||||
#[runtime::pallet_index(83)]
|
||||
pub type Randomness = pallet_randomness;
|
||||
|
||||
#[runtime::pallet_index(84)]
|
||||
pub type PaymentStreams = pallet_payment_streams;
|
||||
|
||||
#[runtime::pallet_index(85)]
|
||||
pub type BucketNfts = pallet_bucket_nfts;
|
||||
|
||||
#[runtime::pallet_index(90)]
|
||||
pub type Nfts = pallet_nfts;
|
||||
// ╚══════════════════════ StorageHub Pallets ═══════════════════════╝
|
||||
|
||||
// ╔═══════════════════ DataHaven-specific Pallets ══════════════════╗
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ snowbridge-pallet-system-v2 = { workspace = true }
|
|||
snowbridge-outbound-queue-primitives = { workspace = true }
|
||||
|
||||
[features]
|
||||
storage-hub = []
|
||||
default = ["std"]
|
||||
std = [
|
||||
"codec/std",
|
||||
|
|
|
|||
Loading…
Reference in a new issue