// This file is part of The Brain. // Copyright (C) 2022-2024 The Nerve Lab // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #![cfg_attr(not(feature = "std"), no_std)] // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 512. #![recursion_limit = "512"] // Make the WASM binary available. #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); mod filters; pub mod frontier_evm; pub mod impls; pub mod migrations; pub mod precompiles; // pub mod hippius_services; pub mod voter_bags; use sp_core::crypto::Ss58Codec; use sp_runtime::AccountId32; use frame_election_provider_support::{ bounds::{ElectionBounds, ElectionBoundsBuilder}, onchain, BalancingConfig, ElectionDataProvider, SequentialPhragmen, VoteWeight, }; use frame_support::derive_impl; use frame_support::genesis_builder_helper::build_state; use frame_support::genesis_builder_helper::get_preset; use frame_support::traits::{ tokens::{PayFromAccount, UnityAssetBalanceConversion}, AsEnsureOriginWithArg, Contains, OnFinalize, WithdrawReasons, }; use frame_system::EnsureSigned; use pallet_election_provider_multi_phase::{GeometricDepositBase, SolutionAccuracyOf}; use pallet_evm::GasWeightMapping; use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use pallet_session::historical as pallet_session_historical; pub use pallet_staking::StakerStatus; #[allow(deprecated)] use pallet_transaction_payment::{CurrencyAdapter, FeeDetails, Multiplier, RuntimeDispatchInfo}; use scale_info::prelude::string::String; // use pallet_registration::NodeType; use pallet_tx_pause::RuntimeCallNameOf; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use precompiles::HipiusPrecompiles; // use scale_info::TypeInfo; use frame_support::traits::{ConstBool, ConstU32, KeyOwnerProofSystem}; use serde::{Deserialize, Serialize}; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H160, H256, U256}; use sp_genesis_builder::PresetId; use sp_runtime::traits::{AccountIdConversion, ConstU64}; use sp_runtime::SaturatedConversion; use sp_runtime::{ create_runtime_str, // curve::PiecewiseLinear, generic, impl_opaque_keys, traits::{ self, BlakeTwo256, Block as BlockT, Bounded, Convert, ConvertInto, DispatchInfoOf, Dispatchable, IdentityLookup, NumberFor, OpaqueKeys, PostDispatchInfoOf, StaticLookup, UniqueSaturatedInto, }, transaction_validity::{ TransactionPriority, TransactionSource, TransactionValidity, TransactionValidityError, }, ApplyExtrinsicResult, FixedPointNumber, FixedU128, Perquintill, RuntimeDebug, }; use sp_std::{prelude::*, vec::Vec}; // Arion pallet configuration parameter_types! { pub const ArionPalletId: PalletId = PalletId(*b"py/arion"); pub const BaseChildDeposit: Balance = 10 * DOLLAR; pub const GlobalDepositHalvingPeriodBlocks: BlockNumber = 14_400; // ~24 hours at 6s/block pub const UnregisterCooldownBlocks: BlockNumber = 7200; // ~12 hours at 6s/block pub const UnbondingPeriodBlocks: BlockNumber = 100_800; // ~7 days at 6s/block /// Retained CRUSH map + attestation commitment epochs (older keys pruned each `submit_crush_map`). pub const EpochCrushMapRetention: u64 = 100; pub const MaxCrushEpochPrunesPerCall: u32 = 200; /// Cap on `prune_attestation_buckets` batch size (weight + anti-spam). pub const MaxAttestationBucketsPrunePerCall: u32 = 64; /// Cap on `prune_stale_node_weights` batch size (weight bound). pub const MaxNodeWeightPrunePerCall: u32 = 200; /// Cap on `prune_stale_node_weights` scan size (bounds the walk over live entries). pub const MaxNodeWeightScanPerCall: u32 = 2000; /// Families visited per `submit_node_quality` recompute page. Declared weight scales /// with this times `MaxChildrenPerFamily` (35), so 25 keeps a single call's family /// term near 2.6k reads. The submitter issues many calls per bucket (batches are /// capped at `MaxNodeWeightUpdates`), so the cursor still covers the whole family set /// well inside a bucket at realistic sizes. pub const MaxFamilyRecomputePerCall: u32 = 25; /// Periodic [`MinerStatsByUid`] pruning in arion (`0` = disabled). pub const ArionMinerStatsPruneInterval: BlockNumber = 100; /// Max stats uid keys scanned per pruning tick. pub const ArionMinerStatsPruneMaxScanPerBlock: u32 = 128; } pub struct ArionAdminMembers; impl frame_support::traits::SortedMembers for ArionAdminMembers { fn sorted_members() -> Vec { let account = AccountId32::from_ss58check("5CVXqxb7mhFTtZVw5BJ8M2ujND9PFymSDxF8bkod6Sm4XJTW") .expect("Invalid SS58 address"); vec![account] } } /// Adapter: arion pulls miner-payment funds from the bank pallet. /// The arion pallet account must be whitelisted via `bank.add_requester`. pub struct ArionPayoutSource; impl pallet_arion::PayoutSource for ArionPayoutSource { fn request_payment(requester: &AccountId, dest: &AccountId, amount: Balance) -> Balance { match pallet_hippocampus::Pallet::::request_payment(requester, dest, amount) { Ok(paid) => paid, Err(e) => { // A rejection here (e.g. requester not whitelisted — a manual // post-upgrade setup step) must be diagnosable, not silent. log::warn!( target: "runtime::arion", "bank rejected miner payment request from {:?}: {:?}", requester, e ); 0 }, } } fn available() -> Balance { // Compartmentalization: the alpha backing still owed to the ranking / // marketplace pots — and chargeback refunds still owed back to the // sudo account — and the emission compartments reserved for ranking-based // `pay_storage_miners` and weight-based `pay_compute_miners` — is not // spendable by the miner settlement: a runaway // miner due (bad stats, bad price, compromised authority key) can at // worst drain the miner budget, never funds owed to someone else. pallet_hippocampus::Pallet::::available_for_payout() .saturating_sub(pallet_marketplace::TotalUndistributedBacking::::get()) .saturating_sub(pallet_marketplace::PendingSudoRefunds::::get()) .saturating_sub(pallet_hippocampus::Pallet::::emission_available()) .saturating_sub(pallet_hippocampus::Pallet::::compute_emission_available()) } } /// Adapter: `pay_storage_miners` reads the **Arion** pallet — its family/child /// registry and its validator-reported node weights — and pays each family. /// /// NOT `RankingStorage`. The ranking pallet is a separate, storage-node-keyed /// leaderboard that Arion operators do not appear in: paying from it left /// registered Arion families with real weight receiving nothing at all, which /// is the bug this adapter exists to fix. Arion is where a storage miner /// registers, where its deposit is locked, and where its weight is reported, /// so it is also where the payout set comes from. /// /// The payee is the **family** (the operator account that put up the child /// deposits), not a child node account. The family's payout weight is the /// SAME fragmentation-neutral aggregate that feeds `FamilyWeight` — one /// log2 over the family's summed bytes and bandwidth — read raw (no EMA, no /// delta clamp) so payouts track the validator's measurements without /// smoothing lag. Splitting the same data across more children does not /// change a family's share. Eligibility (owned + Active registration + a /// non-stale weight) and the aggregation live in /// `pallet_arion::Pallet::active_family_weights`, which also guarantees the /// bank's "one payee, one entry" contract: `FamilyChildren` is keyed by /// family, so no family can appear twice. pub struct ArionFamilyWeightsSource; impl pallet_hippocampus::StorageMinerWeights for ArionFamilyWeightsSource { fn active_storage_miners() -> Vec<(AccountId, u128)> { // Carried over from the ranking-based adapter: uid 238 is excluded // from emission by operator decision. Kept source-independent — it // now only bites if that account is itself a registered Arion family. let uid_238_account = pallet_metagraph::Pallet::::get_uid_item(238).map(|uid| uid.substrate_address); pallet_arion::Pallet::::active_family_weights() .into_iter() .filter(|(family, _)| Some(family) != uid_238_account.as_ref()) .collect() } } /// Adapter: `pay_compute_miners` reads the compute-scoring pallet's §23 /// reward weights for the most recently closed epoch and pays each node's /// **family** account (the operator that put up the child deposit). /// /// `CurrentEpoch` holds the epoch id of the last `vali_submit_epoch_close` /// (the close writes `EpochWeights[epoch][*]` and then sets `CurrentEpoch = /// epoch`), so it *is* the last closed epoch — not `epoch - 1`. Before the /// first close it is `0` and the weight map is empty, which the bank rejects /// with `NoEligibleComputeMiners`. /// /// TWO status fields are checked, because compute-scoring keeps two and they /// move independently: /// /// * `ChildRegistrations[child].status` (`ChildStatus`) is the *registration* /// lifecycle — `Unbonding`, or a `node_id` that no longer maps to a child, /// means the operator is gone. /// * `MinerStatuses[node_id]` (`MinerStatus`) is the *operational* verdict — /// `Quarantined` / `Decommissioned`. /// /// Filtering on the registration alone is not enough. `request_unstake` /// quarantines every child of an exiting family via `transition_node_status` /// but leaves `ChildStatus::Active` untouched, so a family that pulled its /// entire collateral *after* an epoch closed would otherwise still collect its /// full pro-rata share of that epoch's stale weights with nothing at risk — /// the opposite of compute-scoring's "a stranded reward is not a stranded /// fund" intent. The weight alone cannot be relied on to encode the verdict: /// `vali_submit_epoch_close` always writes the submitted weight and transitions /// status separately, so a batch entry may carry `Quarantined` *and* a non-zero /// weight. /// /// `MinerStatuses` is `OptionQuery` and a node recovering to `Active` has its /// row REMOVED, so an absent row means Active and must NOT be filtered out. /// /// Weights of every child belonging to the same family are summed so a family /// receives one transfer and consumes one `MaxComputeMinersPerPayout` slot, /// however many nodes it runs. pub struct ComputeMinerWeightsSource; impl pallet_hippocampus::ComputeMinerWeights for ComputeMinerWeightsSource { fn active_compute_miners() -> Vec<(AccountId, u128)> { use sp_std::collections::btree_map::BTreeMap; let epoch = pallet_compute_scoring::CurrentEpoch::::get(); let mut by_family: BTreeMap = BTreeMap::new(); for entry in pallet_compute_scoring::Pallet::::epoch_weights_for(epoch) { if entry.weight == 0 { continue; } let Some(child) = pallet_compute_scoring::NodeIdToChild::::get(entry.node_id) else { continue; }; let Some(reg) = pallet_compute_scoring::ChildRegistrations::::get(&child) else { continue; }; if reg.status != pallet_compute_scoring::ChildStatus::Active { continue; } // Absent row == Active (see above); only an explicit non-Active // operational status is disqualifying. if let Some(op) = pallet_compute_scoring::MinerStatuses::::get(entry.node_id) { if op.status != pallet_compute_scoring::MinerStatus::Active { continue; } } by_family .entry(reg.family) .and_modify(|w| *w = w.saturating_add(entry.weight)) .or_insert(entry.weight); } by_family.into_iter().collect() } fn current_weight_epoch() -> Option { // Same value `active_compute_miners` reads its weights from, so the // bank's replay guard keys on exactly the epoch it is settling. Some(pallet_compute_scoring::CurrentEpoch::::get()) } } /// Adapter: token price in USD (fixed-point 18 decimals) from the credits /// pallet alpha price feed. pub struct AlphaTokenPriceUsd; impl frame_support::traits::Get for AlphaTokenPriceUsd { fn get() -> u128 { pallet_credits::Pallet::::alpha_price() } } // Implement Arion pallet configuration // ── compute-scoring (§13 status / §23 reward-weights / §I registration) ── // The pallet's source of truth is `hippius-compute/pallets/compute-scoring`; // this tree vendors it. The runtime name MUST stay exactly `ComputeScoring`: // `hippius-compute/binaries/ticket-validator` reads storage by // twox_128("ComputeScoring"), so renaming it silently breaks every reader. pub struct ComputeScoringAuthorityMembers; impl frame_support::traits::SortedMembers for ComputeScoringAuthorityMembers { fn sorted_members() -> Vec { let account = AccountId32::from_ss58check("5CP9wzk9G3kMdJmNyAsWGWVWDQE7Goe1dUvKtMv51EoXs563") .expect("Invalid SS58 address"); vec![account] } } parameter_types! { /// Domain separator for signatures scoped to this pallet instance. pub const ComputePalletInstance: [u8; 32] = hex_literal::hex!( "01d4edff0d4d62f0735960662a177fd5f804c9611b413ee1abac8ecad732fb41" ); /// Genesis hash of the chain this runtime serves — NOT `block_hash(0)`, /// which prunes after `BlockHashCount`. /// /// Read from the running chain: /// curl -s -X POST https://rpc.hippius.network \ /// -H 'Content-Type: application/json' \ /// -d '{"jsonrpc":"2.0","id":1,"method":"chain_getBlockHash","params":[0]}' /// -> 0x28a6b54823f786c5dd8520ef7bdb0ee2639173815bfbb7719bcf58ef9eb5e1f9 /// system_chain = "Hippius Mainnet", specVersion = 92003 /// /// Matches `LocalDefaultGenesisHash` further down this file, which /// `pallet-execution-unit` already pins to the same chain. /// /// ⚠️ THIS CRATE IS DEPLOYED TO TWO CHAINS. It builds both /// `chainspecs/mainnet/hippius-mainnet.json` ("Hippius Mainnet") and the /// "Hippius Testnet" spec in `node/src/chainspec/mainnet.rs`. Both report /// specVersion 92003, so a specVersion match does NOT tell them apart — /// only the genesis hash does. A compile-time constant can therefore only /// ever be right for one of them; on testnet every `submit_audit_stats` / /// `submit_live_attestation` will fail the genesis check with this value. /// /// TODO: move this out of `parameter_types!` into a storage value set by an /// admin extrinsic at post-upgrade init, so one runtime can serve both /// chains. Until then, this constant tracks MAINNET. pub const ComputeChainGenesis: [u8; 32] = hex_literal::hex!( "28a6b54823f786c5dd8520ef7bdb0ee2639173815bfbb7719bcf58ef9eb5e1f9" ); } impl pallet_compute_scoring::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ComputeScoringAdminOrigin = frame_system::EnsureSignedBy; // Root is admitted ALONGSIDE the pinned authority. `vali_submit_epoch_close` // moved off `ensure_root` onto this origin, so binding it to // `EnsureSignedBy` alone would strand any sudo-wrapped submitter the // moment the upgrade lands. Keeping root costs nothing — it was already // strictly more privileged than this account. type AuditAuthorityOrigin = EitherOfDiverse< EnsureRoot, frame_system::EnsureSignedBy, >; type DepositCurrency = Balances; type FamilyRegistry = pallet_registration::Pallet; type ProxyVerifier = pallet_proxy::Pallet; type Registration = pallet_registration::Pallet; type RankingsSink = (); type MaxFamilies = ConstU32<600>; type MaxChildrenTotal = ConstU32<1000>; type MaxChildrenPerFamily = ConstU32<35>; type BaseChildDeposit = BaseChildDeposit; type GlobalDepositHalvingPeriodBlocks = GlobalDepositHalvingPeriodBlocks; type UnregisterCooldownBlocks = UnregisterCooldownBlocks; type UnbondingPeriodBlocks = UnbondingPeriodBlocks; type WeightInfo = pallet_compute_scoring::weights::SubstrateWeight; type MaxAggregateBody = ConstU32<8192>; type MaxValidatorIdLen = ConstU32<64>; type MaxFamilyIdLen = ConstU32<64>; type MaxAuditVmKeyIdLen = ConstU32<64>; type ComputePalletInstance = ComputePalletInstance; type ComputeChainGenesis = ComputeChainGenesis; type NowUnix = Timestamp; type MaxMinerStatusUpdatesPerCall = ConstU32<128>; /// R27 history-sweep drain rate, in storage keys per epoch close. /// Must stay ABOVE the accrual rate — `MaxMinerStatusUpdatesPerCall` /// (128) plus one `LiveAttestationCount` key per VM attesting that /// epoch — or the retained window grows past `EpochHistoryRetention`. /// 2048 covers the current fleet with headroom; watch /// `EpochHistoryPruneBacklog` and raise it if that event appears. type MaxEpochPruneKeysPerCall = ConstU32<2048>; type MaxLiveAttestationBody = ConstU32<1024>; type MaxVmIdLen = ConstU32<64>; type MaxKbsAttestationPubkeys = ConstU32<8>; } impl pallet_arion::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ArionAdminOrigin = frame_system::EnsureSignedBy; type MapAuthorityOrigin = frame_system::EnsureSignedBy; type StatsAuthorityOrigin = frame_system::EnsureSignedBy; type WeightAuthorityOrigin = frame_system::EnsureSignedBy; type AttestationAuthorityOrigin = frame_system::EnsureSignedBy; type MaxContentHashLen = ConstU32<32>; type AttestationRetentionBuckets = ConstU32<168>; type MaxAttestationBucketsPrunePerCall = MaxAttestationBucketsPrunePerCall; type MaxNodeWeightPrunePerCall = MaxNodeWeightPrunePerCall; type MaxNodeWeightScanPerCall = MaxNodeWeightScanPerCall; type MaxFamilyRecomputePerCall = MaxFamilyRecomputePerCall; type WeightInfo = pallet_arion::weights::SubstrateWeight; type MaxAttestations = ConstU32<1000>; type MaxShardHashLen = ConstU32<100>; type MaxWardenPubkeyLen = ConstU32<100>; type MaxSignatureLen = ConstU32<100>; type MaxMerkleProofLen = ConstU32<100>; type MaxWardenIdLen = ConstU32<100>; type DepositCurrency = Balances; type FamilyRegistry = pallet_registration::Pallet; type ProxyVerifier = pallet_proxy::Pallet; type EnforceRegisteredMinersInMap = ConstBool; type MaxMiners = MaxMiners; type EpochCrushMapRetention = EpochCrushMapRetention; type MaxCrushEpochPrunesPerCall = MaxCrushEpochPrunesPerCall; type MaxEndpointLen = MaxEndpointLen; type MaxHttpAddrLen = MaxHttpAddrLen; type MaxStatsUpdates = MaxStatsUpdates; type MaxFamilies = ConstU32<600>; type MaxChildrenTotal = ConstU32<1000>; type MaxChildrenPerFamily = ConstU32<35>; type BaseChildDeposit = BaseChildDeposit; type GlobalDepositHalvingPeriodBlocks = GlobalDepositHalvingPeriodBlocks; type UnregisterCooldownBlocks = UnregisterCooldownBlocks; type UnbondingPeriodBlocks = UnbondingPeriodBlocks; type MaxNodeWeightUpdates = MaxNodeWeightUpdates; type MaxNodeWeight = MaxNodeWeight; type MaxFamilyWeight = MaxFamilyWeight; type FamilyScoreFloorBytes = FamilyScoreFloorBytes; type FamilyScoreCeilBytes = FamilyScoreCeilBytes; type MaxFamilyScore = MaxFamilyScore; type StaleChildBuckets = StaleChildBuckets; type FamilyWeightEmaAlphaPermille = FamilyWeightEmaAlphaPermille; type MaxFamilyWeightDeltaPerBucket = MaxFamilyWeightDeltaPerBucket; type NewcomerGraceBuckets = NewcomerGraceBuckets; type NewcomerFloorWeight = NewcomerFloorWeight; type NodeBandwidthWeightPermille = NodeBandwidthWeightPermille; type NodeStorageWeightPermille = NodeStorageWeightPermille; type NodeScoreScale = NodeScoreScale; type StrikePenalty = StrikePenalty; type IntegrityFailPenalty = IntegrityFailPenalty; type MinerStatsPruneInterval = ArionMinerStatsPruneInterval; type MinerStatsPruneMaxScanPerBlock = ArionMinerStatsPruneMaxScanPerBlock; type PalletId = ArionPalletId; type PayoutSource = ArionPayoutSource; type Staking = Staking; type TokenPriceUsd = AlphaTokenPriceUsd; type SettlementInterval = ArionSettlementInterval; } parameter_types! { pub const HippocampusPalletId: PalletId = PalletId(*b"hipocamp"); /// Miner payment settlement interval (~24h at 6s/block). `0` = disabled. pub const ArionSettlementInterval: BlockNumber = 14_400; pub const BlocksPer24Hours: BlockNumber = 14_400; // ~24 hours at 6-second blocks /// Total emission the bank may release to miners per 24 hours, across /// `pay_storage_miners` AND `pay_compute_miners` together — one shared /// counter, not one each. /// /// 3500 is deliberately the COMBINED ceiling, not a per-payout allowance, /// and is NOT to be scaled up because a second consumer was added. The two /// payouts compete for one daily budget by design: whatever storage draws /// is unavailable to compute for the rest of the period, and vice versa. /// A day where storage draws heavily and compute then hits /// `ExceedsDaily24HourMinerPayoutLimit` is the cap working as intended — /// no funds are lost, the compute compartment is cumulative and the /// remainder settles in a later period. /// /// Do not "fix" that contention by raising this to cover both consumers /// separately; sizing it against the sum of both emission schedules would /// double the maximum daily drain this constant exists to bound. pub const Max24HourMinerPayout: Balance = 3_500_000_000_000_000_000_000; // 3500 alpha (18 decimals) } impl pallet_hippocampus::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type PalletId = HippocampusPalletId; type AdminOrigin = frame_system::EnsureSignedBy; type StorageMinerWeights = ArionFamilyWeightsSource; // Payees are Arion families, not ranked nodes. Every family in the payout // set has at least one Active child, and `register_child` caps // `TotalActiveChildren` at `MaxChildrenTotal` (1_000), so at most 1_000 // families can ever carry weight. Keep this ABOVE that — if the family // count passes this constant, every `pay_storage_miners` call fails with // `TooManyMiners` and no storage emission can be paid at all, with each // missed day unrecoverable under the 24-hour cap. // // NOT sized off `MaxFamilies` (600): that cap is only enforced when a // family claims its FIRST fee-free slot, and `FamilyCount` is decremented // on cleanup without being re-incremented on re-registration, so it does // not bound the number of distinct families. `MaxChildrenTotal` does. type MaxMinersPerPayout = ConstU32<1024>; type BlocksPer24Hours = BlocksPer24Hours; type Max24HourMinerPayout = Max24HourMinerPayout; type ComputeMinerWeights = ComputeMinerWeightsSource; // Payees are families, not nodes. The bound comes from // `pallet_compute_scoring::MaxMinerStatusUpdatesPerCall` (128): one close // per epoch writes at most that many `EpochWeights` entries, which // aggregate to at most that many distinct families. Keep this ABOVE // `MaxMinerStatusUpdatesPerCall` — if that constant ever exceeds this one, // every `pay_compute_miners` call fails with `TooManyComputeMiners`. type MaxComputeMinersPerPayout = ConstU32<640>; type WeightInfo = pallet_hippocampus::weights::SubstrateWeight; } #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; use static_assertions::const_assert; use frame_support::traits::ExistenceRequirement; pub use frame_support::{ construct_runtime, dispatch::DispatchClass, pallet_prelude::Get, parameter_types, traits::{ ConstU16, Currency, EitherOfDiverse, EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter, LockIdentifier, OnUnbalanced, }, weights::{ constants::{ BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_MILLIS, }, IdentityFee, Weight, }, PalletId, StorageValue, }; #[cfg(any(feature = "std", test))] pub use frame_system::Call as SystemCall; use frame_system::EnsureRoot; pub use hippius_primitives::{ currency::*, fee::*, time::*, types::{ AccountId, AccountIndex, Address, Balance, BlockNumber, Hash, Header, Index, Moment, Signature, }, verifier::{arkworks::ArkworksVerifierGroth16Bn254, circom::CircomVerifierGroth16Bn254}, BabeId, AVERAGE_ON_INITIALIZE_RATIO, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, }; use hippius_primitives::{ democracy::{ COOLOFF_PERIOD, ENACTMENT_PERIOD, FASTTRACK_VOTING_PERIOD, LAUNCH_PERIOD, MAX_PROPOSALS, MINIMUM_DEPOSIT, VOTING_PERIOD, }, elections::{ CANDIDACY_BOND, DESIRED_MEMBERS, DESIRED_RUNNERS_UP, ELECTIONS_PHRAGMEN_PALLET_ID, MAX_CANDIDATES, MAX_VOTERS, TERM_DURATION, }, staking::{ BONDING_DURATION, HISTORY_DEPTH, MAX_NOMINATOR_REWARDED_PER_VALIDATOR, OFFCHAIN_REPEAT, SESSIONS_PER_ERA, SLASH_DEFER_DURATION, }, treasury::{ BURN, DATA_DEPOSIT_PER_BYTE, MAXIMUM_REASON_LENGTH, MAX_APPROVALS, PROPOSAL_BOND, PROPOSAL_BOND_MINIMUM, SPEND_PERIOD, TIP_COUNTDOWN, TIP_FINDERS_FEE, TIP_REPORT_DEPOSIT_BASE, TREASURY_PALLET_ID, }, }; pub use pallet_balances::Call as BalancesCall; pub use pallet_timestamp::Call as TimestampCall; use sp_runtime::generic::Era; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; pub use sp_runtime::{MultiAddress, Perbill, Percent, Permill}; use sp_staking::currency_to_vote::U128CurrencyToVote; // Precompiles pub type Precompiles = HipiusPrecompiles; // Frontier use fp_rpc::TransactionStatus; use pallet_ethereum::{Call::transact, Transaction as EthereumTransaction}; use pallet_evm::{Account as EVMAccount, FeeCalculator, Runner}; pub type Nonce = u32; /// The BABE epoch configuration at genesis. pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration = sp_consensus_babe::BabeEpochConfiguration { c: PRIMARY_PROBABILITY, allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondaryPlainSlots, }; /// This runtime version. #[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("hippius"), impl_name: create_runtime_str!("hippius"), authoring_version: 1, spec_version: 92015, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, state_version: 0, }; impl pallet_registration::ProxyTypeCompat for ProxyType { fn is_non_transfer(&self) -> bool { matches!(self, ProxyType::NonTransfer) } fn is_any(&self) -> bool { matches!(self, ProxyType::Any) } } /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } pub const MAXIMUM_BLOCK_LENGTH: u32 = 5 * 1024 * 1024; // Arion pallet configuration parameter_types! { // Maximum number of miners in the CRUSH map pub const MaxMiners: u32 = 1000; // Maximum length for endpoint strings pub const MaxEndpointLen: u32 = 256; // Maximum length for HTTP address strings pub const MaxHttpAddrLen: u32 = 128; // Maximum number of stats updates per submission pub const MaxStatsUpdates: u32 = 100; // Maximum number of node weight updates per submission pub const MaxNodeWeightUpdates: u32 = 100; // Maximum node weight pub const MaxNodeWeight: u16 = 50_000; // Maximum family weight pub const MaxFamilyWeight: u16 = 65_535; // Aggregate family scoring range: 0 at 100 GiB, MaxFamilyScore at 1 PiB pub const FamilyScoreFloorBytes: u128 = 100 * (1u128 << 30); pub const FamilyScoreCeilBytes: u128 = 1u128 << 50; // Max achievable family score — strictly below MaxFamilyWeight (u16::MAX) // so families can never sit saturated at the storage-type ceiling. pub const MaxFamilyScore: u16 = 60_000; // Children not refreshed for more than this many buckets stop counting. pub const StaleChildBuckets: u32 = 4; // EMA alpha for family weight (permille) pub const FamilyWeightEmaAlphaPermille: u32 = 300; // Maximum family weight delta per bucket pub const MaxFamilyWeightDeltaPerBucket: u16 = 100; // Newcomer grace period in buckets pub const NewcomerGraceBuckets: u32 = 24; // Newcomer floor weight pub const NewcomerFloorWeight: u16 = 10; // Bandwidth weight (permille) pub const NodeBandwidthWeightPermille: u32 = 700; // Storage weight (permille) pub const NodeStorageWeightPermille: u32 = 300; // Node score scale factor pub const NodeScoreScale: u16 = 700; // Strike penalty pub const StrikePenalty: u16 = 50; // Integrity fail penalty pub const IntegrityFailPenalty: u16 = 100; } parameter_types! { pub const Version: RuntimeVersion = VERSION; pub const BlockHashCount: BlockNumber = 256; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights ::with_sensible_defaults(MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO); pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength ::max_with_normal_ratio(MAXIMUM_BLOCK_LENGTH, NORMAL_DISPATCH_RATIO); pub const SS58Prefix: u8 = 42; } /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know /// the specifics of the runtime. They can then be made to be agnostic over specific formats /// of data like extrinsics, allowing for them to continue syncing the network through upgrades /// to even the core data structures. pub mod opaque { use super::*; pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; /// Opaque block identifier type. pub type BlockId = generic::BlockId; impl_opaque_keys! { pub struct SessionKeys { pub babe: Babe, pub grandpa: Grandpa, pub im_online: ImOnline, } } } #[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)] impl frame_system::Config for Runtime { type AccountData = pallet_balances::AccountData; type AccountId = AccountId; type BaseCallFilter = filters::MainnetCallFilter; type BlockHashCount = BlockHashCount; type BlockLength = BlockLength; type Block = Block; type BlockWeights = BlockWeights; type RuntimeCall = RuntimeCall; type DbWeight = RocksDbWeight; type RuntimeEvent = RuntimeEvent; type Hash = Hash; type Nonce = Nonce; type Hashing = BlakeTwo256; type Lookup = Indices; type MaxConsumers = frame_support::traits::ConstU32<16>; type OnKilledAccount = (); type OnNewAccount = (); type OnSetCode = (); type RuntimeTask = RuntimeTask; type RuntimeOrigin = RuntimeOrigin; type PalletInfo = PalletInfo; type SS58Prefix = SS58Prefix; type SystemWeightInfo = frame_system::weights::SubstrateWeight; type Version = Version; } parameter_types! { pub const IndexDeposit: Balance = UNIT; } impl pallet_indices::Config for Runtime { type AccountIndex = AccountIndex; type Currency = Balances; type Deposit = IndexDeposit; type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_indices::weights::SubstrateWeight; } parameter_types! { pub const MinimumPeriod: u64 = SLOT_DURATION / 2; } impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Babe; type MinimumPeriod = MinimumPeriod; type WeightInfo = (); } parameter_types! { // pub const ExistentialDeposit: u128 = EXISTENTIAL_DEPOSIT / 100_000_000; // Existential deposit. pub const ExistentialDeposit: u64 = 500; pub const TransferFee: u128 = MILLIUNIT; pub const CreationFee: u128 = MILLIUNIT; pub const MaxLocks: u32 = 50; pub const MaxReserves: u32 = 50; pub const MaxFreezes: u32 = 50; } pub type NegativeImbalance = as Currency< ::AccountId, >>::NegativeImbalance; impl pallet_balances::Config for Runtime { /// The type for recording an account's balance. type Balance = Balance; /// The ubiquitous event type type RuntimeEvent = RuntimeEvent; type DustRemoval = TransferDustToTreasury; type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = pallet_balances::weights::SubstrateWeight; type MaxLocks = MaxLocks; type MaxReserves = MaxReserves; type ReserveIdentifier = [u8; 8]; type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; type FreezeIdentifier = RuntimeFreezeReason; type MaxFreezes = MaxFreezes; } parameter_types! { // pub const TransactionByteFee: Balance = MILLIUNIT; pub const TransactionByteFee: Balance = MILLIUNIT / 2; // pub const OperationalFeeMultiplier: u8 = 5; pub const OperationalFeeMultiplier: u8 = 2; pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(1, 100_000); // pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000_000u128); pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 10_000_000u128); pub MaximumMultiplier: Multiplier = Bounded::max_value(); pub FeeMultiplier: Multiplier = Multiplier::saturating_from_rational(1,1); } impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; #[allow(deprecated)] type OnChargeTransaction = CurrencyAdapter>; type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = IdentityFee; type LengthToFee = IdentityFee; type FeeMultiplierUpdate = pallet_transaction_payment::ConstFeeMultiplier; // type FeeMultiplierUpdate = TargetedFeeAdjustment< // Self, // TargetBlockFullness, // AdjustmentVariable, // MinimumMultiplier, // MaximumMultiplier, // >; } parameter_types! { pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * BlockWeights::get().max_block; } impl pallet_scheduler::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; type PalletsOrigin = OriginCaller; type RuntimeCall = RuntimeCall; type MaximumWeight = MaximumSchedulerWeight; type ScheduleOrigin = EnsureRoot; type MaxScheduledPerBlock = ConstU32<512>; type WeightInfo = pallet_scheduler::weights::SubstrateWeight; type OriginPrivilegeCmp = EqualPrivilegeOnly; type Preimages = Preimage; } parameter_types! { pub const PreimageMaxSize: u32 = 4096 * 1024; pub const PreimageBaseDeposit: Balance = UNIT; // One cent: $10,000 / MB pub const PreimageByteDeposit: Balance = 10 * MILLIUNIT; } impl pallet_preimage::Config for Runtime { type Consideration = (); type Currency = Balances; type RuntimeEvent = RuntimeEvent; type ManagerOrigin = EnsureRoot; type WeightInfo = pallet_preimage::weights::SubstrateWeight; } impl pallet_randomness_collective_flip::Config for Runtime {} impl pallet_sudo::Config for Runtime { type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } parameter_types! { pub const MarketplaceMinSubscriptionBlocks: BlockNumber = 2; pub const MaxActiveSubscriptionsPerUser: u32 = 5; } pub struct EnsureSubscriptionOwner; impl frame_support::traits::EnsureOrigin for EnsureSubscriptionOwner where OuterOrigin: Into, OuterOrigin>> + From>, { type Success = AccountId; fn try_origin(o: OuterOrigin) -> Result { o.into().and_then(|o| match o { frame_system::RawOrigin::Signed(who) => Ok(who), r => Err(OuterOrigin::from(r)), }) } #[cfg(feature = "runtime-benchmarks")] fn try_successful_origin() -> Result { let zero_account = AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) .expect("infinite length input; no invalid inputs for type; qed"); Ok(OuterOrigin::from(frame_system::RawOrigin::Signed(zero_account))) } } parameter_types! { // account id : 5EYCAe5jLNAGgCNQpT4E1xSxeJvqstzrt9hx3HKLkkbiwPci pub const StakingPotId: PalletId = PalletId(*b"stk/rpot"); } pub struct MarketplaceRewardPayout; impl pallet_staking::EraPayout for MarketplaceRewardPayout { fn era_payout( _total_staked: Balance, _total_issuance: Balance, _era_duration_millis: u64, ) -> (Balance, Balance) { // Marketplace alpha stays in bank, no distribution to stakers let registration_balance = pallet_registration::Pallet::::balance(); let registration_account = pallet_registration::Pallet::::account_id(); // Registration revenue routing destination (intentional — not a // treasury bypass). . let recipient_account = AccountId32::from_ss58check("5GEudEYMVWJr64Y3599urXfG1tg4u7iNFWmBYZUET2YTdPkn") .expect("Invalid SS58 address"); if registration_balance > 0 { // Calculate amounts for each destination let staking_amount = registration_balance .checked_mul(50u32.into()) .and_then(|x| x.checked_div(100u32.into())) .unwrap_or_default(); let treasury_amount = registration_balance .checked_mul(50u32.into()) .and_then(|x| x.checked_div(100u32.into())) .unwrap_or_default(); // Transfer to the specific account if let Err(e) = pallet_balances::Pallet::::transfer( ®istration_account.clone(), &recipient_account, treasury_amount, ExistenceRequirement::KeepAlive, ) { log::error!( target: "runtime::marketplace_payout", "❌ Treasury transfer from registration failed: {:?}", e ); } // Get the list of validators from the session let validators = >::validators(); // Ensure you have the correct type here let num_validators = validators.len() as u32; if num_validators > 0 { let amount_per_validator = staking_amount.checked_div(num_validators.into()).unwrap_or_default(); for validator in validators { // Transfer the amount to the validator's account first if let Err(e) = pallet_balances::Pallet::::transfer( ®istration_account.clone(), &validator, amount_per_validator, ExistenceRequirement::KeepAlive, ) { log::error!( target: "runtime::marketplace_payout", "❌ Validator payout transfer from registration failed for {:?}: {:?}", validator, e ); continue; } let bond_result = if pallet_staking::Pallet::::ledger( sp_staking::StakingAccount::Stash(validator.clone()), ) .is_ok() { pallet_staking::Pallet::::bond_extra( frame_system::RawOrigin::Signed(validator.clone()).into(), amount_per_validator, ) } else { pallet_staking::Pallet::::bond( frame_system::RawOrigin::Signed(validator.clone()).into(), amount_per_validator, pallet_staking::RewardDestination::Staked, ) }; if let Err(e) = bond_result { log::warn!( target: "runtime::marketplace_payout", "⚠️ Auto-bond failed for validator {:?}: {:?}", validator, e ); } } } } // Handle explicit staking pot dedicated for rewards use sp_runtime::traits::AccountIdConversion; let staking_pot_account: AccountId = StakingPotId::get().into_account_truncating(); let staking_pot_balance = pallet_balances::Pallet::::free_balance(&staking_pot_account); let mut payout = 0u32.into(); if staking_pot_balance > 0 { // Withdraw the pot's balance to create a NegativeImbalance that is dropped. // This alone has no net effect on total_issuance under pallet_balances semantics. // However, the subsequent staking payout calls deposit_creating and passes the // PositiveImbalance to Reward::on_unbalanced. Since Reward = () in this runtime, // that PositiveImbalance is dropped, decreasing total_issuance. Net effect per era: // total_issuance -= payout + rewarded_amount. The pot is effectively transferred // to stakers, but total_issuance is *not* issuance-neutral (pre-existing issue). // Account reaping after the first drain. `AllowDeath` reaps the pot once the balance hits zero, // so every sudo refill must send at least the existential deposit (ED) to recreate the account. if let Ok(_imbalance) = pallet_balances::Pallet::::withdraw( &staking_pot_account, staking_pot_balance, WithdrawReasons::all(), ExistenceRequirement::AllowDeath, ) { payout = staking_pot_balance; } else { log::warn!( target: "runtime::staking_payout", "⚠️ Silent failure on withdraw for staking pot account: {:?}", staking_pot_account, ); } log::info!( target: "runtime::staking_payout", "✅ Staking reward payout: {}", payout, ); } (payout, 0u32.into()) } } pub struct TransferDustToTreasury; type FungibleImbalance = frame_support::traits::fungible::Imbalance< Balance, frame_support::traits::fungible::DecreaseIssuance, frame_support::traits::fungible::IncreaseIssuance, >; impl OnUnbalanced for TransferDustToTreasury { fn on_unbalanced(amount: FungibleImbalance) { let treasury_account = Treasury::account_id(); // Convert the imbalance to the correct type let negative_imbalance = pallet_balances::NegativeImbalance::::new(amount.peek()); // Resolve the converted imbalance to the treasury account Balances::resolve_creating(&treasury_account, negative_imbalance); } } parameter_types! { pub const MarketplacePalletId: PalletId = PalletId(*b"mrktplce"); pub const BlockDurationMillis: u64 = MILLISECS_PER_BLOCK; pub const BlocksPerHour: u32 = HOURS as u32; // as era is of 6 hours pub const BlocksPerEra: u32 = (HOURS * 6) as u32; pub const RefferallCoolDOwnPeriod : u32 = 200; pub const BlockChargeCheckInterval: u32 = 8; pub const MaxRequestsPerBlock: u32 = 5; pub const MaxUserFileUsageUpdatesPerCall: u32 = 250; /// Cap on `create_referral_codes_for` batch size. pub const MaxReferralCodesPerCall: u32 = 250; /// Accrued referral commissions are swept out to referrers every 30 /// minutes, with no balance threshold to reach first. pub const ReferralPayoutInterval: u32 = (MINUTES * 30) as u32; /// Referrers paid per sweep. At one sweep every 30 minutes this clears /// 12_000 owed referrers a day, far ahead of any plausible backlog, while /// keeping a single block's payout work bounded. pub const MaxReferralPayoutsPerSweep: u32 = 250; /// Accounts charged per renewal drain. /// /// A backstop, not the operative bound. `RenewalWeightBudget` binds first — /// at the measured 2.80ms per account it admits ~35 a tick, well under this /// — so what this figure does is cap the damage if the measurement is ever /// wrong in the cheap direction, not decide the batch size. /// /// Left at 128 rather than lowered to match: a count that tracks the meter /// would have to move with every re-measurement, and a backstop that only /// engages when the meter is wrong is doing its job precisely by not being /// reached. Raise it only against a benchmark. pub const MaxSubscriptionChargesPerRun: u32 = 128; /// Accounts the one-time due-index backfill walks per tick. Read-only over /// the subscription map, so it is cheaper per account than a charge. pub const MaxBackfillAccountsPerRun: u32 = 256; /// Share of a block the renewal drain may spend in one tick. /// /// `AVERAGE_ON_INITIALIZE_RATIO` is the 10% of a block the builder assumes /// *all* hook work costs, and the drain shares `on_initialize` with hourly /// billing, the backfill and the referral sweep — so it gets half of that /// allowance rather than the whole of it. At 2000ms a block this is 100ms, /// which at the measured 2.80ms per charged account is ~35 accounts: well /// below `MaxSubscriptionChargesPerRun`, so the meter is the binding /// constraint and the count is the backstop. That is the intended order — /// the count rests on an estimate, the meter does not. /// /// **Throughput this implies, and why the 1st of the month is the number /// that matters.** ~35 accounts every 8 blocks at 6s is ~63_000 renewals a /// day. That is ample for a date-to-date population spread over 28 days, /// but the spread is the part not to take on faith: every subscription /// predating this change stays anchored to the 1st for life, and new /// signups cluster on round dates rather than distributing evenly. The /// index makes the other 27 days cheap; it does not make the 1st cheaper, /// it only makes it drain safely across ticks instead of in one block. /// /// So the figure to watch after launch is how many ticks the 1st takes to /// clear. Under ~63_000 accounts due on it, the day clears within itself /// and nothing is deferred. Past that the cursor simply carries the /// remainder into the 2nd — correct, but a day of renewals arriving a day /// late — and that is the point to raise this share rather than the count. pub RenewalWeightBudget: Perbill = AVERAGE_ON_INITIALIZE_RATIO / 2; /// Share of a block the hourly pay-as-you-go sweep may spend in one tick. /// /// 3% of 2000ms is 60ms, which alongside the renewal drain's 100ms keeps /// both inside the ~200ms `AVERAGE_ON_INITIALIZE_RATIO` allows for all hook /// work, with room left for the referral sweep and the request-count clear. /// The two budgets are separate rather than shared so an upgrade-window /// backfill cannot starve the sweep that runs every tick. pub HourlyWeightBudget: Perbill = Perbill::from_percent(3); /// Share of a block the matured-alpha release sweep may spend in one tick. /// /// 1% of 2000ms is 20ms — ~800 batch probes a tick. Deliberately the /// smallest of the three: what it guards is a 15-day maturity timer, so /// falling a few ticks behind costs nothing, and the three budgets together /// (5% + 3% + 1%) stay inside the ~10% `AVERAGE_ON_INITIALIZE_RATIO` /// assumes for all hook work. pub AlphaReleaseWeightBudget: Perbill = Perbill::from_percent(1); /// Accounts whose subscription snapshots are repriced per block after a /// `set_plan_price`. Runs every block, so this clears 250 accounts a block /// — a reprice over 100k accounts settles in ~7 minutes — while keeping the /// added per-block work bounded and well clear of the block limit. pub const MaxRepricedAccountsPerBlock: u32 = 250; } impl pallet_marketplace::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type Balance = Balance; type MinSubscriptionBlocks = MarketplaceMinSubscriptionBlocks; type MaxActiveSubscriptions = MaxActiveSubscriptionsPerUser; type UpdateOrigin = EnsureSubscriptionOwner; type PalletId = MarketplacePalletId; type BlockDurationMillis = BlockDurationMillis; type BlocksPerEra = BlocksPerEra; type CustomHash = sp_core::H256; type BlocksPerHour = BlocksPerHour; type BlockChargeCheckInterval = BlockChargeCheckInterval; type AuthorityId = pallet_marketplace::crypto::TestAuthId; type MaxRequestsPerBlock = MaxRequestsPerBlock; type MaxUserFileUsageUpdatesPerCall = MaxUserFileUsageUpdatesPerCall; type MaxReferralCodesPerCall = MaxReferralCodesPerCall; type ReferralPayoutInterval = ReferralPayoutInterval; type MaxReferralPayoutsPerSweep = MaxReferralPayoutsPerSweep; type MaxRepricedAccountsPerBlock = MaxRepricedAccountsPerBlock; type MaxSubscriptionChargesPerRun = MaxSubscriptionChargesPerRun; type MaxBackfillAccountsPerRun = MaxBackfillAccountsPerRun; type RenewalWeightBudget = RenewalWeightBudget; type HourlyWeightBudget = HourlyWeightBudget; type AlphaReleaseWeightBudget = AlphaReleaseWeightBudget; type WeightInfo = pallet_marketplace::weights::SubstrateWeight; } parameter_types! { // NOTE: Currently it is not possible to change the epoch duration after the chain has started. // Attempting to do so will brick block production. pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS / 2; pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK; pub const ReportLongevity: u64 = BondingDuration::get() as u64 * SessionsPerEra::get() as u64 * EpochDuration::get(); pub const MaxAuthorities: u32 = 1000; pub const MaxNominators: u32 = 1000; } impl pallet_babe::Config for Runtime { type EpochDuration = EpochDuration; type ExpectedBlockTime = ExpectedBlockTime; type EpochChangeTrigger = pallet_babe::ExternalTrigger; type DisabledValidators = Session; type WeightInfo = (); type MaxAuthorities = MaxAuthorities; type MaxNominators = MaxNominatorRewardedPerValidator; type KeyOwnerProof = >::Proof; type EquivocationReportSystem = pallet_babe::EquivocationReportSystem; } impl pallet_grandpa::Config for Runtime { type RuntimeEvent = RuntimeEvent; type MaxSetIdSessionEntries = frame_support::traits::ConstU64<0>; type MaxAuthorities = MaxAuthorities; type EquivocationReportSystem = pallet_grandpa::EquivocationReportSystem; type KeyOwnerProof = >::Proof; type MaxNominators = MaxNominatorRewardedPerValidator; type WeightInfo = (); } impl pallet_authorship::Config for Runtime { type EventHandler = Staking; type FindAuthor = pallet_session::FindAccountFromAuthorIndex; } use crate::opaque::SessionKeys; impl pallet_session::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ValidatorId = ::AccountId; type ValidatorIdOf = pallet_staking::StashOf; type ShouldEndSession = Babe; type NextSessionRotation = Babe; type SessionManager = pallet_session::historical::NoteHistoricalRoot; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; type WeightInfo = (); } impl pallet_session::historical::Config for Runtime { type FullIdentification = pallet_staking::Exposure; type FullIdentificationOf = pallet_staking::ExposureOf; } parameter_types! { // Six sessions in an era (24 hours). pub const SessionsPerEra: sp_staking::SessionIndex = SESSIONS_PER_ERA / 2; // 28 eras for unbonding (28 days). pub const BondingDuration: sp_staking::EraIndex = BONDING_DURATION; // 27 eras for slash defer duration (27 days). pub const SlashDeferDuration: sp_staking::EraIndex = SLASH_DEFER_DURATION; pub const MaxNominatorRewardedPerValidator: u32 = MAX_NOMINATOR_REWARDED_PER_VALIDATOR; //pub const OffendingValidatorsThreshold: Perbill = OFFENDING_VALIDATOR_THRESHOLD; pub OffchainRepeat: BlockNumber = OFFCHAIN_REPEAT; pub const HistoryDepth: u32 = HISTORY_DEPTH; } pub struct StakingBenchmarkingConfig; impl pallet_staking::BenchmarkingConfig for StakingBenchmarkingConfig { type MaxNominators = ConstU32<1000>; type MaxValidators = ConstU32<1000>; } /// Upper limit on the number of NPOS nominations. const MAX_QUOTA_NOMINATIONS: u32 = 16; pub struct MarketplaceRewardDistributor; impl frame_support::traits::OnUnbalanced> for MarketplaceRewardDistributor { fn on_unbalanced(_amount: pallet_balances::PositiveImbalance) { // Send the full amount to staking rewards // as OnUnbalanced<_>>::on_unbalanced(amount); } } impl pallet_staking::Config for Runtime { type Currency = Balances; type CurrencyBalance = Balance; type AdminOrigin = EnsureRoot; type UnixTime = Timestamp; type CurrencyToVote = U128CurrencyToVote; type RewardRemainder = Treasury; type RuntimeEvent = RuntimeEvent; type Slash = Treasury; // send the slashed funds to the treasury. type Reward = (); // rewards are minted from the void type SessionsPerEra = SessionsPerEra; type BondingDuration = BondingDuration; type SlashDeferDuration = SlashDeferDuration; type SessionInterface = Self; type TargetList = pallet_staking::UseValidatorsMap; // type EraPayout = pallet_staking::ConvertCurve; type EraPayout = MarketplaceRewardPayout; type NextNewSession = Session; type MaxExposurePageSize = ConstU32<64>; type MaxControllersInDeprecationBatch = ConstU32<100>; type ElectionProvider = ElectionProviderMultiPhase; type GenesisElectionProvider = onchain::OnChainExecution; type VoterList = BagsList; type MaxUnlockingChunks = ConstU32<32>; type HistoryDepth = HistoryDepth; type EventListeners = NominationPools; type WeightInfo = pallet_staking::weights::SubstrateWeight; type NominationsQuota = pallet_staking::FixedNominationsQuota; type BenchmarkingConfig = StakingBenchmarkingConfig; type DisablingStrategy = pallet_staking::UpToLimitDisablingStrategy; } parameter_types! { pub const LaunchPeriod: BlockNumber = LAUNCH_PERIOD; pub const VotingPeriod: BlockNumber = VOTING_PERIOD; pub const FastTrackVotingPeriod: BlockNumber = FASTTRACK_VOTING_PERIOD; pub const MinimumDeposit: Balance = MINIMUM_DEPOSIT; pub const EnactmentPeriod: BlockNumber = ENACTMENT_PERIOD; pub const CooloffPeriod: BlockNumber = COOLOFF_PERIOD; pub const MaxProposals: u32 = MAX_PROPOSALS; } type EnsureRootOrHalfCouncil = EitherOfDiverse< EnsureRoot, pallet_collective::EnsureProportionMoreThan, >; impl pallet_democracy::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type SubmitOrigin = frame_system::EnsureSigned; type EnactmentPeriod = EnactmentPeriod; type LaunchPeriod = LaunchPeriod; type VotingPeriod = VotingPeriod; type VoteLockingPeriod = EnactmentPeriod; // Same as EnactmentPeriod type MinimumDeposit = MinimumDeposit; /// A straight majority of the council can decide what their next motion is. type ExternalOrigin = pallet_collective::EnsureProportionAtLeast; /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. type ExternalMajorityOrigin = pallet_collective::EnsureProportionAtLeast; /// A unanimous council can have the next scheduled referendum be a straight default-carries /// (NTB) vote. type ExternalDefaultOrigin = pallet_collective::EnsureProportionAtLeast; /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote /// be tabled immediately and with a shorter voting/enactment period. type FastTrackOrigin = pallet_collective::EnsureProportionAtLeast; type InstantOrigin = pallet_collective::EnsureProportionAtLeast; type InstantAllowed = frame_support::traits::ConstBool; type FastTrackVotingPeriod = FastTrackVotingPeriod; // To cancel a proposal which has been passed, 2/3 of the council must agree to it. type CancellationOrigin = pallet_collective::EnsureProportionAtLeast; // To cancel a proposal before it has been passed, the technical committee must be unanimous or // Root must agree. type CancelProposalOrigin = EitherOfDiverse< EnsureRoot, pallet_collective::EnsureProportionAtLeast, >; type BlacklistOrigin = EnsureRoot; // Any single technical committee member may veto a coming council proposal, however they can // only do it once and it lasts only for the cool-off period. type VetoOrigin = pallet_collective::EnsureMember; type CooloffPeriod = CooloffPeriod; type Slash = Treasury; type Scheduler = Scheduler; type PalletsOrigin = OriginCaller; type MaxVotes = ConstU32<100>; type WeightInfo = pallet_democracy::weights::SubstrateWeight; type MaxProposals = MaxProposals; type Preimages = Preimage; type MaxDeposits = ConstU32<100>; type MaxBlacklisted = ConstU32<100>; } parameter_types! { pub const CouncilMotionDuration: BlockNumber = 5 * DAYS; pub const CouncilMaxProposals: u32 = 100; pub const CouncilMaxMembers: u32 = 100; pub MaxProposalWeight: Weight = Perbill::from_percent(50) * BlockWeights::get().max_block; } type CouncilCollective = pallet_collective::Instance1; impl pallet_collective::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type Proposal = RuntimeCall; type RuntimeEvent = RuntimeEvent; type MotionDuration = CouncilMotionDuration; type MaxProposals = CouncilMaxProposals; type SetMembersOrigin = EnsureRoot; type MaxMembers = CouncilMaxMembers; type DefaultVote = pallet_collective::PrimeDefaultVote; type WeightInfo = pallet_collective::weights::SubstrateWeight; type MaxProposalWeight = MaxProposalWeight; } parameter_types! { // phase durations. 1/4 of the last session for each. pub const SignedPhase: u64 = EPOCH_DURATION_IN_BLOCKS / 4; pub const UnsignedPhase: u64 = EPOCH_DURATION_IN_BLOCKS / 4; // signed config pub const SignedRewardBase: Balance = UNIT; pub const SignedDepositBase: Balance = UNIT; pub const SignedDepositByte: Balance = CENT; pub BetterUnsignedThreshold: Perbill = Perbill::from_rational(1u32, 10_000); // miner configs pub const MultiPhaseUnsignedPriority: TransactionPriority = StakingUnsignedPriority::get() - 1u64; pub MinerMaxWeight: Weight = BlockWeights::get() .get(DispatchClass::Normal) .max_extrinsic.expect("Normal extrinsics have a weight limit configured; qed") .saturating_sub(BlockExecutionWeight::get()); // Solution can occupy 90% of normal block size pub MinerMaxLength: u32 = Perbill::from_rational(9u32, 10) * *BlockLength::get() .max .get(DispatchClass::Normal); } frame_election_provider_support::generate_solution_type!( #[compact] pub struct NposSolution16::< VoterIndex = u32, TargetIndex = u16, Accuracy = sp_runtime::PerU16, MaxVoters = MaxElectingVoters, >(16) ); parameter_types! { pub MaxNominations: u32 = ::LIMIT as u32; pub MaxElectingVoters: u32 = 40_000; pub MaxElectableTargets: u16 = 10_000; // OnChain values are lower. pub MaxOnChainElectingVoters: u32 = 5000; pub MaxOnChainElectableTargets: u16 = 1250; // The maximum winners that can be elected by the Election pallet which is equivalent to the // maximum active validators the staking pallet can have. pub MaxActiveValidators: u32 = 1000; pub ElectionBoundsOnChain: ElectionBounds = ElectionBoundsBuilder::default() .voters_count(5_000.into()).targets_count(1_250.into()).build(); pub ElectionBoundsMultiPhase: ElectionBounds = ElectionBoundsBuilder::default() .voters_count(10_000.into()).targets_count(1_500.into()).build(); } /// The numbers configured here could always be more than the the maximum limits of staking pallet /// to ensure election snapshot will not run out of memory. For now, we set them to smaller values /// since the staking is bounded and the weight pipeline takes hours for this single pallet. pub struct ElectionProviderBenchmarkConfig; impl pallet_election_provider_multi_phase::BenchmarkingConfig for ElectionProviderBenchmarkConfig { const VOTERS: [u32; 2] = [1000, 2000]; const TARGETS: [u32; 2] = [500, 1000]; const ACTIVE_VOTERS: [u32; 2] = [500, 800]; const DESIRED_TARGETS: [u32; 2] = [200, 400]; const SNAPSHOT_MAXIMUM_VOTERS: u32 = 1000; const MINER_MAXIMUM_VOTERS: u32 = 1000; const MAXIMUM_TARGETS: u32 = 300; } /// Maximum number of iterations for balancing that will be executed in the embedded OCW /// miner of election provider multi phase. pub const MINER_MAX_ITERATIONS: u32 = 10; /// A source of random balance for NposSolver, which is meant to be run by the OCW election miner. pub struct OffchainRandomBalancing; impl Get> for OffchainRandomBalancing { fn get() -> Option { use sp_runtime::traits::TrailingZeroInput; let iterations = match MINER_MAX_ITERATIONS { 0 => 0, max => { let seed = sp_io::offchain::random_seed(); let random = ::decode(&mut TrailingZeroInput::new(&seed)) .expect("input is padded with zeroes; qed") % max.saturating_add(1); random as usize }, }; let config = BalancingConfig { iterations, tolerance: 0 }; Some(config) } } pub struct OnChainSeqPhragmen; impl onchain::Config for OnChainSeqPhragmen { type System = Runtime; type Solver = SequentialPhragmen< AccountId, pallet_election_provider_multi_phase::SolutionAccuracyOf, >; type DataProvider = ::DataProvider; type WeightInfo = frame_election_provider_support::weights::SubstrateWeight; type MaxWinners = ::MaxWinners; type Bounds = ElectionBoundsOnChain; } impl pallet_election_provider_multi_phase::MinerConfig for Runtime { type AccountId = AccountId; type MaxLength = MinerMaxLength; type MaxWeight = MinerMaxWeight; type Solution = NposSolution16; type MaxWinners = MaxActiveValidators; type MaxVotesPerVoter = <::DataProvider as ElectionDataProvider>::MaxVotesPerVoter; // The unsigned submissions have to respect the weight of the submit_unsigned call, thus their // weight estimate function is wired to this call's weight. fn solution_weight(v: u32, t: u32, a: u32, d: u32) -> Weight { < ::WeightInfo as pallet_election_provider_multi_phase::WeightInfo >::submit_unsigned(v, t, a, d) } } parameter_types! { pub const SignedFixedDeposit: Balance = 1; pub const SignedDepositIncreaseFactor: Percent = Percent::from_percent(10); } impl pallet_election_provider_multi_phase::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type EstimateCallFee = TransactionPayment; type SignedPhase = SignedPhase; type UnsignedPhase = UnsignedPhase; type BetterSignedThreshold = (); type OffchainRepeat = OffchainRepeat; type MinerTxPriority = MultiPhaseUnsignedPriority; type MinerConfig = Self; type SignedMaxSubmissions = ConstU32<10>; type SignedRewardBase = SignedRewardBase; type SignedDepositBase = GeometricDepositBase; type SignedDepositByte = SignedDepositByte; type SignedMaxRefunds = ConstU32<3>; type SignedDepositWeight = (); type SignedMaxWeight = MinerMaxWeight; type SlashHandler = (); // burn slashes type RewardHandler = (); // nothing to do upon rewards type DataProvider = Staking; type Fallback = onchain::OnChainExecution; type GovernanceFallback = onchain::OnChainExecution; type Solver = SequentialPhragmen, OffchainRandomBalancing>; type ForceOrigin = EnsureRootOrHalfCouncil; type MaxWinners = MaxActiveValidators; type BenchmarkingConfig = ElectionProviderBenchmarkConfig; type ElectionBounds = ElectionBoundsMultiPhase; type WeightInfo = pallet_election_provider_multi_phase::weights::SubstrateWeight; } parameter_types! { pub const BagThresholds: &'static [u64] = &voter_bags::THRESHOLDS; } impl pallet_bags_list::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ScoreProvider = Staking; type WeightInfo = pallet_bags_list::weights::SubstrateWeight; type BagThresholds = BagThresholds; type Score = VoteWeight; } parameter_types! { pub const PostUnbondPoolsWindow: u32 = 4; pub const NominationPoolsPalletId: PalletId = PalletId(*b"py/nopls"); pub const MaxPointsToBalance: u8 = 10; } pub struct BalanceToU256; impl Convert for BalanceToU256 { fn convert(balance: Balance) -> sp_core::U256 { sp_core::U256::from(balance) } } pub struct U256ToBalance; impl Convert for U256ToBalance { fn convert(n: sp_core::U256) -> Balance { n.try_into().unwrap_or(Balance::MAX) } } impl pallet_nomination_pools::Config for Runtime { type WeightInfo = (); type RuntimeEvent = RuntimeEvent; type Currency = Balances; type RewardCounter = FixedU128; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; type PostUnbondingPoolsWindow = PostUnbondPoolsWindow; type MaxMetadataLen = ConstU32<256>; type MaxUnbonding = ConstU32<8>; type PalletId = NominationPoolsPalletId; type MaxPointsToBalance = MaxPointsToBalance; type RuntimeFreezeReason = RuntimeFreezeReason; type AdminOrigin = EnsureRoot; type StakeAdapter = pallet_nomination_pools::adapter::TransferStake; } parameter_types! { pub const ImOnlineUnsignedPriority: TransactionPriority = TransactionPriority::MAX; /// We prioritize im-online heartbeats over election solution submission. pub const StakingUnsignedPriority: TransactionPriority = TransactionPriority::MAX / 2; } impl frame_system::offchain::CreateSignedTransaction for Runtime where RuntimeCall: From, { fn create_transaction>( call: RuntimeCall, public: ::Signer, account: AccountId, nonce: Nonce, ) -> Option<(RuntimeCall, ::SignaturePayload)> { let tip = 0; // take the biggest period possible. let period = BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2); let current_block = System::block_number() .saturated_into::() // The `System::block_number` is initialized with `n+1`, // so the actual block number is `n`. .saturating_sub(1); let era = Era::mortal(period, current_block); let extra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), frame_system::CheckEra::::from(era), frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), frame_metadata_hash_extension::CheckMetadataHash::::new(true), ); let raw_payload = SignedPayload::new(call, extra) .map_err(|e| { log::warn!("Unable to create signed payload: {:?}", e); }) .ok()?; let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?; let address = Indices::unlookup(account); let (call, extra, _) = raw_payload.deconstruct(); Some((call, (address, signature, extra))) } } impl frame_system::offchain::SigningTypes for Runtime { type Public = ::Signer; type Signature = Signature; } impl frame_system::offchain::SendTransactionTypes for Runtime where RuntimeCall: From, { type Extrinsic = UncheckedExtrinsic; type OverarchingCall = RuntimeCall; } parameter_types! { pub const MinVestedTransfer: Balance = 100 * UNIT; pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); } impl pallet_vesting::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type BlockNumberToBalance = ConvertInto; type MinVestedTransfer = MinVestedTransfer; type WeightInfo = pallet_vesting::weights::SubstrateWeight; type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; type BlockNumberProvider = System; // `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the // highest number of schedules that encodes less than 2^10. const MAX_VESTING_SCHEDULES: u32 = 28; } parameter_types! { pub const FinneyApiUrl: &'static str = "http://127.0.0.1:9945"; pub const FinneyUidsStorageKey: &'static str = "0x658faa385070e074c85bf6b568cf0555aab1b4e78e1ea8305462ee53b3686dc84b00"; pub const FinneyDividendsStorageKey: &'static str = "0x658faa385070e074c85bf6b568cf055586752d66f11480ecef37769cdd736b9b4b00"; pub const UidsSubmissionInterval: u32 = 80; } impl pallet_metagraph::Config for Runtime { type RuntimeEvent = RuntimeEvent; type FinneyUrl = FinneyApiUrl; type UidsStorageKey = FinneyUidsStorageKey; type DividendsStorageKey = FinneyDividendsStorageKey; type UidsSubmissionInterval = UidsSubmissionInterval; type AuthorityId = pallet_metagraph::crypto::TestAuthId; } parameter_types! { pub const IpfsBaseUrl: &'static str = "http://127.0.0.1:5001"; pub const GarbageCollectorInterval : u32 = 14; pub const MinerIPFSCHeckInterval : u32 = 5; } // parameter_types! { // pub const MaxStorageRequestsPerBlock: u32 = 10; // pub const PinPinningInterval: u32 = 50; // } // impl ipfs_pallet::Config for Runtime { // type RuntimeEvent = RuntimeEvent; // type IPFSBaseUrl = IpfsBaseUrl; // type GarbageCollectorInterval = GarbageCollectorInterval; // type AuthorityId = ipfs_pallet::crypto::TestAuthId; // type PinPinningInterval = PinPinningInterval; // type MaxOffchainRequestsPerPeriod = MaxOffchainRequestsPerPeriod; // type RequestsClearInterval = RequestsClearInterval; // type EpochPeriod = ConstU64<100>; // } parameter_types! { pub const AlphaPalletId: PalletId = PalletId(*b"Alpha123"); } pub struct GetStakingPotAccount; impl frame_support::traits::Get for GetStakingPotAccount { fn get() -> AccountId { StakingPotId::get().into_account_truncating() } } pub struct StakingActiveEraIndex; impl frame_support::traits::Get for StakingActiveEraIndex { fn get() -> u32 { // No active era only before the first era starts, when no rewards can exist yet pallet_staking::ActiveEra::::get().map(|era| era.index).unwrap_or(0) } } impl pallet_alpha_bridge::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type PalletId = AlphaPalletId; type RewardDestination = GetStakingPotAccount; type ActiveEraIndex = StakingActiveEraIndex; type Currency = Balances; type WeightInfo = pallet_alpha_bridge::weights::SubstrateWeight; } parameter_types! { pub const IpReleasePeriod: u64 = 15 * DAYS; } impl pallet_ip::Config for Runtime { type RuntimeEvent = RuntimeEvent; type IpReleasePeriod = IpReleasePeriod; } impl pallet_calendar::Config for Runtime {} parameter_types! { pub const VersionKeyStorageKey: &'static str = "0x658faa385070e074c85bf6b568cf0555d8cb0c0627a5cd77797c62415dbef9624b00"; pub const BittensorCallSubmission : u32 = 100; pub const DefaultGenesisHash: &'static str = "0x2f0555cc76fc2840a25a6ea3b9637146806f1f44b090c175ffde2a7e5ab36c03"; } impl pallet_bittensor::Config for Runtime { type RuntimeEvent = RuntimeEvent; type FinneyRpcUrl = FinneyApiUrl; type VersionKeyStorageKey = VersionKeyStorageKey; type BittensorCallSubmission = BittensorCallSubmission; type NetUid = ConstU16<75>; type Versionkey = ConstU32<0>; type DefaultSpecVersion = ConstU32<247>; // Your desired default spec version type DefaultGenesisHash = DefaultGenesisHash; } parameter_types! { pub const ResgisterPalletId: PalletId = PalletId(*b"register"); pub const StorageMinerInitialFee: Balance = 100_000_000_000; // 100 tokens pub const StorageMiners3InitialFee: Balance = 100_000_000_000; // 100 tokens pub const ValidatorInitialFee: Balance = 200_000_000_000; // 200 tokens pub const ComputeMinerInitialFee: Balance = 150_000_000_000; // 150 tokens pub const GpuMinerInitialFee: Balance = 150_000_000_000; // 150 tokens pub const ReportRequestsClearInterval : u32 = 1000; } impl pallet_registration::Config for Runtime { type RuntimeEvent = RuntimeEvent; // Use Pallet instead of the crate name type MetagraphInfo = pallet_metagraph::Pallet; type MetricsInfo = pallet_execution_unit::Pallet; // type IpfsInfo = ipfs_pallet::Pallet; type MinerStakeThreshold = ConstU32<0>; type ChainDecimals = ConstU32<18>; type PalletId = ResgisterPalletId; type StorageMinerInitialFee = StorageMinerInitialFee; type ValidatorInitialFee = ValidatorInitialFee; type ComputeMinerInitialFee = ComputeMinerInitialFee; type StorageMiners3InitialFee = StorageMiners3InitialFee; type GpuMinerInitialFee = GpuMinerInitialFee; type BlocksPerDay = BlocksPerDay; type ProxyTypeCompatType = ProxyType; type NodeCooldownPeriod = ConstU64<500>; type MaxDeregRequestsPerPeriod = ConstU32<20>; type ConsensusThreshold = ConsensusThreshold; type ConsensusPeriod = ConsensusPeriod; type EpochDuration = ConstU32<100>; // epoch pin checks clear duration type ReportRequestsClearInterval = ReportRequestsClearInterval; } parameter_types! { pub const BlocksPerDay: u32 = HOURS as u32 * 24; pub const BlocksPerBackupCheck: u32 = 30; } impl pallet_credits::Config for Runtime { type RuntimeEvent = RuntimeEvent; type AuthorityId = pallet_credits::crypto::TestAuthId; type RefferallCoolDOwnPeriod = RefferallCoolDOwnPeriod; } // pallet_container_registry removed — storage cleared in migration RemoveIpAndContainerRegistryPallets parameter_types! { pub const RankingPalletId: PalletId = PalletId(*b"ranking1"); pub const SecondRankingPalletId: PalletId = PalletId(*b"ranking2"); pub const ThirdRankingPalletId: PalletId = PalletId(*b"ranking3"); pub const FourthRankingPalletId: PalletId = PalletId(*b"ranking4"); pub const RankingsInstanceId1: u16 = 1; pub const RankingsInstanceId2: u16 = 2; pub const RankingsInstanceId3: u16 = 3; pub const RankingsInstanceId4: u16 = 4; pub const RankingsInstanceId5: u16 = 5; } // First ranking pallet implementation remains the same impl pallet_rankings::Config for Runtime { type RuntimeEvent = RuntimeEvent; type PalletId = RankingPalletId; type InstanceID = RankingsInstanceId1; type AuthorityId = pallet_rankings::crypto::TestAuthId; type BlocksPerEra = BlocksPerEra; type RewardLockBlocks = BlocksPerEra; type MaxRewardLocksPerAccount = ConstU32<256>; type LocalDefaultSpecVersion = ConstU32<{ VERSION.spec_version }>; type LocalDefaultGenesisHash = LocalDefaultGenesisHash; type LocalRpcUrl = LocalRpcUrl; } // // Add a second ranking pallet implementation impl pallet_rankings::Config for Runtime { type RuntimeEvent = RuntimeEvent; type PalletId = SecondRankingPalletId; type InstanceID = RankingsInstanceId2; type AuthorityId = pallet_rankings::crypto::TestAuthId; type BlocksPerEra = BlocksPerEra; type RewardLockBlocks = BlocksPerEra; type MaxRewardLocksPerAccount = ConstU32<256>; type LocalDefaultSpecVersion = ConstU32<{ VERSION.spec_version }>; type LocalDefaultGenesisHash = LocalDefaultGenesisHash; type LocalRpcUrl = LocalRpcUrl; } // Add a Third ranking pallet implementation impl pallet_rankings::Config for Runtime { type RuntimeEvent = RuntimeEvent; type PalletId = ThirdRankingPalletId; type InstanceID = RankingsInstanceId3; type AuthorityId = pallet_rankings::crypto::TestAuthId; type BlocksPerEra = BlocksPerEra; type RewardLockBlocks = BlocksPerEra; type MaxRewardLocksPerAccount = ConstU32<256>; type LocalDefaultSpecVersion = ConstU32<{ VERSION.spec_version }>; type LocalDefaultGenesisHash = LocalDefaultGenesisHash; type LocalRpcUrl = LocalRpcUrl; } // // Add a Fourth ranking pallet implementation // impl pallet_rankings::Config for Runtime { // type RuntimeEvent = RuntimeEvent; // type PalletId = FourthRankingPalletId; // type InstanceID = RankingsInstanceId4; // type AuthorityId = pallet_rankings::crypto::TestAuthId; // type BlocksPerEra = BlocksPerEra; // } // // Add a Fourth ranking pallet implementation // impl pallet_rankings::Config for Runtime { // type RuntimeEvent = RuntimeEvent; // type PalletId = FourthRankingPalletId; // type InstanceID = RankingsInstanceId5; // type AuthorityId = pallet_rankings::crypto::TestAuthId; // type BlocksPerEra = BlocksPerEra; // } parameter_types! { pub const LocalRpcUrl: &'static str = "http://localhost:9944"; pub const IpfsPinRpcMethod: &'static str = "extra_peerId"; } impl pallet_utils::Config for Runtime { type RuntimeEvent = RuntimeEvent; type LocalRpcUrl = LocalRpcUrl; type RpcMethod = IpfsPinRpcMethod; } impl pallet_account_profile::Config for Runtime { type RuntimeEvent = RuntimeEvent; } parameter_types! { pub const CooldownPeriodInBlocks: u32 = 20; } // impl pallet_notifications::Config for Runtime { // type RuntimeEvent = RuntimeEvent; // type CooldownPeriod = CooldownPeriodInBlocks; // } parameter_types! { pub const ExecutionUnitRpcUrl: &'static str = "http://localhost:9944"; pub const ExecutionUnitSystemInfoRpcMethod: &'static str = "sys_getSystemInfo"; pub const BlockTimeSecs :u32 = SECONDS_PER_BLOCK as u32; /// number of blocks at which uptime will be checked pub const BlockCheckInterval : u32 = 300; pub const GetReadProofRpcMethod: &'static str = "state_getReadProof"; pub const SystemHealthRpcMethod: &'static str = "system_health"; pub const IPFSBaseUrl: &'static str = "http://localhost:5001"; pub const UnregistrationBuffer : u32 = 60; pub const MaxOffchainRequestsPerPeriod: u32 = 150; pub const RequestsClearInterval: u32 = 10; pub const MaxOffchainHardwareSubmitRequestsPerPeriod: u32 = 1; pub const IpfsServiceUrl: &'static str = "http://localhost:3000"; pub const LocalDefaultGenesisHash: &'static str = "0x28a6b54823f786c5dd8520ef7bdb0ee2639173815bfbb7719bcf58ef9eb5e1f9"; pub const ConsensusPeriod: BlockNumber = 10; pub const ConsensusThreshold: u32 = 2; // pub const EpochDuration: u32 = 10; } impl pallet_execution_unit::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_execution_unit::weights::SubstrateWeight; type LocalRpcUrl = ExecutionUnitRpcUrl; type SystemInfoRpcMethod = ExecutionUnitSystemInfoRpcMethod; type BlockTime = BlockTimeSecs; type BlockCheckInterval = BlockCheckInterval; type GetReadProofRpcMethod = GetReadProofRpcMethod; type SystemHealthRpcMethod = SystemHealthRpcMethod; type AuthorityId = pallet_execution_unit::crypto::TestAuthId; type UnregistrationBuffer = UnregistrationBuffer; type MaxOffchainRequestsPerPeriod = MaxOffchainRequestsPerPeriod; type RequestsClearInterval = RequestsClearInterval; type IpfsServiceUrl = IpfsServiceUrl; type MaxOffchainHardwareSubmitRequestsPerPeriod = MaxOffchainHardwareSubmitRequestsPerPeriod; type HardwareSubmitRequestsClearInterval = BlockCheckInterval; type LocalDefaultSpecVersion = ConstU32<{ VERSION.spec_version }>; type LocalDefaultGenesisHash = LocalDefaultGenesisHash; type ConsensusPeriod = ConsensusPeriod; type ConsensusThreshold = ConsensusThreshold; type ConsensusSimilarityThreshold = ConstU32<85>; type EpochDuration = ConstU32<100>; // epoch pin checks clear duration type ReputationUpdateInterval = ConstU32<15>; } impl pallet_offences::Config for Runtime { type RuntimeEvent = RuntimeEvent; type IdentificationTuple = pallet_session::historical::IdentificationTuple; type OnOffenceHandler = Staking; } parameter_types! { pub const CandidacyBond: Balance = CANDIDACY_BOND; // 1 storage item created, key size is 32 bytes, value size is 16+16. pub const VotingBondBase: Balance = deposit(1, 64); // additional data per vote is 32 bytes (account id). pub const VotingBondFactor: Balance = deposit(0, 32); pub const TermDuration: BlockNumber = TERM_DURATION; pub const DesiredMembers: u32 = DESIRED_MEMBERS; pub const DesiredRunnersUp: u32 = DESIRED_RUNNERS_UP; pub const MaxCandidates: u32 = MAX_CANDIDATES; pub const MaxVoters: u32 = MAX_VOTERS; pub const ElectionsPhragmenPalletId: LockIdentifier = ELECTIONS_PHRAGMEN_PALLET_ID; } // Make sure that there are no more than `MaxMembers` members elected via // elections-phragmen. const_assert!(DesiredMembers::get() <= CouncilMaxMembers::get()); impl pallet_elections_phragmen::Config for Runtime { type CandidacyBond = CandidacyBond; type ChangeMembers = Council; type Currency = Balances; type CurrencyToVote = U128CurrencyToVote; type DesiredMembers = DesiredMembers; type DesiredRunnersUp = DesiredRunnersUp; type RuntimeEvent = RuntimeEvent; type MaxVotesPerVoter = ConstU32<100>; // NOTE: this implies that council's genesis members cannot be set directly and // must come from this module. type InitializeMembers = Council; type KickedMember = (); type LoserCandidate = (); type PalletId = ElectionsPhragmenPalletId; type TermDuration = TermDuration; type MaxCandidates = MaxCandidates; type MaxVoters = MaxVoters; type VotingBondBase = VotingBondBase; type VotingBondFactor = VotingBondFactor; type WeightInfo = pallet_elections_phragmen::weights::SubstrateWeight; } parameter_types! { pub const ProposalBond: Permill = PROPOSAL_BOND; pub const ProposalBondMinimum: Balance = PROPOSAL_BOND_MINIMUM; pub const SpendPeriod: BlockNumber = SPEND_PERIOD; pub const Burn: Permill = BURN; pub const TipCountdown: BlockNumber = TIP_COUNTDOWN; pub const TipFindersFee: Percent = TIP_FINDERS_FEE; pub const TipReportDepositBase: Balance = TIP_REPORT_DEPOSIT_BASE; pub const DataDepositPerByte: Balance = DATA_DEPOSIT_PER_BYTE; pub const TreasuryPalletId: PalletId = TREASURY_PALLET_ID; pub const MaximumReasonLength: u32 = MAXIMUM_REASON_LENGTH; pub const MaxApprovals: u32 = MAX_APPROVALS; pub TreasuryAccount: AccountId = Treasury::account_id(); pub PayoutPeriod: u64 = 10; } impl pallet_treasury::Config for Runtime { type PalletId = TreasuryPalletId; type Currency = Balances; type RejectOrigin = EitherOfDiverse< EnsureRoot, pallet_collective::EnsureProportionMoreThan, >; type RuntimeEvent = RuntimeEvent; type AssetKind = (); type Beneficiary = AccountId; type BeneficiaryLookup = IdentityLookup; type Paymaster = PayFromAccount; type BalanceConverter = UnityAssetBalanceConversion; type PayoutPeriod = PayoutPeriod; type SpendPeriod = SpendPeriod; type Burn = Burn; type BurnDestination = (); type SpendOrigin = frame_support::traits::NeverEnsureOrigin; type SpendFunds = Bounties; type WeightInfo = pallet_treasury::weights::SubstrateWeight; type MaxApprovals = MaxApprovals; } parameter_types! { pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); pub const BountyValueMinimum: Balance = 5 * UNIT; pub const BountyDepositBase: Balance = UNIT; pub const CuratorDepositMultiplier: Permill = Permill::from_percent(50); pub const CuratorDepositMin: Balance = UNIT; pub const CuratorDepositMax: Balance = 100 * UNIT; pub const BountyDepositPayoutDelay: BlockNumber = DAYS; pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS; } impl pallet_bounties::Config for Runtime { type RuntimeEvent = RuntimeEvent; type BountyDepositBase = BountyDepositBase; type BountyDepositPayoutDelay = BountyDepositPayoutDelay; type BountyUpdatePeriod = BountyUpdatePeriod; type CuratorDepositMultiplier = CuratorDepositMultiplier; type CuratorDepositMin = CuratorDepositMin; type CuratorDepositMax = CuratorDepositMax; type BountyValueMinimum = BountyValueMinimum; type DataDepositPerByte = DataDepositPerByte; type MaximumReasonLength = MaximumReasonLength; type WeightInfo = pallet_bounties::weights::SubstrateWeight; type OnSlash = Treasury; type ChildBountyManager = ChildBounties; } parameter_types! { pub const ChildBountyValueMinimum: Balance = UNIT; } impl pallet_child_bounties::Config for Runtime { type RuntimeEvent = RuntimeEvent; type MaxActiveChildBountyCount = ConstU32<5>; type ChildBountyValueMinimum = ChildBountyValueMinimum; type WeightInfo = pallet_child_bounties::weights::SubstrateWeight; } // parameter_types! { // pub const SubAccountStringLimit: u32 = 300; // pub const MaxSubAccountsLimit: u32 = 50; // } // impl pallet_subaccount::Config for Runtime { // type RuntimeEvent = RuntimeEvent; // type WeightInfo = pallet_subaccount::weights::SubstrateWeight; // type StringLimit = SubAccountStringLimit; // type MaxSubAccountsLimit = MaxSubAccountsLimit; // type ExistentialDeposit = ExistentialDeposit; // type Currency = Balances; // // type OnRuntimeUpgrade = pallet_subaccount::migrations::MigrateToNewStorageFormat; // } parameter_types! { pub const MaxKeys: u32 = 10_000; pub const MaxPeerInHeartbeats: u32 = 10_000; } impl pallet_im_online::Config for Runtime { type AuthorityId = ImOnlineId; type RuntimeEvent = RuntimeEvent; type NextSessionRotation = Babe; type ValidatorSet = Historical; type ReportUnresponsiveness = Offences; type UnsignedPriority = ImOnlineUnsignedPriority; type WeightInfo = pallet_im_online::weights::SubstrateWeight; type MaxKeys = MaxKeys; type MaxPeerInHeartbeats = MaxPeerInHeartbeats; } /// Calls that cannot be paused by the tx-pause pallet. pub struct TxPauseWhitelistedCalls; /// Whitelist `Balances::transfer_keep_alive`, all others are pauseable. impl Contains> for TxPauseWhitelistedCalls { fn contains(full_name: &RuntimeCallNameOf) -> bool { matches!( (full_name.0.as_slice(), full_name.1.as_slice()), (b"Balances", b"transfer_keep_alive") ) } } impl pallet_tx_pause::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type PauseOrigin = EnsureRoot; type UnpauseOrigin = EnsureRoot; type WhitelistedCalls = TxPauseWhitelistedCalls; type MaxNameLen = ConstU32<256>; type WeightInfo = pallet_tx_pause::weights::SubstrateWeight; } parameter_types! { pub const BasicDeposit: Balance = deposit(0, 100); pub const ByteDeposit: Balance = deposit(0, 100); pub const SubAccountDeposit: Balance = deposit(1, 1); pub const MaxSubAccounts: u32 = 100; #[derive(Serialize, Deserialize)] pub const MaxAdditionalFields: u32 = 100; pub const MaxRegistrars: u32 = 20; pub const PendingUsernameExpiration: u64 = 7 * DAYS; } impl pallet_identity::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type BasicDeposit = BasicDeposit; type SubAccountDeposit = SubAccountDeposit; type MaxSubAccounts = MaxSubAccounts; type MaxRegistrars = MaxRegistrars; type Slashed = Treasury; type ByteDeposit = ByteDeposit; type IdentityInformation = pallet_identity::legacy::IdentityInfo; type OffchainSignature = Signature; type SigningPublicKey = ::Signer; type UsernameAuthorityOrigin = EnsureRoot; type PendingUsernameExpiration = PendingUsernameExpiration; type MaxSuffixLength = ConstU32<7>; type MaxUsernameLength = ConstU32<32>; type ForceOrigin = EnsureRoot; type RegistrarOrigin = EnsureRoot; type WeightInfo = (); } impl pallet_utility::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type PalletsOrigin = OriginCaller; type WeightInfo = (); } parameter_types! { // One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes. pub const DepositBase: Balance = deposit(1, 88); // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); } impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; type DepositBase = DepositBase; type DepositFactor = DepositFactor; type MaxSignatories = ConstU32<100>; type WeightInfo = pallet_multisig::weights::SubstrateWeight; } parameter_types! { // Set all deposits to zero for feeless transactions pub const ProxyDepositBase: Balance = deposit(0, 0); pub const ProxyDepositFactor: Balance = deposit(0, 0); pub const AnnouncementDepositBase: Balance = deposit(0, 0); pub const AnnouncementDepositFactor: Balance = deposit(0, 0); } /// The type used to represent the kinds of proxying allowed. #[derive( Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, MaxEncodedLen, scale_info::TypeInfo, )] pub enum ProxyType { Any, NonTransfer, Governance, Staking, } impl Default for ProxyType { fn default() -> Self { Self::Any } } impl InstanceFilter for ProxyType { fn filter(&self, c: &RuntimeCall) -> bool { match self { ProxyType::Any => true, ProxyType::NonTransfer => !matches!( c, RuntimeCall::Balances(..) | RuntimeCall::Vesting(pallet_vesting::Call::vested_transfer { .. }) // NonTransfer proxies must not be able to drain the principal via // credit purchases or hAlpha withdrawals. | RuntimeCall::Marketplace(pallet_marketplace::Call::purchase_plan { .. }) // A plan upgrade consumes credits for the net delta, same drain — // on either storage slot. | RuntimeCall::Marketplace( pallet_marketplace::Call::change_storage_plan { .. } ) | RuntimeCall::Marketplace(pallet_marketplace::Call::change_s3_plan { .. }) | RuntimeCall::AlphaBridge(pallet_alpha_bridge::Call::withdraw { .. }) ), ProxyType::Governance => matches!( c, RuntimeCall::Democracy(..) | RuntimeCall::Council(..) | RuntimeCall::Elections(..) | RuntimeCall::Treasury(..) ), ProxyType::Staking => { matches!(c, RuntimeCall::Staking(..)) }, } } fn is_superset(&self, o: &Self) -> bool { match (self, o) { (x, y) if x == y => true, (ProxyType::Any, _) => true, (_, ProxyType::Any) => false, (ProxyType::NonTransfer, _) => true, _ => false, } } } impl pallet_proxy::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; type ProxyType = ProxyType; type ProxyDepositBase = ProxyDepositBase; type ProxyDepositFactor = ProxyDepositFactor; type MaxProxies = ConstU32<32>; type WeightInfo = pallet_proxy::weights::SubstrateWeight; type MaxPending = ConstU32<32>; type CallHasher = BlakeTwo256; type AnnouncementDepositBase = AnnouncementDepositBase; type AnnouncementDepositFactor = AnnouncementDepositFactor; type ExistentialDeposit = ExistentialDeposit; } // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime { System: frame_system = 1, Timestamp: pallet_timestamp = 2, Sudo: pallet_sudo = 3, RandomnessCollectiveFlip: pallet_randomness_collective_flip = 4, Assets: pallet_assets = 5, Balances: pallet_balances = 6, TransactionPayment: pallet_transaction_payment = 7, Authorship: pallet_authorship = 8, Babe: pallet_babe = 9, Grandpa: pallet_grandpa = 10, Indices: pallet_indices = 11, Democracy: pallet_democracy = 12, Council: pallet_collective:: = 13, Vesting: pallet_vesting = 14, Elections: pallet_elections_phragmen = 15, ElectionProviderMultiPhase: pallet_election_provider_multi_phase = 16, Staking: pallet_staking = 17, Session: pallet_session = 18, Historical: pallet_session_historical = 19, Treasury: pallet_treasury = 20, Bounties: pallet_bounties = 21, ChildBounties: pallet_child_bounties = 22, BagsList: pallet_bags_list = 23, NominationPools: pallet_nomination_pools = 24, Scheduler: pallet_scheduler = 25, Preimage: pallet_preimage = 26, Offences: pallet_offences = 27, TxPause: pallet_tx_pause = 28, ImOnline: pallet_im_online = 29, Identity: pallet_identity = 30, Utility: pallet_utility = 31, Multisig: pallet_multisig = 32, Ethereum: pallet_ethereum = 33, EVM: pallet_evm = 34, EVMChainId: pallet_evm_chain_id = 35, DynamicFee: pallet_dynamic_fee = 36, BaseFee: pallet_base_fee = 37, HotfixSufficients: pallet_hotfix_sufficients = 38, Proxy: pallet_proxy = 44, Registration : pallet_registration=53, ExecutionUnit : pallet_execution_unit=54, Metagraph : pallet_metagraph=55, Marketplace: pallet_marketplace = 56, Bittensor: pallet_bittensor = 57, // SubAccount: pallet_subaccount= 58, // Notifications: pallet_notifications = 59, AccountProfile: pallet_account_profile = 60, Utils: pallet_utils = 62, RankingStorage: pallet_rankings =63, RankingCompute: pallet_rankings:: = 68, RankingValidators: pallet_rankings:: = 70, // RankingGpu: pallet_rankings:: = 71, // RankingS3: pallet_rankings:: = 77, Credits: pallet_credits = 65, // ContainerRegistry: pallet_container_registry = 69, AlphaBridge: pallet_alpha_bridge = 73, PalletIp: pallet_ip = 74, // IpfsPallet: ipfs_pallet = 75, Arion: pallet_arion = 76, PalletCalendar: pallet_calendar = 78, ComputeScoring: pallet_compute_scoring = 79, Hippocampus: pallet_hippocampus = 80, } ); #[derive(Clone, Serialize, Deserialize)] pub struct TransactionConverter; impl fp_rpc::ConvertTransaction for TransactionConverter { fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic { UncheckedExtrinsic::new_unsigned( pallet_ethereum::Call::::transact { transaction }.into(), ) } } impl fp_rpc::ConvertTransaction for TransactionConverter { fn convert_transaction( &self, transaction: pallet_ethereum::Transaction, ) -> opaque::UncheckedExtrinsic { let extrinsic = UncheckedExtrinsic::new_unsigned( pallet_ethereum::Call::::transact { transaction }.into(), ); let encoded = extrinsic.encode(); opaque::UncheckedExtrinsic::decode(&mut &encoded[..]) .expect("Encoded extrinsic is always valid") } } type Migrations = (migrations::ActivateMinerPaymentBank,); /// Block type as expected by this runtime. pub type Block = generic::Block; /// A Block signed with a Justification pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, frame_system::CheckGenesis, frame_system::CheckEra, frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, frame_metadata_hash_extension::CheckMetadataHash, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = fp_self_contained::UncheckedExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic; /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, Block, frame_system::ChainContext, Runtime, AllPalletsWithSystem, Migrations, >; impl fp_self_contained::SelfContainedCall for RuntimeCall { type SignedInfo = H160; fn is_self_contained(&self) -> bool { match self { RuntimeCall::Ethereum(call) => call.is_self_contained(), _ => false, } } fn check_self_contained(&self) -> Option> { match self { RuntimeCall::Ethereum(call) => call.check_self_contained(), _ => None, } } fn validate_self_contained( &self, info: &Self::SignedInfo, dispatch_info: &DispatchInfoOf, len: usize, ) -> Option { match self { RuntimeCall::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len), _ => None, } } fn pre_dispatch_self_contained( &self, info: &Self::SignedInfo, dispatch_info: &DispatchInfoOf, len: usize, ) -> Option> { match self { RuntimeCall::Ethereum(call) => { call.pre_dispatch_self_contained(info, dispatch_info, len) }, _ => None, } } fn apply_self_contained( self, info: Self::SignedInfo, ) -> Option>> { match self { call @ RuntimeCall::Ethereum(pallet_ethereum::Call::transact { .. }) => { Some(call.dispatch(RuntimeOrigin::from( pallet_ethereum::RawOrigin::EthereumTransaction(info), ))) }, _ => None, } } } parameter_types! { pub const AssetDeposit: Balance = 10 * UNIT; pub const AssetAccountDeposit: Balance = DOLLAR; pub const ApprovalDeposit: Balance = ExistentialDeposit::get() as u128; pub const AssetsStringLimit: u32 = 50; pub const MetadataDepositBase: Balance = deposit(1, 68); pub const MetadataDepositPerByte: Balance = deposit(0, 1); } #[cfg(not(feature = "runtime-benchmarks"))] pub type AssetId = u128; #[cfg(feature = "runtime-benchmarks")] pub type AssetId = u32; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type AssetId = AssetId; type AssetIdParameter = parity_scale_codec::Compact; type Currency = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = frame_system::EnsureRoot; type AssetDeposit = AssetDeposit; type AssetAccountDeposit = AssetAccountDeposit; type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; type ApprovalDeposit = ApprovalDeposit; type StringLimit = AssetsStringLimit; type RemoveItemsLimit = ConstU32<1000>; type Freezer = (); type Extra = (); type CallbackHandle = (); type WeightInfo = pallet_assets::weights::SubstrateWeight; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); } // parameter_types! { // pub const SygmaAccessSegregatorPalletIndex: u8 = 90; // pub const SygmaBasicFeeHandlerPalletIndex: u8 = 91; // pub const SygmaFeeHandlerRouterPalletIndex: u8 = 92; // pub const SygmaPercentageFeeHandlerRouterPalletIndex: u8 = 93; // pub const SygmaBridgePalletIndex: u8 = 94; // } // pub struct SygmaAdminMembers; // impl SortedMembers for SygmaAdminMembers { // fn sorted_members() -> Vec { // [SygmaBridgeAdminAccount::get()].to_vec() // } // } // impl sygma_bridge::Config for Runtime { // type RuntimeEvent = RuntimeEvent; // type TransferReserveAccounts = BridgeAccounts; // type FeeReserveAccount = SygmaBridgeFeeAccount; // type EIP712ChainID = EIP712ChainID; // type DestVerifyingContractAddress = DestVerifyingContractAddress; // type FeeHandler = SygmaFeeHandlerRouter; // type AssetTransactor = (CurrencyTransactor, FungiblesTransactor); // type ResourcePairs = ResourcePairs; // type IsReserve = ReserveChecker; // type ExtractDestData = DestinationDataParser; // type PalletId = SygmaBridgePalletId; // type PalletIndex = SygmaBridgePalletIndex; // type DecimalConverter = SygmaDecimalConverter; // type WeightInfo = sygma_bridge::weights::SygmaWeightInfo; // } // pub type LocationToAccountId = ( // // The parent (Relay-chain) origin converts to the parent `AccountId`. // ParentIsPreset, // // Sibling parachain origins convert to AccountId via the `ParaId::into`. // SiblingParachainConvertsVia, // // Straight up local `AccountId32` origins just alias directly to `AccountId`. // AccountId32Aliases, // ); // #[allow(deprecated)] // pub type CurrencyTransactor = XcmCurrencyAdapter< // // Use this currency: // Balances, // // Use this currency when it is a fungible asset matching the given location or name: // IsConcrete, // // Convert an XCM Location into a local account id: // LocationToAccountId, // // Our chain's account ID type (we can't get away without mentioning it explicitly): // AccountId32, // // We don't track any teleports of `Balances`. // (), // >; // /// Means for transacting assets besides the native currency on this chain. // pub type FungiblesTransactor = FungiblesAdapter< // // Use this fungibles implementation: // Assets, // // Use this currency when it is a fungible asset matching the given location or name: // SimpleForeignAssetConverter, // // Convert an XCM Location into a local account id: // LocationToAccountId, // // Our chain's account ID type (we can't get away without mentioning it explicitly): // AccountId32, // // Disable teleport. // NoChecking, // // The account to use for tracking teleports. // CheckingAccount, // >; // pub struct SimpleForeignAssetConverter(PhantomData<()>); // impl MatchesFungibles for SimpleForeignAssetConverter { // fn matches_fungibles(a: &Asset) -> result::Result<(AssetId, Balance), ExecutionError> { // match (&a.fun, &a.id) { // (Fungible(ref amount), AssetId(ref id)) => { // if id == &SygUSDLocation::get() { // Ok((SygUSDAssetId::get(), *amount)) // } else if id == &PHALocation::get() { // Ok((PHAAssetId::get(), *amount)) // } else { // Err(ExecutionError::AssetNotHandled) // } // }, // _ => Err(ExecutionError::AssetNotHandled), // } // } // } // impl sygma_access_segregator::Config for Runtime { // type RuntimeEvent = RuntimeEvent; // type BridgeCommitteeOrigin = EnsureSignedBy; // type PalletIndex = SygmaAccessSegregatorPalletIndex; // type Extrinsics = RegisteredExtrinsics; // type WeightInfo = sygma_access_segregator::weights::SygmaWeightInfo; // } // impl sygma_basic_feehandler::Config for Runtime { // type RuntimeEvent = RuntimeEvent; // type PalletIndex = SygmaBasicFeeHandlerPalletIndex; // type WeightInfo = sygma_basic_feehandler::weights::SygmaWeightInfo; // } // impl sygma_fee_handler_router::Config for Runtime { // type RuntimeEvent = RuntimeEvent; // type BasicFeeHandler = SygmaBasicFeeHandler; // type DynamicFeeHandler = (); // type PercentageFeeHandler = SygmaPercentageFeeHandler; // type PalletIndex = SygmaFeeHandlerRouterPalletIndex; // type WeightInfo = sygma_fee_handler_router::weights::SygmaWeightInfo; // } // impl sygma_percentage_feehandler::Config for Runtime { // type RuntimeEvent = RuntimeEvent; // type PalletIndex = SygmaPercentageFeeHandlerRouterPalletIndex; // type WeightInfo = sygma_percentage_feehandler::weights::SygmaWeightInfo; // } // parameter_types! { // // hAlpha: native asset is always a reserved asset // pub NativeLocation: Location = Location::here(); // pub NativeSygmaResourceId: [u8; 32] = hex_literal::hex!("0000000000000000000000000000000000000000000000000000000000002000"); // // SygUSD: a non-reserved asset // pub SygUSDLocation: Location = Location::new( // 1, // [ // Parachain(1000), // slice_to_generalkey(b"sygma"), // slice_to_generalkey(b"sygusd"), // ], // ); // // SygUSDAssetId is the substrate assetID of SygUSD // pub SygUSDAssetId: AssetId = 2000; // // SygUSDResourceId is the resourceID that mapping with the foreign asset SygUSD // pub SygUSDResourceId: ResourceId = hex_literal::hex!("0000000000000000000000000000000000000000000000000000000000001100"); // // PHA: a reserved asset // pub PHALocation: Location = Location::new( // 1, // [ // Parachain(2004), // slice_to_generalkey(b"sygma"), // slice_to_generalkey(b"pha"), // ], // ); // // PHAAssetId is the substrate assetID of PHA // pub PHAAssetId: AssetId = 2001; // // PHAResourceId is the resourceID that mapping with the foreign asset PHA // pub PHAResourceId: ResourceId = hex_literal::hex!("0000000000000000000000000000000000000000000000000000000000001000"); // } // fn bridge_accounts_generator() -> BTreeMap { // let mut account_map: BTreeMap = BTreeMap::new(); // account_map.insert(NativeLocation::get().into(), BridgeAccountNative::get()); // account_map.insert(SygUSDLocation::get().into(), BridgeAccountOtherToken::get()); // account_map.insert(PHALocation::get().into(), BridgeAccountOtherToken::get()); // account_map // } // const DEST_VERIFYING_CONTRACT_ADDRESS: &str = "6CdE2Cd82a4F8B74693Ff5e194c19CA08c2d1c68"; // parameter_types! { // // RegisteredExtrinsics here registers all valid (pallet index, extrinsic_name) paris // // make sure to update this when adding new access control extrinsic // pub RegisteredExtrinsics: Vec<(u8, Vec)> = [ // (SygmaAccessSegregatorPalletIndex::get(), b"grant_access".to_vec()), // (SygmaBasicFeeHandlerPalletIndex::get(), b"set_fee".to_vec()), // (SygmaBridgePalletIndex::get(), b"set_mpc_address".to_vec()), // (SygmaBridgePalletIndex::get(), b"pause_bridge".to_vec()), // (SygmaBridgePalletIndex::get(), b"unpause_bridge".to_vec()), // (SygmaBridgePalletIndex::get(), b"register_domain".to_vec()), // (SygmaBridgePalletIndex::get(), b"unregister_domain".to_vec()), // (SygmaBridgePalletIndex::get(), b"retry".to_vec()), // (SygmaFeeHandlerRouterPalletIndex::get(), b"set_fee_handler".to_vec()), // (SygmaPercentageFeeHandlerRouterPalletIndex::get(), b"set_fee_rate".to_vec()), // ].to_vec(); // pub const SygmaBridgePalletId: PalletId = PalletId(*b"sygma/01"); // // Hippius mainnet super admin: 5D2hZnw8Z7kg5LpQiEBb6HPG4V51wYXuKhE7sVhXiUPWj8D1 // pub SygmaBridgeAdminAccountKey: [u8; 32] = hex_literal::hex!("2ab4c35efb6ab82377c2325467103cf46742d288ae1f8917f1d5960f4a1e9065"); // pub SygmaBridgeAdminAccount: AccountId = SygmaBridgeAdminAccountKey::get().into(); // // SygmaBridgeFeeAccount is a substrate account and used for bridging fee collection // // SygmaBridgeFeeAccount address: 5ELLU7ibt5ZrNEYRwohtaRBDBa3TzcWwwPELBPSWWd2mbgv3 // pub SygmaBridgeFeeAccount: AccountId32 = AccountId32::new([100u8; 32]); // // BridgeAccountNative: 5EYCAe5jLbHcAAMKvLFSXgCTbPrLgBJusvPwfKcaKzuf5X5e // pub BridgeAccountNative: AccountId32 = SygmaBridgePalletId::get().into_account_truncating(); // // BridgeAccountOtherToken 5EYCAe5jLbHcAAMKvLFiGhk3htXY8jQncbLTDGJQnpnPMAVp // pub BridgeAccountOtherToken: AccountId32 = SygmaBridgePalletId::get().into_sub_account_truncating(1u32); // // BridgeAccounts is a list of accounts for holding transferred asset collection // pub BridgeAccounts: BTreeMap = bridge_accounts_generator(); // // EIP712ChainID is the chainID that pallet is assigned with, used in EIP712 typed data domain // // For local testing with ./scripts/sygma-setup/execute_proposal_test.js, please change it to 5 // pub EIP712ChainID: ChainID = U256::from(3799); // // DestVerifyingContractAddress is a H160 address that is used in proposal signature verification, specifically EIP712 typed data // // When relayers signing, this address will be included in the EIP712Domain // // As long as the relayer and pallet configured with the same address, EIP712Domain should be recognized properly. // pub DestVerifyingContractAddress: VerifyingContractAddress = primitive_types::H160::from_slice(hex::decode(DEST_VERIFYING_CONTRACT_ADDRESS).ok().unwrap().as_slice()); // pub CheckingAccount: AccountId32 = AccountId32::new([102u8; 32]); // pub RelayNetwork: NetworkId = NetworkId::Polkadot; // // ResourcePairs is where all supported assets and their associated resourceID are binding // pub ResourcePairs: Vec<(XcmAssetId, ResourceId)> = vec![ // (NativeLocation::get().into(), NativeSygmaResourceId::get()), // (SygUSDLocation::get().into(), SygUSDResourceId::get()), // (PHALocation::get().into(), PHAResourceId::get()), // ]; // pub AssetDecimalPairs: Vec<(XcmAssetId, u8)> = vec![(NativeLocation::get().into(), 18u8), (SygUSDLocation::get().into(), 6u8), (PHALocation::get().into(), 12u8)]; // } // pub struct ReserveChecker; // impl ContainsPair for ReserveChecker { // fn contains(asset: &Asset, origin: &Location) -> bool { // if let Some(ref id) = ConcrateSygmaAsset::origin(asset) { // if id == origin { // return true; // } // } // false // } // } // pub struct ConcrateSygmaAsset; // impl ConcrateSygmaAsset { // pub fn id(asset: &Asset) -> Option { // match (&asset.id, &asset.fun) { // (AssetId(ref id), Fungible(_)) => Some(id.clone()), // _ => None, // } // } // pub fn origin(asset: &Asset) -> Option { // Self::id(asset).and_then(|id| { // match (id.parents, id.first_interior()) { // // Sibling parachain // (1, Some(Parachain(id))) => { // // Assume current parachain id is 1000, for production, always get proper // // parachain info // if *id == 1000 { // Some(Location::new(0, X1(Arc::new([slice_to_generalkey(b"sygma")])))) // } else { // Some(Location::here()) // } // }, // (1, _) => Some(Location::here()), // // Children parachain // (0, Some(Parachain(id))) => Some(Location::new(0, X1(Arc::new([Parachain(*id)])))), // // Local: (0, Here) // (0, None) => Some(id), // _ => None, // } // }) // } // } // pub struct DestinationDataParser; // /// Extract dest to be recipient and Dest DomainID // /// if dest chain is substrate chain, recipient must be a encoded MultiLocation // /// if dest chain is non-substrate chain, recipient is [u8; 32] // impl ExtractDestinationData for crate::DestinationDataParser { // fn extract_dest(dest: &Location) -> Option<(Vec, DomainID)> { // match (dest.parents, dest.interior.clone()) { // // final dest is on the remote substrate chain // (1, X4(xs)) => { // let [a, b, c, d] = *xs; // match (a, b, c, d) { // ( // GeneralKey { length: path_len, data: sygma_path }, // GeneralIndex(dest_domain_id), // Parachain(parachain_id), // Junction::AccountId32 { network: None, id: recipient }, // ) => { // if sygma_path[..path_len as usize] == [0x73, 0x79, 0x67, 0x6d, 0x61] { // return TryInto::::try_into(dest_domain_id).ok().map( // |domain_id| { // let l: Location = Location::new( // 1, // Junctions::X2(Arc::new([ // Parachain(parachain_id), // Junction::AccountId32 { network: None, id: recipient }, // ])), // ); // (l.encode(), domain_id) // }, // ); // } // None // }, // _ => None, // } // }, // (0, X3(xs)) => { // let [a, b, c] = *xs; // match (a, b, c) { // // final dest is on the local substrate chain // ( // GeneralKey { length: path_len, data: sygma_path }, // GeneralIndex(dest_domain_id), // Junction::AccountId32 { network: None, id: recipient }, // ) => { // if sygma_path[..path_len as usize] == [0x73, 0x79, 0x67, 0x6d, 0x61] { // return TryInto::::try_into(dest_domain_id).ok().map( // |domain_id| { // let l: Location = Location::new( // 0, // Junctions::X1(Arc::new([Junction::AccountId32 { // network: None, // id: recipient, // }])), // ); // (l.encode(), domain_id) // }, // ); // } // None // }, // // final dest is on the non-substrate chain such as EVM // ( // GeneralKey { length: path_len, data: sygma_path }, // GeneralIndex(dest_domain_id), // GeneralKey { length: recipient_len, data: recipient }, // ) => { // if sygma_path[..path_len as usize] == [0x73, 0x79, 0x67, 0x6d, 0x61] { // return TryInto::::try_into(dest_domain_id).ok().map( // |domain_id| { // (recipient[..recipient_len as usize].to_vec(), domain_id) // }, // ); // } // None // }, // _ => None, // } // }, // _ => None, // } // } // } // pub struct SygmaDecimalConverter(PhantomData); // impl>> DecimalConverter // for SygmaDecimalConverter // { // fn convert_to(asset: &Asset) -> Option { // match (&asset.fun, &asset.id) { // (Fungible(amount), _) => { // for (asset_id, decimal) in DecimalPairs::get().iter() { // if *asset_id == asset.id { // return if *decimal == 18 { // Some(*amount) // } else { // type U112F16 = DecimalFixedU128; // if *decimal > 18 { // let a = // U112F16::from_num(10u128.saturating_pow(*decimal as u32 - 18)); // let b = U112F16::from_num(*amount).checked_div(a); // let r: u128 = b.unwrap_or_else(|| U112F16::from_num(0)).to_num(); // if r == 0 { // return None; // } // Some(r) // } else { // // Max is 5192296858534827628530496329220095 // // if source asset decimal is 12, the max amount sending to sygma // // relayer is 5192296858534827.628530496329 // if *amount > U112F16::MAX { // return None; // } // let a = // U112F16::from_num(10u128.saturating_pow(18 - *decimal as u32)); // let b = U112F16::from_num(*amount).saturating_mul(a); // Some(b.to_num()) // } // }; // } // } // None // }, // _ => None, // } // } // fn convert_from(asset: &Asset) -> Option { // match (&asset.fun, &asset.id) { // (Fungible(amount), _) => { // for (asset_id, decimal) in DecimalPairs::get().iter() { // if *asset_id == asset.id { // return if *decimal == 18 { // Some((asset.id.clone(), *amount).into()) // } else { // type U112F16 = DecimalFixedU128; // if *decimal > 18 { // // Max is 5192296858534827628530496329220095 // // if dest asset decimal is 24, the max amount coming from sygma // // relayer is 5192296858.534827628530496329 // if *amount > U112F16::MAX { // return None; // } // let a = // U112F16::from_num(10u128.saturating_pow(*decimal as u32 - 18)); // let b = U112F16::from_num(*amount).saturating_mul(a); // let r: u128 = b.to_num(); // Some((asset.id.clone(), r).into()) // } else { // let a = // U112F16::from_num(10u128.saturating_pow(18 - *decimal as u32)); // let b = U112F16::from_num(*amount).checked_div(a); // let r: u128 = b.unwrap_or_else(|| U112F16::from_num(0)).to_num(); // if r == 0 { // return None; // } // Some((asset.id.clone(), r).into()) // } // }; // } // } // None // }, // _ => None, // } // } // } // pub fn slice_to_generalkey(key: &[u8]) -> Junction { // let len = key.len(); // assert!(len <= 32); // GeneralKey { // length: len as u8, // data: { // let mut data = [0u8; 32]; // data[..len].copy_from_slice(key); // data // }, // } // } #[cfg(feature = "runtime-benchmarks")] #[macro_use] extern crate frame_benchmarking; #[cfg(feature = "runtime-benchmarks")] mod benches { frame_benchmarking::define_benchmarks!( [frame_benchmarking, BaselineBench::] [frame_system, SystemBench::] [pallet_balances, Balances] [pallet_timestamp, Timestamp] [pallet_alpha_bridge, AlphaBridge] [pallet_compute_scoring, ComputeScoring] [pallet_marketplace, Marketplace] ); } impl_runtime_apis! { impl sp_api::Core for Runtime { fn version() -> RuntimeVersion { VERSION } fn execute_block(block: Block) { Executive::execute_block(block) } fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { OpaqueMetadata::new(Runtime::metadata().into()) } fn metadata_at_version(version: u32) -> Option { Runtime::metadata_at_version(version) } fn metadata_versions() -> sp_std::vec::Vec { Runtime::metadata_versions() } } impl sp_block_builder::BlockBuilder for Runtime { fn apply_extrinsic( extrinsic: ::Extrinsic, ) -> ApplyExtrinsicResult { Executive::apply_extrinsic(extrinsic) } fn finalize_block() -> ::Header { Executive::finalize_block() } fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { data.create_extrinsics() } fn check_inherents( block: Block, data: sp_inherents::InherentData, ) -> sp_inherents::CheckInherentsResult { data.check_extrinsics(&block) } } // impl sygma_runtime_api::SygmaBridgeApi for Runtime { // fn is_proposal_executed(nonce: DepositNonce, domain_id: DomainID) -> bool { // SygmaBridge::is_proposal_executed(nonce, domain_id) // } // } impl fp_rpc::EthereumRuntimeRPCApi for Runtime { fn chain_id() -> u64 { ::ChainId::get() } fn account_basic(address: H160) -> EVMAccount { let (account, _) = pallet_evm::Pallet::::account_basic(&address); account } fn gas_price() -> U256 { let (gas_price, _) = ::FeeCalculator::min_gas_price(); gas_price } fn account_code_at(address: H160) -> Vec { pallet_evm::AccountCodes::::get(address) } fn author() -> H160 { >::find_author() } fn storage_at(address: H160, index: U256) -> H256 { let mut tmp = [0u8; 32]; index.to_big_endian(&mut tmp); pallet_evm::AccountStorages::::get(address, H256::from_slice(&tmp[..])) } fn call( from: H160, to: H160, data: Vec, value: U256, gas_limit: U256, max_fee_per_gas: Option, max_priority_fee_per_gas: Option, nonce: Option, estimate: bool, access_list: Option)>>, ) -> Result { use pallet_evm::GasWeightMapping; let config = if estimate { let mut config = ::config().clone(); config.estimate = true; Some(config) } else { None }; let is_transactional = false; let validate = true; let mut estimated_transaction_len = data.len() + // to: 20 // from: 20 // value: 32 // gas_limit: 32 // nonce: 32 // 1 byte transaction action variant // chain id 8 bytes // 65 bytes signature 210; if max_fee_per_gas.is_some() { estimated_transaction_len += 32; } if max_priority_fee_per_gas.is_some() { estimated_transaction_len += 32; } if access_list.is_some() { estimated_transaction_len += access_list.encoded_size(); } let gas_limit = gas_limit.min(u64::MAX.into()).low_u64(); let without_base_extrinsic_weight = true; let (weight_limit, proof_size_base_cost) = match ::GasWeightMapping::gas_to_weight( gas_limit, without_base_extrinsic_weight ) { weight_limit if weight_limit.proof_size() > 0 => { (Some(weight_limit), Some(estimated_transaction_len as u64)) } _ => (None, None), }; let evm_config = config.as_ref().unwrap_or(::config()); // Check if the call is to your precompile address let precompile_address = H160::from_low_u64_be(2086); // Replace with your precompile address if to == precompile_address { // Set gas fees to zero for this precompile call let zero_fee = U256::zero(); let zero_priority_fee = U256::zero(); // You can also modify the gas limit if needed let modified_gas_limit = gas_limit; // or any other logic you want // Call the precompile with modified fees return ::Runner::call( from, to, data, value, modified_gas_limit.unique_saturated_into(), Some(zero_fee), Some(zero_priority_fee), nonce, access_list.unwrap_or_default(), false, // is_transactional true, // validate None, // weight_limit None, // proof_size_base_cost ::config(), ).map_err(|err| err.error.into()); } ::Runner::call( from, to, data, value, gas_limit.unique_saturated_into(), max_fee_per_gas, max_priority_fee_per_gas, nonce, access_list.unwrap_or_default(), is_transactional, validate, weight_limit, proof_size_base_cost, evm_config, ).map_err(|err| err.error.into()) } fn create( from: H160, data: Vec, value: U256, gas_limit: U256, max_fee_per_gas: Option, max_priority_fee_per_gas: Option, nonce: Option, estimate: bool, access_list: Option)>>, ) -> Result { use pallet_evm::GasWeightMapping; let config = if estimate { let mut config = ::config().clone(); config.estimate = true; Some(config) } else { None }; let is_transactional = false; let validate = true; let mut estimated_transaction_len = data.len() + // from: 20 // value: 32 // gas_limit: 32 // nonce: 32 // 1 byte transaction action variant // chain id 8 bytes // 65 bytes signature 190; if max_fee_per_gas.is_some() { estimated_transaction_len += 32; } if max_priority_fee_per_gas.is_some() { estimated_transaction_len += 32; } if access_list.is_some() { estimated_transaction_len += access_list.encoded_size(); } let gas_limit = gas_limit.min(u64::MAX.into()).low_u64(); let without_base_extrinsic_weight = true; let (weight_limit, proof_size_base_cost) = match ::GasWeightMapping::gas_to_weight( gas_limit, without_base_extrinsic_weight ) { weight_limit if weight_limit.proof_size() > 0 => { (Some(weight_limit), Some(estimated_transaction_len as u64)) } _ => (None, None), }; let evm_config = config.as_ref().unwrap_or(::config()); let whitelist = pallet_evm::WhitelistedCreators::::get(); ::Runner::create( from, data, value, gas_limit.unique_saturated_into(), max_fee_per_gas, max_priority_fee_per_gas, nonce, access_list.unwrap_or_default(), whitelist, is_transactional, validate, weight_limit, proof_size_base_cost, evm_config, ).map_err(|err| err.error.into()) } fn current_transaction_statuses() -> Option> { pallet_ethereum::CurrentTransactionStatuses::::get() } fn current_block() -> Option { pallet_ethereum::CurrentBlock::::get() } fn current_receipts() -> Option> { pallet_ethereum::CurrentReceipts::::get() } fn current_all() -> ( Option, Option>, Option> ) { ( pallet_ethereum::CurrentBlock::::get(), pallet_ethereum::CurrentReceipts::::get(), pallet_ethereum::CurrentTransactionStatuses::::get() ) } fn extrinsic_filter( xts: Vec<::Extrinsic>, ) -> Vec { xts.into_iter().filter_map(|xt| match xt.0.function { RuntimeCall::Ethereum(transact { transaction }) => Some(transaction), _ => None }).collect::>() } fn elasticity() -> Option { Some(pallet_base_fee::Elasticity::::get()) } fn gas_limit_multiplier_support() {} fn pending_block( xts: Vec<::Extrinsic>, ) -> (Option, Option>) { for ext in xts.into_iter() { let _ = Executive::apply_extrinsic(ext); } Ethereum::on_finalize(System::block_number() + 1); ( pallet_ethereum::CurrentBlock::::get(), pallet_ethereum::CurrentTransactionStatuses::::get() ) } fn initialize_pending_block(header: &::Header) { Executive::initialize_block(header); } } impl fp_rpc::ConvertTransactionRuntimeApi for Runtime { fn convert_transaction(transaction: EthereumTransaction) -> ::Extrinsic { UncheckedExtrinsic::new_unsigned( pallet_ethereum::Call::::transact { transaction }.into(), ) } } impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { fn validate_transaction( source: TransactionSource, tx: ::Extrinsic, block_hash: ::Hash, ) -> TransactionValidity { Executive::validate_transaction(source, tx, block_hash) } } impl sp_offchain::OffchainWorkerApi for Runtime { fn offchain_worker(header: &::Header) { Executive::offchain_worker(header) } } impl sp_session::SessionKeys for Runtime { fn decode_session_keys( encoded: Vec, ) -> Option, KeyTypeId)>> { opaque::SessionKeys::decode_into_raw_public_keys(&encoded) } fn generate_session_keys(seed: Option>) -> Vec { opaque::SessionKeys::generate(seed) } } impl sp_consensus_babe::BabeApi for Runtime { fn configuration() -> sp_consensus_babe::BabeConfiguration { let epoch_config = Babe::epoch_config().unwrap_or(BABE_GENESIS_EPOCH_CONFIG); sp_consensus_babe::BabeConfiguration { slot_duration: Babe::slot_duration(), epoch_length: EpochDuration::get(), c: epoch_config.c, authorities: Babe::authorities().to_vec(), randomness: Babe::randomness(), allowed_slots: epoch_config.allowed_slots, } } fn current_epoch_start() -> sp_consensus_babe::Slot { Babe::current_epoch_start() } fn current_epoch() -> sp_consensus_babe::Epoch { Babe::current_epoch() } fn next_epoch() -> sp_consensus_babe::Epoch { Babe::next_epoch() } fn generate_key_ownership_proof( _slot: sp_consensus_babe::Slot, authority_id: sp_consensus_babe::AuthorityId, ) -> Option { use parity_scale_codec::Encode; Historical::prove((sp_consensus_babe::KEY_TYPE, authority_id)) .map(|p| p.encode()) .map(sp_consensus_babe::OpaqueKeyOwnershipProof::new) } fn submit_report_equivocation_unsigned_extrinsic( equivocation_proof: sp_consensus_babe::EquivocationProof<::Header>, key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof, ) -> Option<()> { let key_owner_proof = key_owner_proof.decode()?; Babe::submit_unsigned_equivocation_report( equivocation_proof, key_owner_proof, ) } } impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { fn account_nonce(account: AccountId) -> Nonce { System::account_nonce(account) } } impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi< Block, Balance, > for Runtime { fn query_info(uxt: ::Extrinsic, len: u32) -> RuntimeDispatchInfo { TransactionPayment::query_info(uxt, len) } fn query_fee_details(uxt: ::Extrinsic, len: u32) -> FeeDetails { TransactionPayment::query_fee_details(uxt, len) } fn query_weight_to_fee(weight: Weight) -> Balance { TransactionPayment::weight_to_fee(weight) } fn query_length_to_fee(length: u32) -> Balance { TransactionPayment::length_to_fee(length) } } impl fg_primitives::GrandpaApi for Runtime { fn grandpa_authorities() -> GrandpaAuthorityList { Grandpa::grandpa_authorities() } fn current_set_id() -> fg_primitives::SetId { Grandpa::current_set_id() } fn submit_report_equivocation_unsigned_extrinsic( equivocation_proof: fg_primitives::EquivocationProof< ::Hash, NumberFor, >, key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, ) -> Option<()> { let key_owner_proof = key_owner_proof.decode()?; Grandpa::submit_unsigned_equivocation_report( equivocation_proof, key_owner_proof, ) } fn generate_key_ownership_proof( _set_id: fg_primitives::SetId, authority_id: GrandpaId, ) -> Option { use parity_scale_codec::Encode; Historical::prove((fg_primitives::KEY_TYPE, authority_id)) .map(|p| p.encode()) .map(fg_primitives::OpaqueKeyOwnershipProof::new) } } impl rpc_primitives_debug::DebugRuntimeApi for Runtime { fn trace_transaction( extrinsics: Vec<::Extrinsic>, traced_transaction: &EthereumTransaction, header: &::Header, ) -> Result< (), sp_runtime::DispatchError, > { #[cfg(feature = "evm-tracing")] { use evm_tracer::tracer::EvmTracer; // Initialize block: calls the "on_initialize" hook on every pallet // in AllPalletsWithSystem. Executive::initialize_block(header); // Apply the a subset of extrinsics: all the substrate-specific or ethereum // transactions that preceded the requested transaction. for ext in extrinsics.into_iter() { let _ = match &ext.0.function { RuntimeCall::Ethereum(transact { transaction }) => { if transaction == traced_transaction { EvmTracer::new().trace(|| Executive::apply_extrinsic(ext)); return Ok(()); } else { Executive::apply_extrinsic(ext) } } _ => Executive::apply_extrinsic(ext), }; } Ok(()) } #[cfg(not(feature = "evm-tracing"))] Err(sp_runtime::DispatchError::Other( "Missing `evm-tracing` compile time feature flag.", )) } fn trace_block( extrinsics: Vec<::Extrinsic>, known_transactions: Vec, header: &::Header, ) -> Result< (), sp_runtime::DispatchError, > { #[cfg(feature = "evm-tracing")] { use evm_tracer::tracer::EvmTracer; let mut config = ::config().clone(); config.estimate = true; // Initialize block: calls the "on_initialize" hook on every pallet // in AllPalletsWithSystem. Executive::initialize_block(header); // Apply all extrinsics. Ethereum extrinsics are traced. for ext in extrinsics.into_iter() { match &ext.0.function { RuntimeCall::Ethereum(transact { transaction }) => { if known_transactions.contains(&transaction.hash()) { // Each known extrinsic is a new call stack. EvmTracer::emit_new(); EvmTracer::new().trace(|| Executive::apply_extrinsic(ext)); } else { let _ = Executive::apply_extrinsic(ext); } } _ => { let _ = Executive::apply_extrinsic(ext); } }; } Ok(()) } #[cfg(not(feature = "evm-tracing"))] Err(sp_runtime::DispatchError::Other( "Missing `evm-tracing` compile time feature flag.", )) } fn trace_call( header: &::Header, from: H160, to: H160, data: Vec, value: U256, gas_limit: U256, max_fee_per_gas: Option, max_priority_fee_per_gas: Option, nonce: Option, access_list: Option)>>, ) -> Result<(), sp_runtime::DispatchError> { #[cfg(feature = "evm-tracing")] { use evm_tracer::tracer::EvmTracer; // Initialize block: calls the "on_initialize" hook on every pallet // in AllPalletsWithSystem. Executive::initialize_block(header); EvmTracer::new().trace(|| { let is_transactional = false; let validate = true; let without_base_extrinsic_weight = true; // Estimated encoded transaction size must be based on the heaviest transaction // type (EIP1559Transaction) to be compatible with all transaction types. let mut estimated_transaction_len = data.len() + // pallet ethereum index: 1 // transact call index: 1 // Transaction enum variant: 1 // chain_id 8 bytes // nonce: 32 // max_priority_fee_per_gas: 32 // max_fee_per_gas: 32 // gas_limit: 32 // action: 21 (enum varianrt + call address) // value: 32 // access_list: 1 (empty vec size) // 65 bytes signature 258; if access_list.is_some() { estimated_transaction_len += access_list.encoded_size(); } let gas_limit = gas_limit.min(u64::MAX.into()).low_u64(); let (weight_limit, proof_size_base_cost) = match ::GasWeightMapping::gas_to_weight( gas_limit, without_base_extrinsic_weight ) { weight_limit if weight_limit.proof_size() > 0 => { (Some(weight_limit), Some(estimated_transaction_len as u64)) } _ => (None, None), }; let _ = ::Runner::call( from, to, data, value, gas_limit, max_fee_per_gas, max_priority_fee_per_gas, nonce, access_list.unwrap_or_default(), is_transactional, validate, weight_limit, proof_size_base_cost, ::config(), ); }); Ok(()) } #[cfg(not(feature = "evm-tracing"))] Err(sp_runtime::DispatchError::Other( "Missing `evm-tracing` compile time feature flag.", )) } } impl rpc_primitives_node_metrics::NodeMetricsRuntimeApi for Runtime { fn get_node_metrics(node_id: Vec) -> Option { let node_metrics = >::get_node_metrics(node_id); node_metrics.map(|metrics| { rpc_primitives_node_metrics::NodeMetricsData { miner_id: String::from_utf8_lossy(&metrics.miner_id).into_owned(), bandwidth_bytes: metrics.bandwidth_mbps, current_storage_bytes: metrics.current_storage_bytes, total_storage_bytes: metrics.total_storage_bytes, geolocation: String::from_utf8_lossy(&metrics.geolocation).into_owned(), successful_pin_checks: metrics.successful_pin_checks, total_pin_checks: metrics.total_pin_checks, storage_proof_time_ms: metrics.storage_proof_time_ms, storage_growth_rate: metrics.storage_growth_rate, latency_ms: metrics.latency_ms, total_latency_ms: metrics.total_latency_ms, total_times_latency_checked: metrics.total_times_latency_checked, avg_response_time_ms: metrics.avg_response_time_ms, peer_count: metrics.peer_count, failed_challenges_count: metrics.failed_challenges_count, successful_challenges: metrics.successful_challenges, total_challenges: metrics.total_challenges, uptime_minutes: metrics.uptime_minutes, total_minutes: metrics.total_minutes, consecutive_reliable_days: metrics.consecutive_reliable_days, recent_downtime_hours: metrics.recent_downtime_hours, is_sev_enabled: metrics.is_sev_enabled, zfs_info: metrics.zfs_info.into_iter() .map(|info| String::from_utf8_lossy(&info).into_owned()) .collect(), raid_info: metrics.raid_info.into_iter() .map(|info| String::from_utf8_lossy(&info).into_owned()) .collect(), ipfs_zfs_pool_size: metrics.ipfs_zfs_pool_size, ipfs_zfs_pool_alloc: metrics.ipfs_zfs_pool_alloc, ipfs_zfs_pool_free: metrics.ipfs_zfs_pool_free, vm_count: metrics.vm_count, primary_network_interface: metrics.primary_network_interface.map(|nif| { rpc_primitives_node_metrics::NetworkInterfaceInfo { name: String::from_utf8_lossy(&nif.name).into_owned(), mac_address: nif.mac_address.map(|mac| String::from_utf8_lossy(&mac).into_owned()), uplink_mb: nif.uplink_mb, downlink_mb: nif.downlink_mb, network_details: nif.network_details.map(|nd| { rpc_primitives_node_metrics::NetworkDetails { network_type: match nd.network_type { pallet_execution_unit::types::NetworkType::Private => rpc_primitives_node_metrics::NetworkType::Private, pallet_execution_unit::types::NetworkType::Public => rpc_primitives_node_metrics::NetworkType::Public, }, city: nd.city.map(|c| String::from_utf8_lossy(&c).into_owned()), region: nd.region.map(|r| String::from_utf8_lossy(&r).into_owned()), country: nd.country.map(|c| String::from_utf8_lossy(&c).into_owned()), loc: nd.loc.map(|l| String::from_utf8_lossy(&l).into_owned()), } }), } }), disks: metrics.disks.into_iter().map(|disk| { rpc_primitives_node_metrics::DiskInfo { name: String::from_utf8_lossy(&disk.name).into_owned(), disk_type: String::from_utf8_lossy(&disk.disk_type).into_owned(), total_space_mb: disk.total_space_mb, free_space_mb: disk.free_space_mb, } }).collect(), ipfs_repo_size: metrics.ipfs_repo_size, ipfs_storage_max: metrics.ipfs_storage_max, cpu_model: String::from_utf8_lossy(&metrics.cpu_model).into_owned(), cpu_cores: metrics.cpu_cores, memory_bytes: metrics.memory_mb, free_memory_bytes: metrics.free_memory_mb, gpu_name: metrics.gpu_name.map(|gpu| String::from_utf8_lossy(&gpu).into_owned()), gpu_memory_bytes: metrics.gpu_memory_mb, hypervisor_disk_type: metrics.hypervisor_disk_type.map(|hdt| String::from_utf8_lossy(&hdt).into_owned()), vm_pool_disk_type: metrics.vm_pool_disk_type.map(|vpdt| String::from_utf8_lossy(&vpdt).into_owned()), } }) } fn get_active_nodes_metrics_by_type(node_type: rpc_primitives_node_metrics::NodeType) -> Vec> { // Convert RPC NodeType to Pallet NodeType let pallet_node_type = match node_type { rpc_primitives_node_metrics::NodeType::Validator => pallet_registration::NodeType::Validator, rpc_primitives_node_metrics::NodeType::StorageMiner => pallet_registration::NodeType::StorageMiner, rpc_primitives_node_metrics::NodeType::StorageS3 => pallet_registration::NodeType::StorageS3, rpc_primitives_node_metrics::NodeType::ComputeMiner => pallet_registration::NodeType::ComputeMiner, rpc_primitives_node_metrics::NodeType::GpuMiner => pallet_registration::NodeType::GpuMiner, }; // log! let node_metrics = >::get_active_nodes_metrics_by_type(pallet_node_type); // Convert from execution unit NodeMetricsData to RPC primitives NodeMetricsData node_metrics.into_iter().map(|metrics_opt| { metrics_opt.map(|metrics| { rpc_primitives_node_metrics::NodeMetricsData { miner_id: String::from_utf8_lossy(&metrics.miner_id).into_owned(), bandwidth_bytes: metrics.bandwidth_mbps, current_storage_bytes: metrics.current_storage_bytes, total_storage_bytes: metrics.total_storage_bytes, geolocation: String::from_utf8_lossy(&metrics.geolocation).into_owned(), successful_pin_checks: metrics.successful_pin_checks, total_pin_checks: metrics.total_pin_checks, storage_proof_time_ms: metrics.storage_proof_time_ms, storage_growth_rate: metrics.storage_growth_rate, latency_ms: metrics.latency_ms, total_latency_ms: metrics.total_latency_ms, total_times_latency_checked: metrics.total_times_latency_checked, avg_response_time_ms: metrics.avg_response_time_ms, peer_count: metrics.peer_count, failed_challenges_count: metrics.failed_challenges_count, successful_challenges: metrics.successful_challenges, total_challenges: metrics.total_challenges, uptime_minutes: metrics.uptime_minutes, total_minutes: metrics.total_minutes, consecutive_reliable_days: metrics.consecutive_reliable_days, recent_downtime_hours: metrics.recent_downtime_hours, is_sev_enabled: metrics.is_sev_enabled, zfs_info: metrics.zfs_info.into_iter() .map(|info| String::from_utf8_lossy(&info).into_owned()) .collect(), ipfs_zfs_pool_size: metrics.ipfs_zfs_pool_size, ipfs_zfs_pool_alloc: metrics.ipfs_zfs_pool_alloc, ipfs_zfs_pool_free: metrics.ipfs_zfs_pool_free, raid_info: metrics.raid_info.into_iter() .map(|info| String::from_utf8_lossy(&info).into_owned()) .collect(), vm_count: metrics.vm_count, primary_network_interface: metrics.primary_network_interface.map(|nif| { rpc_primitives_node_metrics::NetworkInterfaceInfo { name: String::from_utf8_lossy(&nif.name).into_owned(), mac_address: nif.mac_address.map(|mac| String::from_utf8_lossy(&mac).into_owned()), uplink_mb: nif.uplink_mb, downlink_mb: nif.downlink_mb, network_details: nif.network_details.map(|nd| { rpc_primitives_node_metrics::NetworkDetails { network_type: match nd.network_type { pallet_execution_unit::types::NetworkType::Private => rpc_primitives_node_metrics::NetworkType::Private, pallet_execution_unit::types::NetworkType::Public => rpc_primitives_node_metrics::NetworkType::Public, }, city: nd.city.map(|c| String::from_utf8_lossy(&c).into_owned()), region: nd.region.map(|r| String::from_utf8_lossy(&r).into_owned()), country: nd.country.map(|c| String::from_utf8_lossy(&c).into_owned()), loc: nd.loc.map(|l| String::from_utf8_lossy(&l).into_owned()), } }), } }), disks: metrics.disks.into_iter().map(|disk| { rpc_primitives_node_metrics::DiskInfo { name: String::from_utf8_lossy(&disk.name).into_owned(), disk_type: String::from_utf8_lossy(&disk.disk_type).into_owned(), total_space_mb: disk.total_space_mb, free_space_mb: disk.free_space_mb, } }).collect(), ipfs_repo_size: metrics.ipfs_repo_size, ipfs_storage_max: metrics.ipfs_storage_max, cpu_model: String::from_utf8_lossy(&metrics.cpu_model).into_owned(), cpu_cores: metrics.cpu_cores, memory_bytes: metrics.memory_mb, free_memory_bytes: metrics.free_memory_mb, gpu_name: metrics.gpu_name.map(|gpu| String::from_utf8_lossy(&gpu).into_owned()), gpu_memory_bytes: metrics.gpu_memory_mb, hypervisor_disk_type: metrics.hypervisor_disk_type.map(|hdt| String::from_utf8_lossy(&hdt).into_owned()), vm_pool_disk_type: metrics.vm_pool_disk_type.map(|vpdt| String::from_utf8_lossy(&vpdt).into_owned()), } }) }).collect() } fn get_total_node_rewards(account: AccountId32) -> u128 { >::get_total_node_rewards(account) } fn get_client_ip(client_id: AccountId32) -> Option>{ >::get_client_ip(&client_id) } fn get_hypervisor_ip( hypervisor_id: Vec) -> Option>{ >::get_hypervisor_ip(hypervisor_id) } fn get_vm_ip( vm_id: Vec) -> Option>{ >::get_vm_ip(vm_id) } fn get_storage_miner_ip( miner_id: Vec) -> Option>{ >::get_storage_miner_ip(miner_id) } fn get_free_credits_rpc(account: Option) -> Vec<(AccountId32, u128)>{ >::get_free_credits_rpc(account) } fn get_referred_users(account_id: AccountId32) -> Vec { >::get_referred_users(account_id) } fn total_referral_codes() -> u32{ >::total_referral_codes() } fn get_referral_codes(account_id: AccountId32) -> Vec>{ >::get_referral_codes(account_id) } fn get_batches_for_user(account_id: AccountId32) -> Vec> { let batches = >::get_batches_for_user(account_id); batches.into_iter().map(|batch| { rpc_primitives_node_metrics::Batch { owner: batch.owner, credit_amount: batch.credit_amount as u128, // Convert to u32 alpha_amount: batch.alpha_amount as u128, // Convert to u32 remaining_credits: batch.remaining_credits as u128, // Convert to u32 remaining_alpha: batch.remaining_alpha as u128, // Convert to u32 pending_alpha: batch.pending_alpha as u128, // Convert to u32 is_frozen: batch.is_frozen, release_time: batch.release_time as u32, } }).collect() } fn get_batch_by_id(batch_id: u64) -> Option> { let batch = >::get_batch_by_id(batch_id)?; Some(rpc_primitives_node_metrics::Batch { owner: batch.owner, credit_amount: batch.credit_amount as u128, // Convert to u128 alpha_amount: batch.alpha_amount as u128, // Convert to u128 remaining_credits: batch.remaining_credits as u128, // Convert to u128 remaining_alpha: batch.remaining_alpha as u128, // Convert to u128 pending_alpha: batch.pending_alpha as u128, // Convert to u128 is_frozen: batch.is_frozen, release_time: batch.release_time as u32, // Convert to u32 }) } fn get_miner_info(account_id: AccountId32) -> Option<(rpc_primitives_node_metrics::NodeType, rpc_primitives_node_metrics::Status)> { match >::get_miner_info(account_id) { Some((node_type, status)) => { let updated_node_type = match node_type { pallet_registration::NodeType::Validator => rpc_primitives_node_metrics::NodeType::Validator, pallet_registration::NodeType::StorageMiner => rpc_primitives_node_metrics::NodeType::StorageMiner, pallet_registration::NodeType::StorageS3 => rpc_primitives_node_metrics::NodeType::StorageS3, pallet_registration::NodeType::ComputeMiner => rpc_primitives_node_metrics::NodeType::ComputeMiner, pallet_registration::NodeType::GpuMiner => rpc_primitives_node_metrics::NodeType::GpuMiner, }; let updated_status = match status { pallet_registration::Status::Online => rpc_primitives_node_metrics::Status::Online, pallet_registration::Status::Offline => rpc_primitives_node_metrics::Status::Offline, pallet_registration::Status::Degraded => rpc_primitives_node_metrics::Status::Degraded, }; Some((updated_node_type, updated_status)) }, None => None, } } fn get_total_distributed_rewards_by_node_type(node_type: rpc_primitives_node_metrics::NodeType) -> u128 { // Convert RPC NodeType to Pallet NodeType let pallet_node_type = match node_type { rpc_primitives_node_metrics::NodeType::Validator => pallet_registration::NodeType::Validator, rpc_primitives_node_metrics::NodeType::StorageMiner => pallet_registration::NodeType::StorageMiner, rpc_primitives_node_metrics::NodeType::StorageS3 => pallet_registration::NodeType::StorageS3, rpc_primitives_node_metrics::NodeType::ComputeMiner => pallet_registration::NodeType::ComputeMiner, rpc_primitives_node_metrics::NodeType::GpuMiner => pallet_registration::NodeType::GpuMiner, }; >::get_total_distributed_rewards_by_node_type(pallet_node_type) } fn get_miners_total_rewards(node_type: rpc_primitives_node_metrics::NodeType) -> Vec{ // Convert RPC NodeType to Pallet NodeType let pallet_node_type = match node_type { rpc_primitives_node_metrics::NodeType::Validator => pallet_registration::NodeType::Validator, rpc_primitives_node_metrics::NodeType::StorageMiner => pallet_registration::NodeType::StorageMiner, rpc_primitives_node_metrics::NodeType::StorageS3 => pallet_registration::NodeType::StorageS3, rpc_primitives_node_metrics::NodeType::ComputeMiner => pallet_registration::NodeType::ComputeMiner, rpc_primitives_node_metrics::NodeType::GpuMiner => pallet_registration::NodeType::GpuMiner, }; // Convert pallet MinerRewardSummary to RPC MinerRewardSummary >::get_miners_total_rewards(pallet_node_type) .into_iter() .map(|summary| rpc_primitives_node_metrics::MinerRewardSummary { account: summary.account.clone(), reward: summary.reward, }) .collect() } fn get_account_pending_rewards( account: AccountId32) -> Vec{ >::get_account_pending_rewards(account) .into_iter() .map(|summary| rpc_primitives_node_metrics::MinerRewardSummary { account: summary.account.clone(), reward: summary.reward, }) .collect() } fn get_miners_pending_rewards(node_type: rpc_primitives_node_metrics::NodeType) -> Vec{ // Convert RPC NodeType to Pallet NodeType let pallet_node_type = match node_type { rpc_primitives_node_metrics::NodeType::Validator => pallet_registration::NodeType::Validator, rpc_primitives_node_metrics::NodeType::StorageMiner => pallet_registration::NodeType::StorageMiner, rpc_primitives_node_metrics::NodeType::StorageS3 => pallet_registration::NodeType::StorageS3, rpc_primitives_node_metrics::NodeType::ComputeMiner => pallet_registration::NodeType::ComputeMiner, rpc_primitives_node_metrics::NodeType::GpuMiner => pallet_registration::NodeType::GpuMiner, }; >::get_miners_pending_rewards(pallet_node_type) .into_iter() .map(|summary| rpc_primitives_node_metrics::MinerRewardSummary { account: summary.account.clone(), reward: summary.reward, }) .collect() } fn calculate_total_file_size(account: AccountId32) -> u128 { // >::user_total_files_size(&account).unwrap_or(0) 0 } fn get_user_files(account: AccountId32) -> Vec { // >::get_user_files(account) // .into_iter() // .map(|file| rpc_primitives_node_metrics::UserFile { // file_hash: file.file_hash.to_vec(), // file_name: file.file_name.to_vec(), // miner_ids: file.miner_ids.clone(), // file_size: file.file_size, // created_at: file.created_at, // }) // .collect() Vec::new() } fn total_file_size_fulfilled(account_id: AccountId32) -> u128 { // >::user_total_files_size(&account_id).unwrap_or(0) 0 } } impl rpc_primitives_txpool::TxPoolRuntimeApi for Runtime { fn extrinsic_filter( xts_ready: Vec<::Extrinsic>, xts_future: Vec<::Extrinsic>, ) -> rpc_primitives_txpool::TxPoolResponse { rpc_primitives_txpool::TxPoolResponse { ready: xts_ready .into_iter() .filter_map(|xt| match xt.0.function { RuntimeCall::Ethereum(transact { transaction }) => Some(transaction), _ => None, }) .collect(), future: xts_future .into_iter() .filter_map(|xt| match xt.0.function { RuntimeCall::Ethereum(transact { transaction }) => Some(transaction), _ => None, }) .collect(), } } } impl sp_genesis_builder::GenesisBuilder for Runtime { fn build_state(config: Vec) -> sp_genesis_builder::Result { build_state::(config) } fn get_preset(id: &Option) -> Option> { get_preset::(id, |_| None) } fn preset_names() -> Vec { vec![] } } #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn benchmark_metadata(extra: bool) -> ( Vec, Vec, ) { use frame_benchmarking::{baseline, Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use baseline::Pallet as BaselineBench; let mut list = Vec::::new(); list_benchmarks!(list, extra); let storage_info = AllPalletsWithSystem::storage_info(); (list, storage_info) } fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig ) -> Result, sp_runtime::RuntimeString> { use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch}; use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; use baseline::Pallet as BaselineBench; impl frame_system_benchmarking::Config for Runtime {} impl baseline::Config for Runtime {} use frame_support::traits::WhitelistedStorageKeys; let whitelist: Vec = AllPalletsWithSystem::whitelisted_storage_keys(); let mut batches = Vec::::new(); let params = (&config, &whitelist); add_benchmarks!(params, batches); Ok(batches) } } }