From d2bea9278c3f702c1d083fbcad2db13375fa6625 Mon Sep 17 00:00:00 2001 From: Steve Degosserie <723552+stiiifff@users.noreply.github.com> Date: Wed, 3 Sep 2025 10:57:57 +0200 Subject: [PATCH] =?UTF-8?q?chore:=20=E2=99=BB=EF=B8=8F=20=20Remove=20the?= =?UTF-8?q?=20StorageHub=20conditional=20feature=20from=20the=20DataHav?= =?UTF-8?q?=E2=80=A6=20(#146)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …en runtimes (always include SH) --- operator/runtime/mainnet/Cargo.toml | 72 +++----- operator/runtime/mainnet/src/configs/mod.rs | 3 +- .../mainnet/src/configs/runtime_params.rs | 54 +----- .../mainnet/src/configs/storagehub/mod.rs | 1 - operator/runtime/mainnet/src/lib.rs | 154 ---------------- operator/runtime/stagenet/Cargo.toml | 72 +++----- operator/runtime/stagenet/src/configs/mod.rs | 4 +- .../stagenet/src/configs/runtime_params.rs | 54 +----- .../stagenet/src/configs/storagehub/mod.rs | 1 - operator/runtime/stagenet/src/lib.rs | 174 ------------------ operator/runtime/testnet/Cargo.toml | 72 +++----- operator/runtime/testnet/src/configs/mod.rs | 3 +- .../testnet/src/configs/runtime_params.rs | 54 +----- .../testnet/src/configs/storagehub/mod.rs | 1 - operator/runtime/testnet/src/lib.rs | 154 ---------------- test/.papi/descriptors/package.json | 2 +- test/.papi/metadata/datahaven.scale | Bin 419382 -> 592209 bytes 17 files changed, 70 insertions(+), 805 deletions(-) diff --git a/operator/runtime/mainnet/Cargo.toml b/operator/runtime/mainnet/Cargo.toml index 81cb171f..53c2155a 100644 --- a/operator/runtime/mainnet/Cargo.toml +++ b/operator/runtime/mainnet/Cargo.toml @@ -32,7 +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 } +num-bigint = { workspace = true } pallet-authorship = { workspace = true } pallet-babe = { workspace = true } pallet-balances = { workspace = true, features = ["insecure_zero_ed"] } @@ -114,26 +114,26 @@ strum_macros = { 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 } +pallet-bucket-nfts = { workspace = true } +pallet-nfts = { workspace = true } +pallet-cr-randomness = { workspace = true } +pallet-file-system = { workspace = true } +pallet-file-system-runtime-api = { workspace = true } +pallet-payment-streams = { workspace = true } +pallet-payment-streams-runtime-api = { workspace = true } +pallet-proofs-dealer = { workspace = true } +pallet-proofs-dealer-runtime-api = { workspace = true } +pallet-randomness = { workspace = true } +pallet-storage-providers = { workspace = true } +pallet-storage-providers-runtime-api = { workspace = true } +shp-constants = { workspace = true } +shp-file-metadata = { workspace = true } +shp-traits = { workspace = true } +shp-treasury-funding = { workspace = true } +shp-forest-verifier = { workspace = true } +shp-file-key-verifier = { workspace = true } +shp-data-price-updater = { workspace = true } +sp-trie = { workspace = true } [build-dependencies] @@ -152,29 +152,6 @@ 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", @@ -260,8 +237,6 @@ std = [ "pallet-datahaven-native-transfer/std", # StorageHub - "pallet-authorship/std", - "pallet-balances/std", "pallet-bucket-nfts/std", "pallet-nfts/std", "pallet-cr-randomness/std", @@ -272,13 +247,8 @@ 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", diff --git a/operator/runtime/mainnet/src/configs/mod.rs b/operator/runtime/mainnet/src/configs/mod.rs index 843bc9ee..ccd9fe41 100644 --- a/operator/runtime/mainnet/src/configs/mod.rs +++ b/operator/runtime/mainnet/src/configs/mod.rs @@ -22,11 +22,10 @@ // OTHER DEALINGS IN THE SOFTWARE. // // For more information, please refer to -#[cfg(feature = "storage-hub")] -mod storagehub; pub mod governance; pub mod runtime_params; +mod storagehub; use super::{ currency::*, AccountId, Babe, Balance, Balances, BeefyMmrLeaf, Block, BlockNumber, diff --git a/operator/runtime/mainnet/src/configs/runtime_params.rs b/operator/runtime/mainnet/src/configs/runtime_params.rs index 48e197ab..73cdda79 100644 --- a/operator/runtime/mainnet/src/configs/runtime_params.rs +++ b/operator/runtime/mainnet/src/configs/runtime_params.rs @@ -5,62 +5,10 @@ use sp_core::{ConstU32, H160, H256}; use sp_runtime::{BoundedVec, Perbill}; use sp_std::vec; -#[cfg(feature = "storage-hub")] -use crate::currency::{GIGAWEI, HAVE}; - -#[cfg(feature = "storage-hub")] use crate::configs::storagehub::{ChallengeTicksTolerance, ReplicationTargetType, SpMinDeposit}; - -#[cfg(feature = "storage-hub")] +use crate::currency::{GIGAWEI, HAVE}; use datahaven_runtime_common::{Balance, BlockNumber}; -#[cfg(not(feature = "storage-hub"))] -#[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::)] -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> = - 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" - )); - - // Proportion of fees allocated to the Treasury (remainder are burned). - // e.g. 20% to the treasury, 80% burned. - #[codec(index = 4)] - #[allow(non_upper_case_globals)] - pub static FeesTreasuryProportion: Perbill = Perbill::from_percent(20); - } -} - -#[cfg(feature = "storage-hub")] #[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::)] pub mod dynamic_params { use super::*; diff --git a/operator/runtime/mainnet/src/configs/storagehub/mod.rs b/operator/runtime/mainnet/src/configs/storagehub/mod.rs index 636393e8..96061b2c 100644 --- a/operator/runtime/mainnet/src/configs/storagehub/mod.rs +++ b/operator/runtime/mainnet/src/configs/storagehub/mod.rs @@ -16,7 +16,6 @@ use frame_support::{ weights::Weight, }; use frame_system::pallet_prelude::BlockNumberFor; -use frame_system::EnsureRoot; use frame_system::EnsureSigned; use num_bigint::BigUint; use pallet_nfts::PalletFeatures; diff --git a/operator/runtime/mainnet/src/lib.rs b/operator/runtime/mainnet/src/lib.rs index 5525cebe..4fb5487d 100644 --- a/operator/runtime/mainnet/src/lib.rs +++ b/operator/runtime/mainnet/src/lib.rs @@ -266,7 +266,6 @@ impl WeightToFeePolynomial for WeightToFee { // 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( @@ -420,159 +419,6 @@ mod runtime { pub type MessageQueue = pallet_message_queue; // ╚════════════ Polkadot SDK Utility Pallets - Block 2 ═════════════╝ - // ╔══════════════════════ StorageHub Pallets ═══════════════════════╗ - // Start with index 80 - // ╚══════════════════════ 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 ══════════════════╝ -} - -#[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; - - #[runtime::pallet_index(37)] - pub type Treasury = pallet_treasury; - - #[runtime::pallet_index(38)] - pub type Proxy = pallet_proxy; - // ╚═════════════════ 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)] diff --git a/operator/runtime/stagenet/Cargo.toml b/operator/runtime/stagenet/Cargo.toml index 6a220a34..6e67bf85 100644 --- a/operator/runtime/stagenet/Cargo.toml +++ b/operator/runtime/stagenet/Cargo.toml @@ -32,7 +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 } +num-bigint = { workspace = true } pallet-authorship = { workspace = true } pallet-babe = { workspace = true } pallet-balances = { workspace = true, features = ["insecure_zero_ed"]} @@ -113,26 +113,26 @@ 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 } +pallet-bucket-nfts = { workspace = true } +pallet-nfts = { workspace = true } +pallet-cr-randomness = { workspace = true } +pallet-file-system = { workspace = true } +pallet-file-system-runtime-api = { workspace = true } +pallet-payment-streams = { workspace = true } +pallet-payment-streams-runtime-api = { workspace = true } +pallet-proofs-dealer = { workspace = true } +pallet-proofs-dealer-runtime-api = { workspace = true } +pallet-randomness = { workspace = true } +pallet-storage-providers = { workspace = true } +pallet-storage-providers-runtime-api = { workspace = true } +shp-constants = { workspace = true } +shp-file-metadata = { workspace = true } +shp-traits = { workspace = true } +shp-treasury-funding = { workspace = true } +shp-forest-verifier = { workspace = true } +shp-file-key-verifier = { workspace = true } +shp-data-price-updater = { workspace = true } +sp-trie = { workspace = true } [build-dependencies] substrate-wasm-builder = { workspace = true, optional = true, default-features = true } @@ -150,29 +150,6 @@ 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", @@ -258,8 +235,6 @@ std = [ "pallet-datahaven-native-transfer/std", # StorageHub - "pallet-authorship/std", - "pallet-balances/std", "pallet-bucket-nfts/std", "pallet-nfts/std", "pallet-cr-randomness/std", @@ -270,13 +245,8 @@ 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", diff --git a/operator/runtime/stagenet/src/configs/mod.rs b/operator/runtime/stagenet/src/configs/mod.rs index d1efe148..75c12b82 100644 --- a/operator/runtime/stagenet/src/configs/mod.rs +++ b/operator/runtime/stagenet/src/configs/mod.rs @@ -23,11 +23,9 @@ // // For more information, please refer to -#[cfg(feature = "storage-hub")] -mod storagehub; - pub mod governance; pub mod runtime_params; +mod storagehub; use super::{ currency::*, AccountId, Babe, Balance, Balances, BeefyMmrLeaf, Block, BlockNumber, diff --git a/operator/runtime/stagenet/src/configs/runtime_params.rs b/operator/runtime/stagenet/src/configs/runtime_params.rs index 93808918..8623fb77 100644 --- a/operator/runtime/stagenet/src/configs/runtime_params.rs +++ b/operator/runtime/stagenet/src/configs/runtime_params.rs @@ -5,16 +5,10 @@ use sp_core::{ConstU32, H160, H256}; use sp_runtime::{BoundedVec, Perbill}; use sp_std::vec; -#[cfg(feature = "storage-hub")] -use crate::currency::{GIGAWEI, HAVE}; - -#[cfg(feature = "storage-hub")] use crate::configs::storagehub::{ChallengeTicksTolerance, ReplicationTargetType, SpMinDeposit}; - -#[cfg(feature = "storage-hub")] +use crate::currency::{GIGAWEI, HAVE}; use datahaven_runtime_common::{Balance, BlockNumber}; -#[cfg(not(feature = "storage-hub"))] #[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::)] pub mod dynamic_params { use super::*; @@ -61,52 +55,6 @@ pub mod dynamic_params { #[codec(index = 4)] #[allow(non_upper_case_globals)] pub static FeesTreasuryProportion: Perbill = Perbill::from_percent(20); - } -} - -#[cfg(feature = "storage-hub")] -#[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::)] -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> = - 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" - )); - - // Proportion of fees allocated to the Treasury (remainder are burned). - // e.g. 20% to the treasury, 80% burned. - #[codec(index = 4)] - #[allow(non_upper_case_globals)] - pub static FeesTreasuryProportion: Perbill = Perbill::from_percent(20); // ╔══════════════════════ StorageHub Pallets ═══════════════════════╗ diff --git a/operator/runtime/stagenet/src/configs/storagehub/mod.rs b/operator/runtime/stagenet/src/configs/storagehub/mod.rs index 636393e8..96061b2c 100644 --- a/operator/runtime/stagenet/src/configs/storagehub/mod.rs +++ b/operator/runtime/stagenet/src/configs/storagehub/mod.rs @@ -16,7 +16,6 @@ use frame_support::{ weights::Weight, }; use frame_system::pallet_prelude::BlockNumberFor; -use frame_system::EnsureRoot; use frame_system::EnsureSigned; use num_bigint::BigUint; use pallet_nfts::PalletFeatures; diff --git a/operator/runtime/stagenet/src/lib.rs b/operator/runtime/stagenet/src/lib.rs index f57f8592..6860c626 100644 --- a/operator/runtime/stagenet/src/lib.rs +++ b/operator/runtime/stagenet/src/lib.rs @@ -268,7 +268,6 @@ impl WeightToFeePolynomial for WeightToFee { // 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( @@ -422,179 +421,6 @@ mod runtime { 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 ══════════════════╗ - // 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; - - #[runtime::pallet_index(37)] - pub type Treasury = pallet_treasury; - - #[runtime::pallet_index(38)] - pub type Proxy = pallet_proxy; - // ╚═════════════════ 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)] diff --git a/operator/runtime/testnet/Cargo.toml b/operator/runtime/testnet/Cargo.toml index ea39ef21..7040c7fe 100644 --- a/operator/runtime/testnet/Cargo.toml +++ b/operator/runtime/testnet/Cargo.toml @@ -32,7 +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 } +num-bigint = { workspace = true } pallet-authorship = { workspace = true } pallet-babe = { workspace = true } pallet-balances = { workspace = true, features = ["insecure_zero_ed"] } @@ -113,26 +113,26 @@ strum = { workspace = true } strum_macros = { 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 } +pallet-bucket-nfts = { workspace = true } +pallet-nfts = { workspace = true } +pallet-cr-randomness = { workspace = true } +pallet-file-system = { workspace = true } +pallet-file-system-runtime-api = { workspace = true } +pallet-payment-streams = { workspace = true } +pallet-payment-streams-runtime-api = { workspace = true } +pallet-proofs-dealer = { workspace = true } +pallet-proofs-dealer-runtime-api = { workspace = true } +pallet-randomness = { workspace = true } +pallet-storage-providers = { workspace = true } +pallet-storage-providers-runtime-api = { workspace = true } +shp-constants = { workspace = true } +shp-file-metadata = { workspace = true } +shp-traits = { workspace = true } +shp-treasury-funding = { workspace = true } +shp-forest-verifier = { workspace = true } +shp-file-key-verifier = { workspace = true } +shp-data-price-updater = { workspace = true } +sp-trie = { workspace = true } [build-dependencies] substrate-wasm-builder = { workspace = true, optional = true, default-features = true } @@ -150,29 +150,6 @@ snowbridge-pallet-system = { workspace = true } snowbridge-pallet-system-v2 = { 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", @@ -258,8 +235,6 @@ std = [ "pallet-datahaven-native-transfer/std", # StorageHub - "pallet-authorship/std", - "pallet-balances/std", "pallet-bucket-nfts/std", "pallet-nfts/std", "pallet-cr-randomness/std", @@ -270,13 +245,8 @@ 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", diff --git a/operator/runtime/testnet/src/configs/mod.rs b/operator/runtime/testnet/src/configs/mod.rs index a899710b..38a52284 100644 --- a/operator/runtime/testnet/src/configs/mod.rs +++ b/operator/runtime/testnet/src/configs/mod.rs @@ -22,11 +22,10 @@ // OTHER DEALINGS IN THE SOFTWARE. // // For more information, please refer to -#[cfg(feature = "storage-hub")] -mod storagehub; pub mod governance; pub mod runtime_params; +mod storagehub; use super::{ currency::*, AccountId, Babe, Balance, Balances, BeefyMmrLeaf, Block, BlockNumber, diff --git a/operator/runtime/testnet/src/configs/runtime_params.rs b/operator/runtime/testnet/src/configs/runtime_params.rs index 9cb3c457..ac0c23b8 100644 --- a/operator/runtime/testnet/src/configs/runtime_params.rs +++ b/operator/runtime/testnet/src/configs/runtime_params.rs @@ -6,62 +6,10 @@ use sp_std::vec; use crate::Runtime; -#[cfg(feature = "storage-hub")] -use crate::currency::{GIGAWEI, HAVE}; - -#[cfg(feature = "storage-hub")] use crate::configs::storagehub::{ChallengeTicksTolerance, ReplicationTargetType, SpMinDeposit}; - -#[cfg(feature = "storage-hub")] +use crate::currency::{GIGAWEI, HAVE}; use datahaven_runtime_common::{Balance, BlockNumber}; -#[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::)] -#[cfg(not(feature = "storage-hub"))] -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> = - 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" - )); - - // Proportion of fees allocated to the Treasury (remainder are burned). - // e.g. 20% to the treasury, 80% burned. - #[codec(index = 4)] - #[allow(non_upper_case_globals)] - pub static FeesTreasuryProportion: Perbill = Perbill::from_percent(20); - } -} - -#[cfg(feature = "storage-hub")] #[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::)] pub mod dynamic_params { use super::*; diff --git a/operator/runtime/testnet/src/configs/storagehub/mod.rs b/operator/runtime/testnet/src/configs/storagehub/mod.rs index 636393e8..96061b2c 100644 --- a/operator/runtime/testnet/src/configs/storagehub/mod.rs +++ b/operator/runtime/testnet/src/configs/storagehub/mod.rs @@ -16,7 +16,6 @@ use frame_support::{ weights::Weight, }; use frame_system::pallet_prelude::BlockNumberFor; -use frame_system::EnsureRoot; use frame_system::EnsureSigned; use num_bigint::BigUint; use pallet_nfts::PalletFeatures; diff --git a/operator/runtime/testnet/src/lib.rs b/operator/runtime/testnet/src/lib.rs index 1613a0d6..b8d25d5b 100644 --- a/operator/runtime/testnet/src/lib.rs +++ b/operator/runtime/testnet/src/lib.rs @@ -265,7 +265,6 @@ impl WeightToFeePolynomial for WeightToFee { // 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( @@ -419,159 +418,6 @@ mod runtime { pub type MessageQueue = pallet_message_queue; // ╚════════════ Polkadot SDK Utility Pallets - Block 2 ═════════════╝ - // ╔══════════════════════ StorageHub Pallets ═══════════════════════╗ - // Start with index 80 - // ╚══════════════════════ 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 ══════════════════╝ -} - -#[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; - - #[runtime::pallet_index(37)] - pub type Treasury = pallet_treasury; - - #[runtime::pallet_index(38)] - pub type Proxy = pallet_proxy; - // ╚═════════════════ 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)] diff --git a/test/.papi/descriptors/package.json b/test/.papi/descriptors/package.json index 917b557a..105eab77 100644 --- a/test/.papi/descriptors/package.json +++ b/test/.papi/descriptors/package.json @@ -1,5 +1,5 @@ { - "version": "0.1.0-autogenerated.11221632385899729439", + "version": "0.1.0-autogenerated.11476301422201833224", "name": "@polkadot-api/descriptors", "files": [ "dist" diff --git a/test/.papi/metadata/datahaven.scale b/test/.papi/metadata/datahaven.scale index 5920b3a3e0f112837a0f0c5f92f93afe72cf8544..da66071d897d38202958010af98ab7aca12acc19 100644 GIT binary patch literal 592209 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