From 9931800a63ba4e3ab80dafbbf11cb8f84fd615e2 Mon Sep 17 00:00:00 2001 From: Aliaksandr Tsurko Date: Mon, 3 Mar 2025 17:00:51 +0100 Subject: [PATCH 1/7] Encapsulate precompiles into crate --- Cargo.lock | 37 +- Cargo.toml | 96 +- common/Cargo.toml | 32 + common/src/lib.rs | 86 ++ precompiles/Cargo.toml | 58 ++ precompiles/src/balance_transfer.rs | 64 ++ precompiles/src/ed25519.rs | 48 + precompiles/src/lib.rs | 349 ++++++++ precompiles/src/metagraph.rs | 184 ++++ precompiles/src/neuron.rs | 210 +++++ precompiles/src/solidity/balanceTransfer.abi | 15 + precompiles/src/solidity/balanceTransfer.sol | 7 + precompiles/src/solidity/ed25519Verify.abi | 14 + precompiles/src/solidity/ed25519Verify.sol | 17 + precompiles/src/solidity/metagraph.abi | 389 ++++++++ precompiles/src/solidity/metagraph.sol | 134 +++ precompiles/src/solidity/neuron.abi | 233 +++++ precompiles/src/solidity/neuron.sol | 122 +++ precompiles/src/solidity/staking.abi | 98 ++ precompiles/src/solidity/staking.sol | 79 ++ precompiles/src/solidity/subnet.abi | 887 +++++++++++++++++++ precompiles/src/solidity/subnet.sol | 173 ++++ precompiles/src/staking.rs | 206 +++++ precompiles/src/subnet.rs | 628 +++++++++++++ runtime/Cargo.toml | 23 +- runtime/src/lib.rs | 71 +- 26 files changed, 4142 insertions(+), 118 deletions(-) create mode 100644 common/Cargo.toml create mode 100644 common/src/lib.rs create mode 100644 precompiles/Cargo.toml create mode 100644 precompiles/src/balance_transfer.rs create mode 100644 precompiles/src/ed25519.rs create mode 100644 precompiles/src/lib.rs create mode 100644 precompiles/src/metagraph.rs create mode 100644 precompiles/src/neuron.rs create mode 100644 precompiles/src/solidity/balanceTransfer.abi create mode 100644 precompiles/src/solidity/balanceTransfer.sol create mode 100644 precompiles/src/solidity/ed25519Verify.abi create mode 100644 precompiles/src/solidity/ed25519Verify.sol create mode 100644 precompiles/src/solidity/metagraph.abi create mode 100644 precompiles/src/solidity/metagraph.sol create mode 100644 precompiles/src/solidity/neuron.abi create mode 100644 precompiles/src/solidity/neuron.sol create mode 100644 precompiles/src/solidity/staking.abi create mode 100644 precompiles/src/solidity/staking.sol create mode 100644 precompiles/src/solidity/subnet.abi create mode 100644 precompiles/src/solidity/subnet.sol create mode 100644 precompiles/src/staking.rs create mode 100644 precompiles/src/subnet.rs diff --git a/Cargo.lock b/Cargo.lock index 0d76188012..8efcdc5ac0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5813,7 +5813,6 @@ name = "node-subtensor-runtime" version = "4.0.0-dev" dependencies = [ "ark-serialize", - "ed25519-dalek", "fp-account", "fp-evm", "fp-rpc", @@ -5884,6 +5883,7 @@ dependencies = [ "substrate-wasm-builder", "subtensor-custom-rpc-runtime-api", "subtensor-macros", + "subtensor-runtime-common", "tle", "w3f-bls", ] @@ -11204,6 +11204,41 @@ dependencies = [ "syn 2.0.96", ] +[[package]] +name = "subtensor-precompiles" +version = "0.1.0" +dependencies = [ + "ed25519-dalek", + "fp-evm", + "frame-support", + "frame-system", + "log", + "pallet-admin-utils", + "pallet-balances", + "pallet-evm", + "pallet-evm-precompile-modexp", + "pallet-evm-precompile-sha3fips", + "pallet-evm-precompile-simple", + "pallet-proxy", + "pallet-subtensor", + "precompile-utils", + "sp-core", + "sp-runtime", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409)", + "subtensor-runtime-common", +] + +[[package]] +name = "subtensor-runtime-common" +version = "0.1.0" +dependencies = [ + "frame-support", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", +] + [[package]] name = "subtensor-tools" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index ef5d64b0d6..b00c098913 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,21 +23,15 @@ rayon = "1.10" [workspace] members = [ - "node", - "pallets/commitments", - "pallets/subtensor", - "pallets/admin-utils", - "pallets/collective", - "pallets/registry", - "primitives/*", - "runtime", - "support/tools", - "support/macros", - "support/linting", - "support/procedural-fork", - "pallets/drand", + "common", + "node", + "pallets/*", + "precompiles", + "primitives/*", + "runtime", + "common", + "support/*", ] -exclude = ["support/procedural-fork"] resolver = "2" [workspace.lints.clippy] @@ -46,14 +40,27 @@ arithmetic-side-effects = "deny" type_complexity = "allow" unwrap-used = "deny" manual_inspect = "allow" -useless_conversion = "allow" # until polkadot is patched +useless_conversion = "allow" # until polkadot is patched [workspace.dependencies] +pallet-admin-utils = { default-features = false, path = "pallets/admin-utils" } +pallet-collective = { default-features = false, path = "pallets/collective" } +pallet-commitments = { default-features = false, path = "pallets/commitments" } +pallet-registry = { default-features = false, path = "pallets/registry" } +pallet-subtensor = { default-features = false, path = "pallets/subtensor" } +subtensor-custom-rpc-runtime-api = { default-features = false, path = "pallets/subtensor/runtime-api" } +subtensor-precompiles = { default-features = false, path = "precompiles" } +subtensor-runtime-common = { default-features = false, path = "common" } + async-trait = "0.1" cargo-husky = { version = "1", default-features = false } clap = "4.5.4" -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } -ed25519-dalek = { version = "2.1.0", default-features = false, features = ["alloc"] } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ + "derive", +] } +ed25519-dalek = { version = "2.1.0", default-features = false, features = [ + "alloc", +] } enumflags2 = "0.7.9" futures = "0.3.30" hex = { version = "0.4", default-features = false } @@ -64,7 +71,9 @@ memmap2 = "0.9.4" ndarray = { version = "0.15.6", default-features = false } parity-util-mem = "0.12.0" rand = "0.8.5" -scale-codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } +scale-codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ + "derive", +] } scale-info = { version = "2.11.2", default-features = false } serde = { version = "1.0.214", default-features = false } serde-tuple-vec-map = { version = "1.0.1", default-features = false } @@ -74,11 +83,11 @@ serde_with = { version = "=2.0.0", default-features = false } smallvec = "1.13.2" litep2p = { git = "https://github.com/paritytech/litep2p", tag = "v0.7.0" } syn = { version = "2.0.87", features = [ - "full", - "visit-mut", - "visit", - "extra-traits", - "parsing", + "full", + "visit-mut", + "visit", + "extra-traits", + "parsing", ] } quote = "1" proc-macro2 = { version = "1", features = ["span-locations"] } @@ -181,7 +190,9 @@ fc-consensus = { git = "https://github.com/opentensor/frontier", rev = "635bdac8 fp-consensus = { git = "https://github.com/opentensor/frontier", rev = "635bdac882", default-features = false } fp-dynamic-fee = { git = "https://github.com/opentensor/frontier", rev = "635bdac882", default-features = false } fc-api = { git = "https://github.com/opentensor/frontier", rev = "635bdac882", default-features = false } -fc-rpc = { git = "https://github.com/opentensor/frontier", rev = "635bdac882", default-features = false, features = ["rpc-binary-search-estimate"]} +fc-rpc = { git = "https://github.com/opentensor/frontier", rev = "635bdac882", default-features = false, features = [ + "rpc-binary-search-estimate", +] } fc-rpc-core = { git = "https://github.com/opentensor/frontier", rev = "635bdac882", default-features = false } fc-mapping-sync = { git = "https://github.com/opentensor/frontier", rev = "635bdac882", default-features = false } precompile-utils = { git = "https://github.com/opentensor/frontier", rev = "635bdac882", default-features = false } @@ -199,21 +210,34 @@ pallet-hotfix-sufficients = { git = "https://github.com/opentensor/frontier", re #DRAND pallet-drand = { path = "pallets/drand", default-features = false } -sp-crypto-ec-utils = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", features = ["bls12-381"] } -getrandom = { version = "0.2.15", features = ["custom"], default-features = false } -sp-keystore = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-crypto-ec-utils = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", features = [ + "bls12-381", +] } +getrandom = { version = "0.2.15", features = [ + "custom", +], default-features = false } +sp-keystore = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } w3f-bls = { version = "=0.1.3", default-features = false } -ark-crypto-primitives = { version = "0.4.0", default-features = false, features = [ "r1cs", "snark" ] } -ark-scale = { version = "0.0.11", default-features = false, features = ["hazmat"] } +ark-crypto-primitives = { version = "0.4.0", default-features = false, features = [ + "r1cs", + "snark", +] } +ark-scale = { version = "0.0.11", default-features = false, features = [ + "hazmat", +] } sp-ark-bls12-381 = { git = "https://github.com/paritytech/substrate-curves", default-features = false } -ark-bls12-381 = { version = "0.4.0", features = ["curve"], default-features = false } -ark-serialize = { version = "0.4.0", features = [ "derive" ], default-features = false } +ark-bls12-381 = { version = "0.4.0", features = [ + "curve", +], default-features = false } +ark-serialize = { version = "0.4.0", features = [ + "derive", +], default-features = false } ark-ff = { version = "0.4.0", default-features = false } ark-ec = { version = "0.4.0", default-features = false } ark-std = { version = "0.4.0", default-features = false } anyhow = "1.0.81" sha2 = { version = "0.10.8", default-features = false } -rand_chacha = { version = "0.3.1", default-features = false } +rand_chacha = { version = "0.3.1", default-features = false } tle = { git = "https://github.com/ideal-lab5/timelock", rev = "5416406cfd32799e31e1795393d4916894de4468", default-features = false } frame-metadata = "16" @@ -232,11 +256,11 @@ codegen-units = 1 [features] default = [] try-runtime = [ - "node-subtensor/try-runtime", - "node-subtensor-runtime/try-runtime", + "node-subtensor/try-runtime", + "node-subtensor-runtime/try-runtime", ] runtime-benchmarks = [ - "node-subtensor/runtime-benchmarks", - "node-subtensor-runtime/runtime-benchmarks", + "node-subtensor/runtime-benchmarks", + "node-subtensor-runtime/runtime-benchmarks", ] metadata-hash = ["node-subtensor-runtime/metadata-hash"] diff --git a/common/Cargo.toml b/common/Cargo.toml new file mode 100644 index 0000000000..d0b43cdc1b --- /dev/null +++ b/common/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "subtensor-runtime-common" +version = "0.1.0" +edition = "2024" +authors = ["Opentensor Foundation "] +homepage = "https://opentensor.ai/" +publish = false +repository = "https://github.com/opentensor/subtensor/" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { workspace = true } +frame-support = { workspace = true } +scale-info = { workspace = true } +sp-runtime = { workspace = true } +sp-core = { workspace = true } + +[lints] +workspace = true + +[features] +default = ["std"] +fast-blocks = [] +std = [ + "codec/std", + "frame-support/std", + "scale-info/std", + "sp-core/std", + "sp-runtime/std", +] diff --git a/common/src/lib.rs b/common/src/lib.rs new file mode 100644 index 0000000000..ad038cfb00 --- /dev/null +++ b/common/src/lib.rs @@ -0,0 +1,86 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_runtime::{ + MultiSignature, + traits::{IdentifyAccount, Verify}, +}; + +/// Balance of an account. +pub type Balance = u64; + +/// An index to a block. +pub type BlockNumber = u32; + +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent to the +/// public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +/// Index of a transaction in the chain. +pub type Index = u32; + +/// A hash of some data used by the chain. +pub type Hash = sp_core::H256; + +pub type Nonce = u32; + +/// Transfers below SMALL_TRANSFER_LIMIT are considered small transfers +pub const SMALL_TRANSFER_LIMIT: Balance = 500_000_000; // 0.5 TAO + +#[derive( + Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, MaxEncodedLen, TypeInfo, +)] +pub enum ProxyType { + Any, + Owner, // Subnet owner Calls + NonCritical, + NonTransfer, + Senate, + NonFungibile, // Nothing involving moving TAO + Triumvirate, + Governance, // Both above governance + Staking, + Registration, + Transfer, + SmallTransfer, + RootWeights, + ChildKeys, + SudoUncheckedSetCode, +} + +impl Default for ProxyType { + // allow all Calls; required to be most permissive + fn default() -> Self { + Self::Any + } +} + +pub mod time { + use super::*; + + /// This determines the average expected block time that we are targeting. Blocks will be + /// produced at a minimum duration defined by `SLOT_DURATION`. `SLOT_DURATION` is picked up by + /// `pallet_timestamp` which is in turn picked up by `pallet_aura` to implement `fn + /// slot_duration()`. + /// + /// Change this to adjust the block time. + #[cfg(not(feature = "fast-blocks"))] + pub const MILLISECS_PER_BLOCK: u64 = 12000; + + /// Fast blocks for development + #[cfg(feature = "fast-blocks")] + pub const MILLISECS_PER_BLOCK: u64 = 250; + + // NOTE: Currently it is not possible to change the slot duration after the chain has started. + // Attempting to do so will brick block production. + pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + + // Time is measured by number of blocks. + pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); + pub const HOURS: BlockNumber = MINUTES * 60; + pub const DAYS: BlockNumber = HOURS * 24; +} diff --git a/precompiles/Cargo.toml b/precompiles/Cargo.toml new file mode 100644 index 0000000000..ec46e6aee2 --- /dev/null +++ b/precompiles/Cargo.toml @@ -0,0 +1,58 @@ +[package] +name = "subtensor-precompiles" +version = "0.1.0" +edition = "2024" +authors = ["Opentensor Foundation "] +homepage = "https://opentensor.ai/" +publish = false +repository = "https://github.com/opentensor/subtensor/" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +ed25519-dalek = { workspace = true } +fp-evm = { workspace = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +log = { workspace = true } +pallet-balances = { workspace = true } +pallet-evm = { workspace = true } +pallet-evm-precompile-modexp = { workspace = true } +pallet-evm-precompile-sha3fips = { workspace = true } +pallet-evm-precompile-simple = { workspace = true } +pallet-proxy = { workspace = true } +precompile-utils = { workspace = true } +sp-core = { workspace = true } +sp-runtime = { workspace = true } +sp-std = { workspace = true } +subtensor-runtime-common = { workspace = true } + +pallet-subtensor = { workspace = true } +pallet-admin-utils = { workspace = true } + +[lints] +workspace = true + +[features] +default = ["std"] +std = [ + "ed25519-dalek/std", + "fp-evm/std", + "frame-support/std", + "frame-system/std", + "log/std", + "pallet-admin-utils/std", + "pallet-balances/std", + "pallet-evm-precompile-modexp/std", + "pallet-evm-precompile-sha3fips/std", + "pallet-evm-precompile-simple/std", + "pallet-evm/std", + "pallet-proxy/std", + "pallet-subtensor/std", + "precompile-utils/std", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", + "subtensor-runtime-common/std", +] diff --git a/precompiles/src/balance_transfer.rs b/precompiles/src/balance_transfer.rs new file mode 100644 index 0000000000..83897bdfeb --- /dev/null +++ b/precompiles/src/balance_transfer.rs @@ -0,0 +1,64 @@ +use core::marker::PhantomData; + +use frame_support::dispatch::{GetDispatchInfo, PostDispatchInfo}; +use pallet_evm::PrecompileHandle; +use precompile_utils::EvmResult; +use sp_core::{H256, U256}; +use sp_runtime::traits::{Dispatchable, StaticLookup, UniqueSaturatedInto}; + +use crate::{PrecompileExt, PrecompileHandleExt, contract_to_origin, parse_pubkey}; + +pub(crate) struct BalanceTransferPrecompile(PhantomData); + +impl PrecompileExt for BalanceTransferPrecompile +where + R: frame_system::Config + pallet_balances::Config + pallet_evm::Config, + R::AccountId: From<[u8; 32]>, + ::RuntimeCall: + GetDispatchInfo + Dispatchable, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable, + <::Lookup as StaticLookup>::Source: From, + ::Balance: From, +{ + const INDEX: u64 = 2048; + const ADDRESS_SS58: [u8; 32] = [ + 0x07, 0xec, 0x71, 0x2a, 0x5d, 0x38, 0x43, 0x4d, 0xdd, 0x03, 0x3f, 0x8f, 0x02, 0x4e, 0xcd, + 0xfc, 0x4b, 0xb5, 0x95, 0x1c, 0x13, 0xc3, 0x08, 0x5c, 0x39, 0x9c, 0x8a, 0x5f, 0x62, 0x93, + 0x70, 0x5d, + ]; +} + +#[precompile_utils::precompile] +impl BalanceTransferPrecompile +where + R: frame_system::Config + pallet_balances::Config + pallet_evm::Config, + R::AccountId: From<[u8; 32]>, + ::RuntimeCall: + GetDispatchInfo + Dispatchable, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable, + <::Lookup as StaticLookup>::Source: From, + ::Balance: From, +{ + #[precompile::public("transfer(bytes32)")] + #[precompile::payable] + fn transfer(handle: &mut impl PrecompileHandle, address: H256) -> EvmResult<()> { + let amount_sub = handle.try_convert_apparent_value::()?; + + if amount_sub.is_zero() { + return Ok(()); + } + + let dest = parse_pubkey::(address.as_bytes())?.0.into(); + + let call = pallet_balances::Call::::transfer_allow_death { + dest, + value: amount_sub.unique_saturated_into(), + }; + + handle.try_dispatch_runtime_call::(call, contract_to_origin(&Self::ADDRESS_SS58)?) + } +} diff --git a/precompiles/src/ed25519.rs b/precompiles/src/ed25519.rs new file mode 100644 index 0000000000..236da80a27 --- /dev/null +++ b/precompiles/src/ed25519.rs @@ -0,0 +1,48 @@ +extern crate alloc; + +use alloc::vec::Vec; + +use ed25519_dalek::{Signature, Verifier, VerifyingKey}; +use fp_evm::{ExitError, ExitSucceed, LinearCostPrecompile, PrecompileFailure}; + +use crate::{PrecompileExt, parse_slice}; + +pub(crate) struct Ed25519Verify; + +impl PrecompileExt for Ed25519Verify { + const INDEX: u64 = 1026; + const ADDRESS_SS58: [u8; 32] = [0; 32]; +} + +impl LinearCostPrecompile for Ed25519Verify { + const BASE: u64 = 15; + const WORD: u64 = 3; + + fn execute(input: &[u8], _: u64) -> Result<(ExitSucceed, Vec), PrecompileFailure> { + if input.len() < 132 { + return Err(PrecompileFailure::Error { + exit_status: ExitError::Other("input must contain 128 bytes".into()), + }); + }; + + let mut buf = [0u8; 32]; + + let msg = parse_slice(input, 4, 36)?; + let pk = VerifyingKey::try_from(parse_slice(input, 36, 68)?).map_err(|_| { + PrecompileFailure::Error { + exit_status: ExitError::Other("Public key recover failed".into()), + } + })?; + let sig = Signature::try_from(parse_slice(input, 68, 132)?).map_err(|_| { + PrecompileFailure::Error { + exit_status: ExitError::Other("Signature recover failed".into()), + } + })?; + + if pk.verify(msg, &sig).is_ok() { + buf[31] = 1u8; + }; + + Ok((ExitSucceed::Returned, buf.to_vec())) + } +} diff --git a/precompiles/src/lib.rs b/precompiles/src/lib.rs new file mode 100644 index 0000000000..b69a2ec6b8 --- /dev/null +++ b/precompiles/src/lib.rs @@ -0,0 +1,349 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; + +use alloc::format; +use core::marker::PhantomData; + +use frame_support::dispatch::{GetDispatchInfo, Pays, PostDispatchInfo}; +use frame_system::RawOrigin; +use pallet_evm::{ + AddressMapping, BalanceConverter, ExitError, GasWeightMapping, HashedAddressMapping, + IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, + PrecompileSet, +}; +use pallet_evm_precompile_modexp::Modexp; +use pallet_evm_precompile_sha3fips::Sha3FIPS256; +use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256}; +use precompile_utils::EvmResult; +use sp_core::{H160, U256, crypto::ByteArray}; +use sp_runtime::traits::{BlakeTwo256, StaticLookup}; +use sp_runtime::{AccountId32, traits::Dispatchable}; +use subtensor_runtime_common::ProxyType; + +use pallet_admin_utils::{PrecompileEnable, PrecompileEnum}; +use sp_std::vec; + +use crate::balance_transfer::*; +use crate::ed25519::*; +use crate::metagraph::*; +use crate::neuron::*; +use crate::staking::*; +use crate::subnet::*; + +mod balance_transfer; +mod ed25519; +mod metagraph; +mod neuron; +mod staking; +mod subnet; + +pub struct Precompiles(PhantomData); + +impl Default for Precompiles +where + R: frame_system::Config + + pallet_evm::Config + + pallet_balances::Config + + pallet_admin_utils::Config + + pallet_subtensor::Config + + pallet_proxy::Config, + R::AccountId: From<[u8; 32]> + ByteArray, + ::RuntimeCall: From> + + From> + + From> + + From> + + GetDispatchInfo + + Dispatchable, + ::AddressMapping: AddressMapping, + ::Balance: From, + <::Lookup as StaticLookup>::Source: From, +{ + fn default() -> Self { + Self::new() + } +} + +impl Precompiles +where + R: frame_system::Config + + pallet_evm::Config + + pallet_balances::Config + + pallet_admin_utils::Config + + pallet_subtensor::Config + + pallet_proxy::Config, + R::AccountId: From<[u8; 32]> + ByteArray, + ::RuntimeCall: From> + + From> + + From> + + From> + + GetDispatchInfo + + Dispatchable, + ::AddressMapping: AddressMapping, + ::Balance: From, + <::Lookup as StaticLookup>::Source: From, +{ + pub fn new() -> Self { + Self(Default::default()) + } + + pub fn used_addresses() -> [H160; 13] { + [ + hash(1), + hash(2), + hash(3), + hash(4), + hash(5), + hash(1024), + hash(1025), + hash(Ed25519Verify::INDEX), + hash(BalanceTransferPrecompile::::INDEX), + hash(StakingPrecompile::::INDEX), + hash(SubnetPrecompile::::INDEX), + hash(MetagraphPrecompile::::INDEX), + hash(NeuronPrecompile::::INDEX), + ] + } +} +impl PrecompileSet for Precompiles +where + R: frame_system::Config + + pallet_evm::Config + + pallet_balances::Config + + pallet_admin_utils::Config + + pallet_subtensor::Config + + pallet_proxy::Config, + R::AccountId: From<[u8; 32]> + ByteArray, + ::RuntimeCall: From> + + From> + + From> + + From> + + GetDispatchInfo + + Dispatchable, + ::AddressMapping: AddressMapping, + ::Balance: From, + <::Lookup as StaticLookup>::Source: From, +{ + fn execute(&self, handle: &mut impl PrecompileHandle) -> Option { + match handle.code_address() { + // Ethereum precompiles : + a if a == hash(1) => Some(ECRecover::execute(handle)), + a if a == hash(2) => Some(Sha256::execute(handle)), + a if a == hash(3) => Some(Ripemd160::execute(handle)), + a if a == hash(4) => Some(Identity::execute(handle)), + a if a == hash(5) => Some(Modexp::execute(handle)), + // Non-Frontier specific nor Ethereum precompiles : + a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), + a if a == hash(1025) => Some(ECRecoverPublicKey::execute(handle)), + a if a == hash(Ed25519Verify::INDEX) => Some(Ed25519Verify::execute(handle)), + // Subtensor specific precompiles : + a if a == hash(BalanceTransferPrecompile::::INDEX) => { + if PrecompileEnable::::get(PrecompileEnum::BalanceTransfer) { + Some(BalanceTransferPrecompile::::execute(handle)) + } else { + Some(Err(PrecompileFailure::Error { + exit_status: ExitError::Other( + "Precompile Balance Transfer is disabled".into(), + ), + })) + } + } + a if a == hash(StakingPrecompile::::INDEX) => { + if PrecompileEnable::::get(PrecompileEnum::Staking) { + Some(StakingPrecompile::::execute(handle)) + } else { + Some(Err(PrecompileFailure::Error { + exit_status: ExitError::Other( + "Precompile Balance Transfer is disabled".into(), + ), + })) + } + } + + a if a == hash(SubnetPrecompile::::INDEX) => { + if PrecompileEnable::::get(PrecompileEnum::Subnet) { + Some(SubnetPrecompile::::execute(handle)) + } else { + Some(Err(PrecompileFailure::Error { + exit_status: ExitError::Other("Precompile Subnet is disabled".into()), + })) + } + } + a if a == hash(MetagraphPrecompile::::INDEX) => { + if PrecompileEnable::::get(PrecompileEnum::Metagraph) { + Some(MetagraphPrecompile::::execute(handle)) + } else { + Some(Err(PrecompileFailure::Error { + exit_status: ExitError::Other("Precompile Metagrah is disabled".into()), + })) + } + } + a if a == hash(NeuronPrecompile::::INDEX) => { + if PrecompileEnable::::get(PrecompileEnum::Neuron) { + Some(NeuronPrecompile::::execute(handle)) + } else { + Some(Err(PrecompileFailure::Error { + exit_status: ExitError::Other("Precompile Neuron is disabled".into()), + })) + } + } + _ => None, + } + } + + fn is_precompile(&self, address: H160, _gas: u64) -> IsPrecompileResult { + IsPrecompileResult::Answer { + is_precompile: Self::used_addresses().contains(&address), + extra_cost: 0, + } + } +} + +fn hash(a: u64) -> H160 { + H160::from_low_u64_be(a) +} + +/// Takes a slice from bytes with PrecompileFailure as Error +fn parse_slice(data: &[u8], from: usize, to: usize) -> Result<&[u8], PrecompileFailure> { + let maybe_slice = data.get(from..to); + if let Some(slice) = maybe_slice { + Ok(slice) + } else { + log::error!( + "fail to get slice from data, {:?}, from {}, to {}", + &data, + from, + to + ); + Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }) + } +} + +fn parse_pubkey>(data: &[u8]) -> Result<(A, vec::Vec), PrecompileFailure> { + let mut pubkey = [0u8; 32]; + pubkey.copy_from_slice(parse_slice(data, 0, 32)?); + + Ok(( + pubkey.into(), + data.get(32..) + .map_or_else(vec::Vec::new, |slice| slice.to_vec()), + )) +} + +fn contract_to_origin>( + contract: &[u8; 32], +) -> Result, PrecompileFailure> { + let (account_id, _) = parse_pubkey::(contract)?; + Ok(RawOrigin::Signed(account_id)) +} + +fn try_u16_from_u256(value: U256) -> Result { + value.try_into().map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::Other("the value is outside of u16 bounds".into()), + }) +} + +trait PrecompileHandleExt: PrecompileHandle { + fn caller_account_id(&self) -> R::AccountId + where + R: frame_system::Config + pallet_evm::Config, + ::AddressMapping: AddressMapping, + { + ::AddressMapping::into_account_id(self.context().caller) + } + + fn try_convert_apparent_value(&self) -> EvmResult + where + R: pallet_evm::Config, + { + let amount = self.context().apparent_value; + ::BalanceConverter::into_substrate_balance(amount).ok_or( + PrecompileFailure::Error { + exit_status: ExitError::Other( + "error converting balance from ETH to subtensor".into(), + ), + }, + ) + } + + /// Dispatches a runtime call, but also checks and records the gas costs. + fn try_dispatch_runtime_call( + &mut self, + call: Call, + origin: RawOrigin, + ) -> EvmResult<()> + where + R: frame_system::Config + pallet_evm::Config, + R::RuntimeCall: From, + R::RuntimeCall: GetDispatchInfo + Dispatchable, + R::RuntimeOrigin: From>, + { + let call = R::RuntimeCall::from(call); + let info = GetDispatchInfo::get_dispatch_info(&call); + + let target_gas = self.gas_limit(); + if let Some(gas) = target_gas { + let valid_weight = + ::GasWeightMapping::gas_to_weight(gas, false).ref_time(); + if info.weight.ref_time() > valid_weight { + return Err(PrecompileFailure::Error { + exit_status: ExitError::OutOfGas, + }); + } + } + + self.record_external_cost( + Some(info.weight.ref_time()), + Some(info.weight.proof_size()), + None, + )?; + + match call.dispatch(R::RuntimeOrigin::from(origin)) { + Ok(post_info) => { + if post_info.pays_fee(&info) == Pays::Yes { + let actual_weight = post_info.actual_weight.unwrap_or(info.weight); + let cost = + ::GasWeightMapping::weight_to_gas(actual_weight); + self.record_cost(cost)?; + + self.refund_external_cost( + Some( + info.weight + .ref_time() + .saturating_sub(actual_weight.ref_time()), + ), + Some( + info.weight + .proof_size() + .saturating_sub(actual_weight.proof_size()), + ), + ); + } + + log::info!("Dispatch succeeded. Post info: {:?}", post_info); + + Ok(()) + } + Err(e) => { + log::error!("Dispatch failed. Error: {:?}", e); + log::warn!("Returning error PrecompileFailure::Error"); + Err(PrecompileFailure::Error { + exit_status: ExitError::Other( + format!("dispatch execution failed: {}", <&'static str>::from(e)).into(), + ), + }) + } + } + } +} + +impl PrecompileHandleExt for T where T: PrecompileHandle {} + +trait PrecompileExt: Precompile { + const INDEX: u64; + // ss58 public key i.e., the contract sends funds it received to the destination address from + // the method parameter. + const ADDRESS_SS58: [u8; 32]; +} diff --git a/precompiles/src/metagraph.rs b/precompiles/src/metagraph.rs new file mode 100644 index 0000000000..a5a70e12f3 --- /dev/null +++ b/precompiles/src/metagraph.rs @@ -0,0 +1,184 @@ +use alloc::string::String; +use core::marker::PhantomData; + +use fp_evm::{ExitError, PrecompileFailure, PrecompileHandle}; +use pallet_subtensor::AxonInfo as SubtensorModuleAxonInfo; +use precompile_utils::{EvmResult, solidity::Codec}; +use sp_core::{ByteArray, H256}; + +use crate::PrecompileExt; + +pub struct MetagraphPrecompile(PhantomData); + +impl PrecompileExt for MetagraphPrecompile +where + R: frame_system::Config + pallet_subtensor::Config, + R::AccountId: ByteArray, +{ + const INDEX: u64 = 2050; + const ADDRESS_SS58: [u8; 32] = [0; 32]; +} + +#[precompile_utils::precompile] +impl MetagraphPrecompile +where + R: frame_system::Config + pallet_subtensor::Config, + R::AccountId: ByteArray, +{ + #[precompile::public("getUidCount(uint16)")] + #[precompile::view] + fn get_uid_count(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::SubnetworkN::::get(netuid)) + } + + #[precompile::public("getStake(uint16,uint16)")] + #[precompile::view] + fn get_stake(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) + .map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + })?; + + Ok(pallet_subtensor::Pallet::::get_total_stake_for_hotkey( + &hotkey, + )) + } + + #[precompile::public("getRank(uint16,uint16)")] + #[precompile::view] + fn get_rank(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_rank_for_uid(netuid, uid)) + } + + #[precompile::public("getTrust(uint16,uint16)")] + #[precompile::view] + fn get_trust(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_trust_for_uid( + netuid, uid, + )) + } + + #[precompile::public("getConsensus(uint16,uint16)")] + #[precompile::view] + fn get_consensus(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_consensus_for_uid( + netuid, uid, + )) + } + + #[precompile::public("getIncentive(uint16,uint16)")] + #[precompile::view] + fn get_incentive(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_incentive_for_uid( + netuid, uid, + )) + } + + #[precompile::public("getDividends(uint16,uint16)")] + #[precompile::view] + fn get_dividends(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_dividends_for_uid( + netuid, uid, + )) + } + + #[precompile::public("getEmission(uint16,uint16)")] + #[precompile::view] + fn get_emission(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_emission_for_uid( + netuid, uid, + )) + } + + #[precompile::public("getVtrust(uint16,uint16)")] + #[precompile::view] + fn get_vtrust(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_validator_trust_for_uid( + netuid, uid, + )) + } + + #[precompile::public("getValidatorStatus(uint16,uint16)")] + #[precompile::view] + fn get_validator_status( + _: &mut impl PrecompileHandle, + netuid: u16, + uid: u16, + ) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_validator_permit_for_uid( + netuid, uid, + )) + } + + #[precompile::public("getLastUpdate(uint16,uint16)")] + #[precompile::view] + fn get_last_update(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_last_update_for_uid( + netuid, uid, + )) + } + + #[precompile::public("getIsActive(uint16,uint16)")] + #[precompile::view] + fn get_is_active(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_active_for_uid( + netuid, uid, + )) + } + + #[precompile::public("getAxon(uint16,uint16)")] + #[precompile::view] + fn get_axon(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) + .map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::Other("hotkey not found".into()), + })?; + + Ok(pallet_subtensor::Pallet::::get_axon_info(netuid, &hotkey).into()) + } + + #[precompile::public("getHotkey(uint16,uint16)")] + #[precompile::view] + fn get_hotkey(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) + .map(|acc| H256::from_slice(acc.as_slice())) + .map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }) + } + + #[precompile::public("getColdkey(uint16,uint16)")] + #[precompile::view] + fn get_coldkey(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) + .map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + })?; + let coldkey = pallet_subtensor::Owner::::get(&hotkey); + + Ok(H256::from_slice(coldkey.as_slice())) + } +} + +#[derive(Codec)] +struct AxonInfo { + block: u64, + version: u32, + ip: u128, + port: u16, + ip_type: u8, + protocol: u8, +} + +impl From for AxonInfo { + fn from(value: SubtensorModuleAxonInfo) -> Self { + Self { + block: value.block, + version: value.version, + ip: value.ip, + port: value.port, + ip_type: value.ip_type, + protocol: value.protocol, + } + } +} diff --git a/precompiles/src/neuron.rs b/precompiles/src/neuron.rs new file mode 100644 index 0000000000..e4c1895543 --- /dev/null +++ b/precompiles/src/neuron.rs @@ -0,0 +1,210 @@ +use core::marker::PhantomData; + +use frame_support::dispatch::{GetDispatchInfo, PostDispatchInfo}; +use frame_system::RawOrigin; +use pallet_evm::{AddressMapping, PrecompileHandle}; +use precompile_utils::{EvmResult, prelude::UnboundedBytes}; +use sp_core::H256; +use sp_runtime::traits::Dispatchable; +use sp_std::vec::Vec; + +use crate::{PrecompileExt, PrecompileHandleExt, parse_pubkey}; + +pub struct NeuronPrecompile(PhantomData); + +impl PrecompileExt for NeuronPrecompile +where + R: frame_system::Config + pallet_evm::Config + pallet_subtensor::Config, + R::AccountId: From<[u8; 32]>, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable, + ::AddressMapping: AddressMapping, +{ + const INDEX: u64 = 2052; + const ADDRESS_SS58: [u8; 32] = [ + 0xbc, 0x46, 0x35, 0x79, 0xbc, 0x99, 0xf9, 0xee, 0x7c, 0x59, 0xed, 0xee, 0x20, 0x61, 0xa3, + 0x09, 0xd2, 0x1e, 0x68, 0xd5, 0x39, 0xb6, 0x40, 0xec, 0x66, 0x46, 0x90, 0x30, 0xab, 0x74, + 0xc1, 0xdb, + ]; +} + +#[precompile_utils::precompile] +impl NeuronPrecompile +where + R: frame_system::Config + pallet_evm::Config + pallet_subtensor::Config, + R::AccountId: From<[u8; 32]>, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable, + ::AddressMapping: AddressMapping, +{ + #[precompile::public("setWeights(uint16,uint16[],uint16[],uint64)")] + #[precompile::payable] + pub fn set_weights( + handle: &mut impl PrecompileHandle, + netuid: u16, + dests: Vec, + weights: Vec, + version_key: u64, + ) -> EvmResult<()> { + let call = pallet_subtensor::Call::::set_weights { + netuid, + dests, + weights, + version_key, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("commitWeights(uint16,bytes32)")] + #[precompile::payable] + pub fn commit_weights( + handle: &mut impl PrecompileHandle, + netuid: u16, + commit_hash: H256, + ) -> EvmResult<()> { + let call = pallet_subtensor::Call::::commit_weights { + netuid, + commit_hash, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("revealWeights(uint16,uint16[],uint16[],uint16[],uint64)")] + #[precompile::payable] + pub fn reveal_weights( + handle: &mut impl PrecompileHandle, + netuid: u16, + uids: Vec, + values: Vec, + salt: Vec, + version_key: u64, + ) -> EvmResult<()> { + let call = pallet_subtensor::Call::::reveal_weights { + netuid, + uids, + values, + salt, + version_key, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("burnedRegister(uint16,bytes32)")] + #[precompile::payable] + fn burned_register( + handle: &mut impl PrecompileHandle, + netuid: u16, + hotkey: H256, + ) -> EvmResult<()> { + let coldkey = handle.caller_account_id::(); + let (hotkey, _) = parse_pubkey(hotkey.as_bytes())?; + let call = pallet_subtensor::Call::::burned_register { netuid, hotkey }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(coldkey)) + } + + #[precompile::public("serveAxon(uint16,uint32,uint128,uint16,uint8,uint8,uint8,uint8)")] + #[precompile::payable] + #[allow(clippy::too_many_arguments)] + fn serve_axon( + handle: &mut impl PrecompileHandle, + netuid: u16, + version: u32, + ip: u128, + port: u16, + ip_type: u8, + protocol: u8, + placeholder1: u8, + placeholder2: u8, + ) -> EvmResult<()> { + let call = pallet_subtensor::Call::::serve_axon { + netuid, + version, + ip, + port, + ip_type, + protocol, + placeholder1, + placeholder2, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public( + "serveAxonTls(uint16,uint32,uint128,uint16,uint8,uint8,uint8,uint8,bytes)" + )] + #[precompile::payable] + #[allow(clippy::too_many_arguments)] + fn serve_axon_tls( + handle: &mut impl PrecompileHandle, + netuid: u16, + version: u32, + ip: u128, + port: u16, + ip_type: u8, + protocol: u8, + placeholder1: u8, + placeholder2: u8, + certificate: UnboundedBytes, + ) -> EvmResult<()> { + let call = pallet_subtensor::Call::::serve_axon_tls { + netuid, + version, + ip, + port, + ip_type, + protocol, + placeholder1, + placeholder2, + certificate: certificate.into(), + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("servePrometheus(uint16,uint32,uint128,uint16,uint8)")] + #[precompile::payable] + #[allow(clippy::too_many_arguments)] + fn serve_prometheus( + handle: &mut impl PrecompileHandle, + netuid: u16, + version: u32, + ip: u128, + port: u16, + ip_type: u8, + ) -> EvmResult<()> { + let call = pallet_subtensor::Call::::serve_prometheus { + netuid, + version, + ip, + port, + ip_type, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } +} diff --git a/precompiles/src/solidity/balanceTransfer.abi b/precompiles/src/solidity/balanceTransfer.abi new file mode 100644 index 0000000000..99913b9005 --- /dev/null +++ b/precompiles/src/solidity/balanceTransfer.abi @@ -0,0 +1,15 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "data", + "type": "bytes32" + } + ], + "name": "transfer", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] \ No newline at end of file diff --git a/precompiles/src/solidity/balanceTransfer.sol b/precompiles/src/solidity/balanceTransfer.sol new file mode 100644 index 0000000000..42790b9005 --- /dev/null +++ b/precompiles/src/solidity/balanceTransfer.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.8.0; + +address constant ISUBTENSOR_BALANCE_TRANSFER_ADDRESS = 0x0000000000000000000000000000000000000800; + +interface ISubtensorBalanceTransfer { + function transfer(bytes32 data) external payable; +} \ No newline at end of file diff --git a/precompiles/src/solidity/ed25519Verify.abi b/precompiles/src/solidity/ed25519Verify.abi new file mode 100644 index 0000000000..05d75ae6cc --- /dev/null +++ b/precompiles/src/solidity/ed25519Verify.abi @@ -0,0 +1,14 @@ +[ + { + "inputs": [ + { "internalType": "bytes32", "name": "message", "type": "bytes32" }, + { "internalType": "bytes32", "name": "publicKey", "type": "bytes32" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "name": "verify", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "pure", + "type": "function" + } +] \ No newline at end of file diff --git a/precompiles/src/solidity/ed25519Verify.sol b/precompiles/src/solidity/ed25519Verify.sol new file mode 100644 index 0000000000..035feb4cc4 --- /dev/null +++ b/precompiles/src/solidity/ed25519Verify.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.0; + +address constant IED25519VERIFY_ADDRESS = 0x0000000000000000000000000000000000000402; + +interface IEd25519Verify { + /** + * @dev Verifies Ed25519 signature using provided message and public key. + * + * @param message The 32-byte signature payload message. + * @param publicKey 32-byte public key matching to private key used to sign the message. + * @param r The Ed25519 signature commitment (first 32 bytes). + * @param s The Ed25519 signature response (second 32 bytes). + * @return bool Returns true if the signature is valid for the given message and public key, false otherwise. + */ + function verify(bytes32 message, bytes32 publicKey, bytes32 r, bytes32 s) external pure returns (bool); +} diff --git a/precompiles/src/solidity/metagraph.abi b/precompiles/src/solidity/metagraph.abi new file mode 100644 index 0000000000..eb4b9be6ab --- /dev/null +++ b/precompiles/src/solidity/metagraph.abi @@ -0,0 +1,389 @@ +[ + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getAxon", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "block", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "version", + "type": "uint32" + }, + { + "internalType": "uint128", + "name": "ip", + "type": "uint128" + }, + { + "internalType": "uint16", + "name": "port", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "ip_type", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "protocol", + "type": "uint8" + } + ], + "internalType": "struct AxonInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getColdkey", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getConsensus", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getDividends", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getEmission", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getHotkey", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getIncentive", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getIsActive", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getLastUpdate", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getRank", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getStake", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getTrust", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getUidCount", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getValidatorStatus", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getVtrust", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/precompiles/src/solidity/metagraph.sol b/precompiles/src/solidity/metagraph.sol new file mode 100644 index 0000000000..3a19281a57 --- /dev/null +++ b/precompiles/src/solidity/metagraph.sol @@ -0,0 +1,134 @@ +pragma solidity ^0.8.0; + +address constant IMetagraph_ADDRESS = 0x0000000000000000000000000000000000000802; + +struct AxonInfo { + uint64 block; + uint32 version; + uint128 ip; + uint16 port; + uint8 ip_type; + uint8 protocol; +} + +interface IMetagraph { + + /** + * @dev Returns the count of unique identifiers (UIDs) associated with a given network identifier (netuid). + * @param netuid The network identifier for which to retrieve the UID count. + * @return The count of UIDs associated with the specified netuid. + */ + function getUidCount(uint16 netuid) external view returns (uint16); + + /** + * @dev Retrieves the stake amount associated with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the stake. + * @param uid The unique identifier for which to retrieve the stake. + * @return The stake amount associated with the specified netuid and uid. + */ + function getStake(uint16 netuid, uint16 uid) external view returns (uint64); + + /** + * @dev Retrieves the rank of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the rank. + * @param uid The unique identifier for which to retrieve the rank. + * @return The rank of the node with the specified netuid and uid. + */ + function getRank(uint16 netuid, uint16 uid) external view returns (uint16); + + /** + * @dev Retrieves the trust value of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the trust value. + * @param uid The unique identifier for which to retrieve the trust value. + * @return The trust value of the node with the specified netuid and uid. + */ + function getTrust(uint16 netuid, uint16 uid) external view returns (uint16); + + /** + * @dev Retrieves the consensus value of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the consensus value. + * @param uid The unique identifier for which to retrieve the consensus value. + * @return The consensus value of the node with the specified netuid and uid. + */ + function getConsensus(uint16 netuid, uint16 uid) external view returns (uint16); + + /** + * @dev Retrieves the incentive value of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the incentive value. + * @param uid The unique identifier for which to retrieve the incentive value. + * @return The incentive value of the node with the specified netuid and uid. + */ + function getIncentive(uint16 netuid, uint16 uid) external view returns (uint16); + + /** + * @dev Retrieves the dividend value of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the dividend value. + * @param uid The unique identifier for which to retrieve the dividend value. + * @return The dividend value of the node with the specified netuid and uid. + */ + function getDividends(uint16 netuid, uint16 uid) external view returns (uint16); + + /** + * @dev Retrieves the emission value of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the emission value. + * @param uid The unique identifier for which to retrieve the emission value. + * @return The emission value of the node with the specified netuid and uid. + */ + function getEmission(uint16 netuid, uint16 uid) external view returns (uint64); + + /** + * @dev Retrieves the v-trust value of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the v-trust value. + * @param uid The unique identifier for which to retrieve the v-trust value. + * @return The v-trust value of the node with the specified netuid and uid. + */ + function getVtrust(uint16 netuid, uint16 uid) external view returns (uint16); + + /** + * @dev Checks the validator status of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to check the validator status. + * @param uid The unique identifier for which to check the validator status. + * @return Returns true if the node is a validator, false otherwise. + */ + function getValidatorStatus(uint16 netuid, uint16 uid) external view returns (bool); + + /** + * @dev Retrieves the last update timestamp of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the last update timestamp. + * @param uid The unique identifier for which to retrieve the last update timestamp. + * @return The last update timestamp of the node with the specified netuid and uid. + */ + function getLastUpdate(uint16 netuid, uint16 uid) external view returns (uint64); + + /** + * @dev Checks if a node with a given network identifier (netuid) and unique identifier (uid) is active. + * @param netuid The network identifier for which to check the node's activity. + * @param uid The unique identifier for which to check the node's activity. + * @return Returns true if the node is active, false otherwise. + */ + function getIsActive(uint16 netuid, uint16 uid) external view returns (bool); + + /** + * @dev Retrieves the axon information of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the axon information. + * @param uid The unique identifier for which to retrieve the axon information. + * @return The axon information of the node with the specified netuid and uid. + */ + function getAxon(uint16 netuid, uint16 uid) external view returns (AxonInfo memory); + + /** + * @dev Retrieves the hotkey of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the hotkey. + * @param uid The unique identifier for which to retrieve the hotkey. + * @return The hotkey of the node with the specified netuid and uid. + */ + function getHotkey(uint16 netuid, uint16 uid) external view returns (bytes32); + + /** + * @dev Retrieves the coldkey of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the coldkey. + * @param uid The unique identifier for which to retrieve the coldkey. + * @return The coldkey of the node with the specified netuid and uid. + */ + function getColdkey(uint16 netuid, uint16 uid) external view returns (bytes32); +} diff --git a/precompiles/src/solidity/neuron.abi b/precompiles/src/solidity/neuron.abi new file mode 100644 index 0000000000..e4ffb6fa18 --- /dev/null +++ b/precompiles/src/solidity/neuron.abi @@ -0,0 +1,233 @@ +[ + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "burnedRegister", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "commitHash", + "type": "bytes32" + } + ], + "name": "commitWeights", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16[]", + "name": "uids", + "type": "uint16[]" + }, + { + "internalType": "uint16[]", + "name": "values", + "type": "uint16[]" + }, + { + "internalType": "uint16[]", + "name": "salt", + "type": "uint16[]" + }, + { + "internalType": "uint64", + "name": "versionKey", + "type": "uint64" + } + ], + "name": "revealWeights", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "version", + "type": "uint32" + }, + { + "internalType": "uint128", + "name": "ip", + "type": "uint128" + }, + { + "internalType": "uint16", + "name": "port", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "ipType", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "protocol", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "placeholder1", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "placeholder2", + "type": "uint8" + } + ], + "name": "serveAxon", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "version", + "type": "uint32" + }, + { + "internalType": "uint128", + "name": "ip", + "type": "uint128" + }, + { + "internalType": "uint16", + "name": "port", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "ipType", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "protocol", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "placeholder1", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "placeholder2", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "certificate", + "type": "bytes" + } + ], + "name": "serveAxonTls", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "version", + "type": "uint32" + }, + { + "internalType": "uint128", + "name": "ip", + "type": "uint128" + }, + { + "internalType": "uint16", + "name": "port", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "ipType", + "type": "uint8" + } + ], + "name": "servePrometheus", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16[]", + "name": "dests", + "type": "uint16[]" + }, + { + "internalType": "uint16[]", + "name": "weights", + "type": "uint16[]" + }, + { + "internalType": "uint64", + "name": "versionKey", + "type": "uint64" + } + ], + "name": "setWeights", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/precompiles/src/solidity/neuron.sol b/precompiles/src/solidity/neuron.sol new file mode 100644 index 0000000000..204bc3f600 --- /dev/null +++ b/precompiles/src/solidity/neuron.sol @@ -0,0 +1,122 @@ +pragma solidity ^0.8.0; + +address constant INeuron_ADDRESS = 0x0000000000000000000000000000000000000804; + +interface INeuron { + /** + * @dev Registers a neuron by calling `do_burned_registration` internally with the origin set to the ss58 mirror of the H160 address. + * This allows the H160 to further call neuron-related methods and receive emissions. + * + * @param netuid The subnet to register the neuron to (uint16). + * @param hotkey The hotkey public key (32 bytes). + */ + function burnedRegister(uint16 netuid, bytes32 hotkey) external payable; + + /** + * @dev Registers axon information for a neuron. + * This function is used to serve axon information, including the subnet to register to, version, IP address, port, IP type, protocol, and placeholders for future use. + * + * @param netuid The subnet to register the axon to (uint16). + * @param version The version of the axon (uint32). + * @param ip The IP address of the axon (uint128). + * @param port The port number of the axon (uint16). + * @param ipType The type of IP address (uint8). + * @param protocol The protocol used by the axon (uint8). + * @param placeholder1 Placeholder for future use (uint8). + * @param placeholder2 Placeholder for future use (uint8). + */ + function serveAxon( + uint16 netuid, + uint32 version, + uint128 ip, + uint16 port, + uint8 ipType, + uint8 protocol, + uint8 placeholder1, + uint8 placeholder2 + ) external payable; + + /** + * @dev Serves axon information for a neuron over TLS. + * This function is used to serve axon information, including the subnet to register to, version, IP address, port, IP type, protocol, and placeholders for future use. + * + * @param netuid The subnet to register the axon to (uint16). + * @param version The version of the axon (uint32). + * @param ip The IP address of the axon (uint128). + * @param port The port number of the axon (uint16). + * @param ipType The type of IP address (uint8). + * @param protocol The protocol used by the axon (uint8). + * @param placeholder1 Placeholder for future use (uint8). + * @param placeholder2 Placeholder for future use (uint8). + * @param certificate The TLS certificate for the axon (bytes). + */ + function serveAxonTls( + uint16 netuid, + uint32 version, + uint128 ip, + uint16 port, + uint8 ipType, + uint8 protocol, + uint8 placeholder1, + uint8 placeholder2, + bytes memory certificate + ) external payable; + + /** + * @dev Serves Prometheus information for a neuron. + * This function is used to serve Prometheus information, including the subnet to register to, version, IP address, port, and IP type. + * + * @param netuid The subnet to register the Prometheus information to (uint16). + * @param version The version of the Prometheus information (uint32). + * @param ip The IP address of the Prometheus information (uint128). + * @param port The port number of the Prometheus information (uint16). + * @param ipType The type of IP address (uint8). + */ + function servePrometheus( + uint16 netuid, + uint32 version, + uint128 ip, + uint16 port, + uint8 ipType + ) external payable; + + /** + * @dev Sets the weights for a neuron. + * + * @param netuid The subnet to set the weights for (uint16). + * @param dests The destinations of the weights (uint16[]). + * @param weights The weights to set (uint16[]). + * @param versionKey The version key for the weights (uint64). + */ + function setWeights( + uint16 netuid, + uint16[] memory dests, + uint16[] memory weights, + uint64 versionKey + ) external payable; + + /** + * @dev Commits the weights for a neuron. + * + * @param netuid The subnet to commit the weights for (uint16). + * @param commitHash The commit hash for the weights (bytes32). + */ + function commitWeights(uint16 netuid, bytes32 commitHash) external payable; + + /** + * @dev Reveals the weights for a neuron. + * + * @param netuid The subnet to reveal the weights for (uint16). + * @param uids The unique identifiers for the weights (uint16[]). + * @param values The values of the weights (uint16[]). + * @param salt The salt values for the weights (uint16[]). + * @param versionKey The version key for the weights (uint64). + */ + function revealWeights( + uint16 netuid, + uint16[] memory uids, + uint16[] memory values, + uint16[] memory salt, + uint64 versionKey + ) external payable; +} diff --git a/precompiles/src/solidity/staking.abi b/precompiles/src/solidity/staking.abi new file mode 100644 index 0000000000..3c4a018c90 --- /dev/null +++ b/precompiles/src/solidity/staking.abi @@ -0,0 +1,98 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "delegate", + "type": "bytes32" + } + ], + "name": "addProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "netuid", + "type": "uint256" + } + ], + "name": "addStake", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "delegate", + "type": "bytes32" + } + ], + "name": "removeProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "netuid", + "type": "uint256" + } + ], + "name": "getStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "netuid", + "type": "uint256" + } + ], + "name": "removeStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/precompiles/src/solidity/staking.sol b/precompiles/src/solidity/staking.sol new file mode 100644 index 0000000000..19d51d0470 --- /dev/null +++ b/precompiles/src/solidity/staking.sol @@ -0,0 +1,79 @@ +pragma solidity ^0.8.0; + +address constant ISTAKING_ADDRESS = 0x0000000000000000000000000000000000000801; + +interface IStaking { + /** + * @dev Adds a subtensor stake corresponding to the value sent with the transaction, associated + * with the `hotkey`. + * + * This function allows external accounts and contracts to stake TAO into the subtensor pallet, + * which effectively calls `add_stake` on the subtensor pallet with specified hotkey as a parameter + * and coldkey being the hashed address mapping of H160 sender address to Substrate ss58 address as + * implemented in Frontier HashedAddressMapping: + * https://github.com/polkadot-evm/frontier/blob/2e219e17a526125da003e64ef22ec037917083fa/frame/evm/src/lib.rs#L739 + * + * @param hotkey The hotkey public key (32 bytes). + * @param netuid The subnet to stake to (uint256). + * + * Requirements: + * - `hotkey` must be a valid hotkey registered on the network, ensuring that the stake is + * correctly attributed. + */ + function addStake(bytes32 hotkey, uint256 netuid) external payable; + + /** + * @dev Removes a subtensor stake `amount` from the specified `hotkey`. + * + * This function allows external accounts and contracts to unstake TAO from the subtensor pallet, + * which effectively calls `remove_stake` on the subtensor pallet with specified hotkey as a parameter + * and coldkey being the hashed address mapping of H160 sender address to Substrate ss58 address as + * implemented in Frontier HashedAddressMapping: + * https://github.com/polkadot-evm/frontier/blob/2e219e17a526125da003e64ef22ec037917083fa/frame/evm/src/lib.rs#L739 + * + * @param hotkey The hotkey public key (32 bytes). + * @param amount The amount to unstake in rao. + * @param netuid The subnet to stake to (uint256). + * + * Requirements: + * - `hotkey` must be a valid hotkey registered on the network, ensuring that the stake is + * correctly attributed. + * - The existing stake amount must be not lower than specified amount + */ + function removeStake( + bytes32 hotkey, + uint256 amount, + uint256 netuid + ) external; + + /** + * @dev Delegates staking to a proxy account. + * + * @param delegate The public key (32 bytes) of the delegate. + */ + function addProxy(bytes32 delegate) external; + + /** + * @dev Removes staking proxy account. + * + * @param delegate The public key (32 bytes) of the delegate. + */ + function removeProxy(bytes32 delegate) external; + + /** + * @dev Returns the stake amount associated with the specified `hotkey` and `coldkey`. + * + * This function retrieves the current stake amount linked to a specific hotkey and coldkey pair. + * It is a view function, meaning it does not modify the state of the contract and is free to call. + * + * @param hotkey The hotkey public key (32 bytes). + * @param coldkey The coldkey public key (32 bytes). + * @param netuid The subnet the stake is on (uint256). + * @return The current stake amount in uint256 format. + */ + function getStake( + bytes32 hotkey, + bytes32 coldkey, + uint256 netuid + ) external view returns (uint256); +} diff --git a/precompiles/src/solidity/subnet.abi b/precompiles/src/solidity/subnet.abi new file mode 100644 index 0000000000..3cc16d9df7 --- /dev/null +++ b/precompiles/src/solidity/subnet.abi @@ -0,0 +1,887 @@ +[ + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getActivityCutoff", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getAdjustmentAlpha", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getAlphaValues", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getBondsMovingAverage", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getCommitRevealWeightsEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getCommitRevealWeightsInterval", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getDifficulty", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "name": "getImmunityPeriod", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "name": "getKappa", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getLiquidAlphaEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getMaxBurn", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getMaxDifficulty", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getMaxWeightLimit", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getMinAllowedWeights", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getMinBurn", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getMinDifficulty", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getNetworkPowRegistrationAllowed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getNetworkRegistrationAllowed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "name": "getRho", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getServingRateLimit", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getWeightsSetRateLimit", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getWeightsVersionKey", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "registerNetwork", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "subnetName", + "type": "string" + }, + { + "internalType": "string", + "name": "githubRepo", + "type": "string" + }, + { + "internalType": "string", + "name": "subnetContact", + "type": "string" + }, + { + "internalType": "string", + "name": "subnetUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "discord", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "string", + "name": "additional", + "type": "string" + } + ], + "name": "registerNetwork", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "activityCutoff", + "type": "uint16" + } + ], + "name": "setActivityCutoff", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "adjustmentAlpha", + "type": "uint64" + } + ], + "name": "setAdjustmentAlpha", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "alphaLow", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "alphaHigh", + "type": "uint16" + } + ], + "name": "setAlphaValues", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "bondsMovingAverage", + "type": "uint64" + } + ], + "name": "setBondsMovingAverage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "commitRevealWeightsEnabled", + "type": "bool" + } + ], + "name": "setCommitRevealWeightsEnabled", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "commitRevealWeightsInterval", + "type": "uint64" + } + ], + "name": "setCommitRevealWeightsInterval", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "difficulty", + "type": "uint64" + } + ], + "name": "setDifficulty", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "immunityPeriod", + "type": "uint16" + } + ], + "name": "setImmunityPeriod", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "kappa", + "type": "uint16" + } + ], + "name": "setKappa", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "liquidAlphaEnabled", + "type": "bool" + } + ], + "name": "setLiquidAlphaEnabled", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "maxBurn", + "type": "uint64" + } + ], + "name": "setMaxBurn", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "maxDifficulty", + "type": "uint64" + } + ], + "name": "setMaxDifficulty", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxWeightLimit", + "type": "uint16" + } + ], + "name": "setMaxWeightLimit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "minAllowedWeights", + "type": "uint16" + } + ], + "name": "setMinAllowedWeights", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "minBurn", + "type": "uint64" + } + ], + "name": "setMinBurn", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "minDifficulty", + "type": "uint64" + } + ], + "name": "setMinDifficulty", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "networkPowRegistrationAllowed", + "type": "bool" + } + ], + "name": "setNetworkPowRegistrationAllowed", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "networkRegistrationAllowed", + "type": "bool" + } + ], + "name": "setNetworkRegistrationAllowed", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "rho", + "type": "uint16" + } + ], + "name": "setRho", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "servingRateLimit", + "type": "uint64" + } + ], + "name": "setServingRateLimit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "weightsSetRateLimit", + "type": "uint64" + } + ], + "name": "setWeightsSetRateLimit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "weightsVersionKey", + "type": "uint64" + } + ], + "name": "setWeightsVersionKey", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/precompiles/src/solidity/subnet.sol b/precompiles/src/solidity/subnet.sol new file mode 100644 index 0000000000..d5ef0916d9 --- /dev/null +++ b/precompiles/src/solidity/subnet.sol @@ -0,0 +1,173 @@ +pragma solidity ^0.8.0; + +address constant ISUBNET_ADDRESS = 0x0000000000000000000000000000000000000803; + +interface ISubnet { + /// Registers a new network without specifying details. + function registerNetwork(bytes32 hotkey) external payable; + /// Registers a new network with specified subnet name, GitHub repository, and contact information. + function registerNetwork( + bytes32 hotkey, + string memory subnetName, + string memory githubRepo, + string memory subnetContact, + string memory subnetUrl, + string memory discord, + string memory description, + string memory additional + ) external payable; + + function getServingRateLimit(uint16 netuid) external view returns (uint64); + + function setServingRateLimit( + uint16 netuid, + uint64 servingRateLimit + ) external payable; + + function getMinDifficulty(uint16 netuid) external view returns (uint64); + + function setMinDifficulty( + uint16 netuid, + uint64 minDifficulty + ) external payable; + + function getMaxDifficulty(uint16 netuid) external view returns (uint64); + + function setMaxDifficulty( + uint16 netuid, + uint64 maxDifficulty + ) external payable; + + function getWeightsVersionKey(uint16 netuid) external view returns (uint64); + + function setWeightsVersionKey( + uint16 netuid, + uint64 weightsVersionKey + ) external payable; + + function getWeightsSetRateLimit( + uint16 netuid + ) external view returns (uint64); + + function setWeightsSetRateLimit( + uint16 netuid, + uint64 weightsSetRateLimit + ) external payable; + + function getAdjustmentAlpha(uint16 netuid) external view returns (uint64); + + function setAdjustmentAlpha( + uint16 netuid, + uint64 adjustmentAlpha + ) external payable; + + function getMaxWeightLimit(uint16 netuid) external view returns (uint16); + + function setMaxWeightLimit( + uint16 netuid, + uint16 maxWeightLimit + ) external payable; + + function getImmunityPeriod(uint16) external view returns (uint16); + + function setImmunityPeriod( + uint16 netuid, + uint64 immunityPeriod + ) external payable; + + function getMinAllowedWeights(uint16 netuid) external view returns (uint16); + + function setMinAllowedWeights( + uint16 netuid, + uint16 minAllowedWeights + ) external payable; + + function getKappa(uint16) external view returns (uint16); + + function setKappa(uint16 netuid, uint16 kappa) external payable; + + function getRho(uint16) external view returns (uint16); + + function setRho(uint16 netuid, uint16 rho) external payable; + + function getActivityCutoff(uint16 netuid) external view returns (uint16); + + function setActivityCutoff( + uint16 netuid, + uint16 activityCutoff + ) external payable; + + function getNetworkRegistrationAllowed( + uint16 netuid + ) external view returns (bool); + + function setNetworkRegistrationAllowed( + uint16 netuid, + bool networkRegistrationAllowed + ) external payable; + + function getNetworkPowRegistrationAllowed( + uint16 netuid + ) external view returns (bool); + + function setNetworkPowRegistrationAllowed( + uint16 netuid, + bool networkPowRegistrationAllowed + ) external payable; + + function getMinBurn(uint16 netuid) external view returns (uint64); + + function setMinBurn(uint16 netuid, uint64 minBurn) external payable; + + function getMaxBurn(uint16 netuid) external view returns (uint64); + + function setMaxBurn(uint16 netuid, uint64 maxBurn) external payable; + + function getDifficulty(uint16 netuid) external view returns (uint64); + + function setDifficulty(uint16 netuid, uint64 difficulty) external payable; + + function getBondsMovingAverage( + uint16 netuid + ) external view returns (uint64); + + function setBondsMovingAverage( + uint16 netuid, + uint64 bondsMovingAverage + ) external payable; + + function getCommitRevealWeightsEnabled( + uint16 netuid + ) external view returns (bool); + + function setCommitRevealWeightsEnabled( + uint16 netuid, + bool commitRevealWeightsEnabled + ) external payable; + + function getLiquidAlphaEnabled(uint16 netuid) external view returns (bool); + + function setLiquidAlphaEnabled( + uint16 netuid, + bool liquidAlphaEnabled + ) external payable; + + function getAlphaValues( + uint16 netuid + ) external view returns (uint16, uint16); + + function setAlphaValues( + uint16 netuid, + uint16 alphaLow, + uint16 alphaHigh + ) external payable; + + function getCommitRevealWeightsInterval( + uint16 netuid + ) external view returns (uint64); + + function setCommitRevealWeightsInterval( + uint16 netuid, + uint64 commitRevealWeightsInterval + ) external payable; +} diff --git a/precompiles/src/staking.rs b/precompiles/src/staking.rs new file mode 100644 index 0000000000..9df3cc74e7 --- /dev/null +++ b/precompiles/src/staking.rs @@ -0,0 +1,206 @@ +// The goal of staking precompile is to allow interaction between EVM users and smart contracts and +// subtensor staking functionality, namely add_stake, and remove_stake extrinsicsk, as well as the +// staking state. +// +// Additional requirement is to preserve compatibility with Ethereum indexers, which requires +// no balance transfers from EVM accounts without a corresponding transaction that can be +// parsed by an indexer. +// +// Implementation of add_stake: +// - User transfers balance that will be staked to the precompile address with a payable +// method addStake. This method also takes hotkey public key (bytes32) of the hotkey +// that the stake should be assigned to. +// - Precompile transfers the balance back to the signing address, and then invokes +// do_add_stake from subtensor pallet with signing origin that mmatches to HashedAddressMapping +// of the message sender, which will effectively withdraw and stake balance from the message +// sender. +// - Precompile checks the result of do_add_stake and, in case of a failure, reverts the transaction, +// and leaves the balance on the message sender account. +// +// Implementation of remove_stake: +// - User involkes removeStake method and specifies hotkey public key (bytes32) of the hotkey +// to remove stake from, and the amount to unstake. +// - Precompile calls do_remove_stake method of the subtensor pallet with the signing origin of message +// sender, which effectively unstakes the specified amount and credits it to the message sender +// - Precompile checks the result of do_remove_stake and, in case of a failure, reverts the transaction. +// + +use core::marker::PhantomData; + +use frame_support::dispatch::{GetDispatchInfo, PostDispatchInfo}; +use frame_system::RawOrigin; +use pallet_evm::{BalanceConverter, AddressMapping, ExitError, PrecompileFailure, PrecompileHandle}; +use precompile_utils::EvmResult; +use sp_core::{H256, U256}; +use sp_runtime::traits::{Dispatchable, StaticLookup, UniqueSaturatedInto}; +use subtensor_runtime_common::ProxyType; + +use crate::{PrecompileExt, PrecompileHandleExt, parse_pubkey, try_u16_from_u256}; + +pub(crate) struct StakingPrecompile(PhantomData); + +impl PrecompileExt for StakingPrecompile +where + R: frame_system::Config + + pallet_evm::Config + + pallet_subtensor::Config + + pallet_proxy::Config + + pallet_balances::Config, + R::AccountId: From<[u8; 32]>, + ::RuntimeCall: From> + + From> + + From> + + GetDispatchInfo + + Dispatchable, + ::AddressMapping: AddressMapping, + ::Balance: From, + <::Lookup as StaticLookup>::Source: From, +{ + const INDEX: u64 = 2049; + const ADDRESS_SS58: [u8; 32] = [ + 0x26, 0xf4, 0x10, 0x1e, 0x52, 0xb7, 0x57, 0x34, 0x33, 0x24, 0x5b, 0xc3, 0x0a, 0xe1, 0x8b, + 0x63, 0x99, 0x53, 0xd8, 0x41, 0x79, 0x33, 0x03, 0x61, 0x4d, 0xfa, 0xcf, 0xf0, 0x37, 0xf7, + 0x12, 0x94, + ]; +} + +#[precompile_utils::precompile] +impl StakingPrecompile +where + R: frame_system::Config + + pallet_evm::Config + + pallet_subtensor::Config + + pallet_proxy::Config + + pallet_balances::Config, + R::AccountId: From<[u8; 32]>, + ::RuntimeCall: From> + + From> + + From> + + GetDispatchInfo + + Dispatchable, + ::AddressMapping: AddressMapping, + ::Balance: From, + <::Lookup as StaticLookup>::Source: From, +{ + #[precompile::public("addStake(bytes32,uint256)")] + #[precompile::payable] + fn add_stake(handle: &mut impl PrecompileHandle, address: H256, netuid: U256) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let amount = handle.context().apparent_value; + + if !amount.is_zero() { + Self::transfer_back_to_caller(&account_id, amount)?; + } + + let amount_sub = handle.try_convert_apparent_value::()?; + let (hotkey, _) = parse_pubkey(address.as_bytes())?; + let netuid = try_u16_from_u256(netuid)?; + let call = pallet_subtensor::Call::::add_stake { + hotkey, + netuid, + amount_staked: amount_sub.unique_saturated_into(), + }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("removeStake(bytes32,uint256,uint256)")] + fn remove_stake( + handle: &mut impl PrecompileHandle, + address: H256, + amount: U256, + netuid: U256, + ) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let (hotkey, _) = parse_pubkey(address.as_bytes())?; + let netuid = try_u16_from_u256(netuid)?; + let amount_unstaked = amount.unique_saturated_into(); + let call = pallet_subtensor::Call::::remove_stake { + hotkey, + netuid, + amount_unstaked, + }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("addProxy(bytes32)")] + fn add_proxy(handle: &mut impl PrecompileHandle, delegate: H256) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let (delegate, _) = parse_pubkey(delegate.as_bytes())?; + let delegate = ::Lookup::unlookup(delegate); + let call = pallet_proxy::Call::::add_proxy { + delegate, + proxy_type: ProxyType::Staking, + delay: 0u32.into(), + }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("removeProxy(bytes32)")] + fn remove_proxy(handle: &mut impl PrecompileHandle, delegate: H256) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let (delegate, _) = parse_pubkey(delegate.as_bytes())?; + let delegate = ::Lookup::unlookup(delegate); + let call = pallet_proxy::Call::::remove_proxy { + delegate, + proxy_type: ProxyType::Staking, + delay: 0u32.into(), + }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("getStake(bytes32,bytes32,uint256)")] + #[precompile::view] + fn get_stake( + _: &mut impl PrecompileHandle, + hotkey: H256, + coldkey: H256, + netuid: U256, + ) -> EvmResult { + let (hotkey, _) = parse_pubkey(hotkey.as_bytes())?; + let (coldkey, _) = parse_pubkey(coldkey.as_bytes())?; + let netuid = try_u16_from_u256(netuid)?; + let stake = pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid, + ); + + Ok(stake.into()) + } + + fn transfer_back_to_caller( + account_id: &::AccountId, + amount: U256, + ) -> Result<(), PrecompileFailure> { + let smart_contract_account_id = R::AccountId::from(Self::ADDRESS_SS58); + let amount_sub = + ::BalanceConverter::into_substrate_balance(amount) + .ok_or(ExitError::OutOfFund)?; + + // Create a transfer call from the smart contract to the caller + let transfer_call = ::RuntimeCall::from( + pallet_balances::Call::::transfer_allow_death { + dest: account_id.clone().into(), + value: amount_sub.unique_saturated_into(), + }, + ); + + // Execute the transfer + let transfer_result = + transfer_call.dispatch(RawOrigin::Signed(smart_contract_account_id).into()); + + if let Err(dispatch_error) = transfer_result { + log::error!( + "Transfer back to caller failed. Error: {:?}", + dispatch_error + ); + return Err(PrecompileFailure::Error { + exit_status: ExitError::Other("Transfer back to caller failed".into()), + }); + } + + Ok(()) + } +} diff --git a/precompiles/src/subnet.rs b/precompiles/src/subnet.rs new file mode 100644 index 0000000000..bcf5d2df00 --- /dev/null +++ b/precompiles/src/subnet.rs @@ -0,0 +1,628 @@ +use core::marker::PhantomData; + +use frame_support::dispatch::{GetDispatchInfo, PostDispatchInfo}; +use frame_support::traits::ConstU32; +use frame_system::RawOrigin; +use pallet_evm::{AddressMapping, PrecompileHandle}; +use precompile_utils::{EvmResult, prelude::BoundedString}; +use sp_core::H256; +use sp_runtime::{AccountId32, traits::Dispatchable}; + +use crate::{PrecompileExt, PrecompileHandleExt, parse_pubkey}; + +pub struct SubnetPrecompile(PhantomData); + +impl PrecompileExt for SubnetPrecompile +where + R: frame_system::Config + + pallet_evm::Config + + pallet_subtensor::Config + + pallet_admin_utils::Config, + R::AccountId: From<[u8; 32]>, + ::RuntimeCall: From> + + From> + + GetDispatchInfo + + Dispatchable, + ::AddressMapping: AddressMapping, + // ::Balance: From, + // <::Lookup as StaticLookup>::Source: From, +{ + const INDEX: u64 = 2051; + const ADDRESS_SS58: [u8; 32] = [ + 0x3a, 0x86, 0x18, 0xfb, 0xbb, 0x1b, 0xbc, 0x47, 0x86, 0x64, 0xff, 0x53, 0x46, 0x18, 0x0c, + 0x35, 0xd0, 0x9f, 0xac, 0x26, 0xf2, 0x02, 0x70, 0x85, 0xb3, 0x1c, 0x56, 0xc1, 0x06, 0x3c, + 0x1c, 0xd3, + ]; +} + +#[precompile_utils::precompile] +impl SubnetPrecompile +where + R: frame_system::Config + + pallet_evm::Config + + pallet_subtensor::Config + + pallet_admin_utils::Config, + R::AccountId: From<[u8; 32]>, + ::RuntimeCall: From> + + From> + + GetDispatchInfo + + Dispatchable, + ::AddressMapping: AddressMapping, + // ::Balance: From, + // <::Lookup as StaticLookup>::Source: From, +{ + #[precompile::public("registerNetwork(bytes32)")] + #[precompile::payable] + fn register_network(handle: &mut impl PrecompileHandle, hotkey: H256) -> EvmResult<()> { + let (hotkey, _) = parse_pubkey(hotkey.as_bytes())?; + let call = pallet_subtensor::Call::::register_network_with_identity { + hotkey, + identity: None, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public( + "registerNetwork(bytes32,string,string,string,string,string,string,string)" + )] + #[precompile::payable] + #[allow(clippy::too_many_arguments)] + fn register_network_with_identity( + handle: &mut impl PrecompileHandle, + hotkey: H256, + subnet_name: BoundedString>, + github_repo: BoundedString>, + subnet_contact: BoundedString>, + subnet_url: BoundedString>, + discord: BoundedString>, + description: BoundedString>, + additional: BoundedString>, + ) -> EvmResult<()> { + let (hotkey, _) = parse_pubkey(hotkey.as_bytes())?; + let identity = pallet_subtensor::SubnetIdentityOfV2 { + subnet_name: subnet_name.into(), + github_repo: github_repo.into(), + subnet_contact: subnet_contact.into(), + subnet_url: subnet_url.into(), + discord: discord.into(), + description: description.into(), + additional: additional.into(), + }; + + let call = pallet_subtensor::Call::::register_network_with_identity { + hotkey, + identity: Some(identity), + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getServingRateLimit(uint16)")] + #[precompile::view] + fn get_serving_rate_limit(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::ServingRateLimit::::get(netuid)) + } + + #[precompile::public("setServingRateLimit(uint16,uint64)")] + #[precompile::payable] + fn set_serving_rate_limit( + handle: &mut impl PrecompileHandle, + netuid: u16, + serving_rate_limit: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_serving_rate_limit { + netuid, + serving_rate_limit, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getMinDifficulty(uint16)")] + #[precompile::view] + fn get_min_difficulty(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::MinDifficulty::::get(netuid)) + } + + #[precompile::public("setMinDifficulty(uint16,uint64)")] + #[precompile::payable] + fn set_min_difficulty( + handle: &mut impl PrecompileHandle, + netuid: u16, + min_difficulty: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_min_difficulty { + netuid, + min_difficulty, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getMaxDifficulty(uint16)")] + #[precompile::view] + fn get_max_difficulty(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::MaxDifficulty::::get(netuid)) + } + + #[precompile::public("setMaxDifficulty(uint16,uint64)")] + #[precompile::payable] + fn set_max_difficulty( + handle: &mut impl PrecompileHandle, + netuid: u16, + max_difficulty: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_max_difficulty { + netuid, + max_difficulty, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getWeightsVersionKey(uint16)")] + #[precompile::view] + fn get_weights_version_key(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::WeightsVersionKey::::get(netuid)) + } + + #[precompile::public("setWeightsVersionKey(uint16,uint64)")] + #[precompile::payable] + fn set_weights_version_key( + handle: &mut impl PrecompileHandle, + netuid: u16, + weights_version_key: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_weights_version_key { + netuid, + weights_version_key, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getWeightsSetRateLimit(uint16)")] + #[precompile::view] + fn get_weights_set_rate_limit(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::WeightsSetRateLimit::::get(netuid)) + } + + #[precompile::public("setWeightsSetRateLimit(uint16,uint64)")] + #[precompile::payable] + fn set_weights_set_rate_limit( + handle: &mut impl PrecompileHandle, + netuid: u16, + weights_set_rate_limit: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_weights_set_rate_limit { + netuid, + weights_set_rate_limit, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getAdjustmentAlpha(uint16)")] + #[precompile::view] + fn get_adjustment_alpha(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::AdjustmentAlpha::::get(netuid)) + } + + #[precompile::public("setAdjustmentAlpha(uint16,uint64)")] + #[precompile::payable] + fn set_adjustment_alpha( + handle: &mut impl PrecompileHandle, + netuid: u16, + adjustment_alpha: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_adjustment_alpha { + netuid, + adjustment_alpha, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getMaxWeightLimit(uint16)")] + #[precompile::view] + fn get_max_weight_limit(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::MaxWeightsLimit::::get(netuid)) + } + + #[precompile::public("setMaxWeightLimit(uint16,uint16)")] + #[precompile::payable] + fn set_max_weight_limit( + handle: &mut impl PrecompileHandle, + netuid: u16, + max_weight_limit: u16, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_max_weight_limit { + netuid, + max_weight_limit, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getImmunityPeriod(uint16)")] + #[precompile::view] + fn get_immunity_period(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::ImmunityPeriod::::get(netuid)) + } + + #[precompile::public("setImmunityPeriod(uint16,uint16)")] + #[precompile::payable] + fn set_immunity_period( + handle: &mut impl PrecompileHandle, + netuid: u16, + immunity_period: u16, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_immunity_period { + netuid, + immunity_period, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getMinAllowedWeights(uint16)")] + #[precompile::view] + fn get_min_allowed_weights(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::MinAllowedWeights::::get(netuid)) + } + + #[precompile::public("setMinAllowedWeights(uint16,uint16)")] + #[precompile::payable] + fn set_min_allowed_weights( + handle: &mut impl PrecompileHandle, + netuid: u16, + min_allowed_weights: u16, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_min_allowed_weights { + netuid, + min_allowed_weights, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getKappa(uint16)")] + #[precompile::view] + fn get_kappa(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::Kappa::::get(netuid)) + } + + #[precompile::public("setKappa(uint16,uint16)")] + #[precompile::payable] + fn set_kappa(handle: &mut impl PrecompileHandle, netuid: u16, kappa: u16) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_kappa { netuid, kappa }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getRho(uint16)")] + #[precompile::view] + fn get_rho(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::Rho::::get(netuid)) + } + + #[precompile::public("setRho(uint16,uint16)")] + #[precompile::payable] + fn set_rho(handle: &mut impl PrecompileHandle, netuid: u16, rho: u16) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_rho { netuid, rho }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getActivityCutoff(uint16)")] + #[precompile::view] + fn get_activity_cutoff(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::ActivityCutoff::::get(netuid)) + } + + #[precompile::public("setActivityCutoff(uint16,uint16)")] + #[precompile::payable] + fn set_activity_cutoff( + handle: &mut impl PrecompileHandle, + netuid: u16, + activity_cutoff: u16, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_activity_cutoff { + netuid, + activity_cutoff, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getNetworkRegistrationAllowed(uint16)")] + #[precompile::view] + fn get_network_registration_allowed( + _: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult { + Ok(pallet_subtensor::NetworkRegistrationAllowed::::get( + netuid, + )) + } + + #[precompile::public("setNetworkRegistrationAllowed(uint16,bool)")] + #[precompile::payable] + fn set_network_registration_allowed( + handle: &mut impl PrecompileHandle, + netuid: u16, + registration_allowed: bool, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_network_registration_allowed { + netuid, + registration_allowed, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getNetworkPowRegistrationAllowed(uint16)")] + #[precompile::view] + fn get_network_pow_registration_allowed( + _: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult { + Ok(pallet_subtensor::NetworkPowRegistrationAllowed::::get( + netuid, + )) + } + + #[precompile::public("setNetworkPowRegistrationAllowed(uint16,bool)")] + #[precompile::payable] + fn set_network_pow_registration_allowed( + handle: &mut impl PrecompileHandle, + netuid: u16, + registration_allowed: bool, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_network_pow_registration_allowed { + netuid, + registration_allowed, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getMinBurn(uint16)")] + #[precompile::view] + fn get_min_burn(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::MinBurn::::get(netuid)) + } + + #[precompile::public("setMinBurn(uint16,uint64)")] + #[precompile::payable] + fn set_min_burn( + handle: &mut impl PrecompileHandle, + netuid: u16, + min_burn: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_min_burn { netuid, min_burn }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getMaxBurn(uint16)")] + #[precompile::view] + fn get_max_burn(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::MaxBurn::::get(netuid)) + } + + #[precompile::public("setMaxBurn(uint16,uint64)")] + #[precompile::payable] + fn set_max_burn( + handle: &mut impl PrecompileHandle, + netuid: u16, + max_burn: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_max_burn { netuid, max_burn }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getDifficulty(uint16)")] + #[precompile::view] + fn get_difficulty(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::Difficulty::::get(netuid)) + } + + #[precompile::public("setDifficulty(uint16,uint64)")] + #[precompile::payable] + fn set_difficulty( + handle: &mut impl PrecompileHandle, + netuid: u16, + difficulty: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_difficulty { netuid, difficulty }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getBondsMovingAverage(uint16)")] + #[precompile::view] + fn get_bonds_moving_average(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::BondsMovingAverage::::get(netuid)) + } + + #[precompile::public("setBondsMovingAverage(uint16,uint64)")] + #[precompile::payable] + fn set_bonds_moving_average( + handle: &mut impl PrecompileHandle, + netuid: u16, + bonds_moving_average: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_bonds_moving_average { + netuid, + bonds_moving_average, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getCommitRevealWeightsEnabled(uint16)")] + #[precompile::view] + fn get_commit_reveal_weights_enabled( + _: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult { + Ok(pallet_subtensor::CommitRevealWeightsEnabled::::get( + netuid, + )) + } + + #[precompile::public("setCommitRevealWeightsEnabled(uint16,bool)")] + #[precompile::payable] + fn set_commit_reveal_weights_enabled( + handle: &mut impl PrecompileHandle, + netuid: u16, + enabled: bool, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_commit_reveal_weights_enabled { + netuid, + enabled, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getLiquidAlphaEnabled(uint16)")] + #[precompile::view] + fn get_liquid_alpha_enabled(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::LiquidAlphaOn::::get(netuid)) + } + + #[precompile::public("setLiquidAlphaEnabled(uint16,bool)")] + #[precompile::payable] + fn set_liquid_alpha_enabled( + handle: &mut impl PrecompileHandle, + netuid: u16, + enabled: bool, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_liquid_alpha_enabled { netuid, enabled }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getAlphaValues(uint16)")] + #[precompile::view] + fn get_alpha_values(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult<(u16, u16)> { + Ok(pallet_subtensor::AlphaValues::::get(netuid)) + } + + #[precompile::public("setAlphaValues(uint16,uint16,uint16)")] + #[precompile::payable] + fn set_alpha_values( + handle: &mut impl PrecompileHandle, + netuid: u16, + alpha_low: u16, + alpha_high: u16, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_alpha_values { + netuid, + alpha_low, + alpha_high, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("getCommitRevealWeightsInterval(uint16)")] + #[precompile::view] + fn get_commit_reveal_weights_interval( + _: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult { + Ok(pallet_subtensor::RevealPeriodEpochs::::get(netuid)) + } + + #[precompile::public("setCommitRevealWeightsInterval(uint16,uint64)")] + #[precompile::payable] + fn set_commit_reveal_weights_interval( + handle: &mut impl PrecompileHandle, + netuid: u16, + interval: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_commit_reveal_weights_interval { + netuid, + interval, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } +} diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index e28b7ba1b2..a90daa47a7 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -20,11 +20,8 @@ name = "spec_version" path = "src/spec_version.rs" [dependencies] -ed25519-dalek = { workspace = true, default-features = false, features = [ - "alloc", -] } subtensor-macros.workspace = true -subtensor-custom-rpc-runtime-api = { path = "../pallets/subtensor/runtime-api", default-features = false } +subtensor-custom-rpc-runtime-api = { workspace = true } smallvec = { workspace = true } log = { workspace = true } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ @@ -34,7 +31,7 @@ scale-info = { workspace = true, features = ["derive"] } serde_json = { workspace = true, features = ["alloc"] } pallet-aura = { workspace = true } pallet-balances = { workspace = true } -pallet-subtensor = { default-features = false, path = "../pallets/subtensor" } +pallet-subtensor = { workspace = true } frame-support = { workspace = true } pallet-grandpa = { workspace = true } pallet-insecure-randomness-collective-flip = { workspace = true } @@ -58,14 +55,15 @@ sp-session = { workspace = true } sp-std = { workspace = true } sp-transaction-pool = { workspace = true } sp-version = { workspace = true } +subtensor-runtime-common = { workspace = true } # Temporary sudo pallet-sudo = { workspace = true } -pallet-admin-utils = { default-features = false, path = "../pallets/admin-utils" } +pallet-admin-utils = { workspace = true } # Used for sudo decentralization -pallet-collective = { default-features = false, path = "../pallets/collective" } +pallet-collective = { workspace = true } pallet-membership = { workspace = true } # Multisig @@ -91,10 +89,10 @@ frame-benchmarking = { workspace = true, optional = true } frame-system-benchmarking = { workspace = true, optional = true } # Identity registry pallet for registering project info -pallet-registry = { default-features = false, path = "../pallets/registry" } +pallet-registry = { workspace = true } # Metadata commitment pallet -pallet-commitments = { default-features = false, path = "../pallets/commitments" } +pallet-commitments = { workspace = true } # Frontier fp-evm = { workspace = true } @@ -134,13 +132,15 @@ substrate-wasm-builder = { workspace = true, optional = true } [features] default = ["std"] pow-faucet = ["pallet-subtensor/pow-faucet"] -fast-blocks = ["pallet-subtensor/fast-blocks"] +fast-blocks = [ + "pallet-subtensor/fast-blocks", + "subtensor-runtime-common/fast-blocks", +] std = [ "frame-try-runtime?/std", "frame-system-benchmarking?/std", "frame-benchmarking/std", "codec/std", - "ed25519-dalek/std", "scale-info/std", "frame-executive/std", "frame-metadata-hash-extension/std", @@ -188,6 +188,7 @@ std = [ "log/std", "sp-storage/std", "sp-genesis-builder/std", + "subtensor-runtime-common/std", # Frontier "fp-evm/std", "fp-rpc/std", diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 614103afbf..f9d1448db7 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -62,6 +62,7 @@ use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; +use subtensor_runtime_common::{*, time::*}; // A few exports that help ease life for downstream crates. pub use frame_support::{ @@ -159,30 +160,9 @@ impl frame_system::offchain::CreateSignedTransaction pub use pallet_scheduler; pub use pallet_subtensor; -// An index to a block. -pub type BlockNumber = u32; - -// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = MultiSignature; - -// Some way of identifying an account on the chain. We intentionally make it equivalent -// to the public key of our transaction signing scheme. -pub type AccountId = <::Signer as IdentifyAccount>::AccountId; - -// Balance of an account. -pub type Balance = u64; - -// Index of a transaction in the chain. -pub type Index = u32; - -// A hash of some data used by the chain. -pub type Hash = sp_core::H256; - // Member type for membership type MemberCount = u32; -pub type Nonce = u32; - // Method used to calculate the fee of an extrinsic pub const fn deposit(items: u32, bytes: u32) -> Balance { pub const ITEMS_FEE: Balance = 2_000 * 10_000; @@ -235,28 +215,6 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { state_version: 1, }; -/// This determines the average expected block time that we are targeting. -/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`. -/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked -/// up by `pallet_aura` to implement `fn slot_duration()`. -/// -/// Change this to adjust the block time. -#[cfg(not(feature = "fast-blocks"))] -pub const MILLISECS_PER_BLOCK: u64 = 12000; - -/// Fast blocks for development -#[cfg(feature = "fast-blocks")] -pub const MILLISECS_PER_BLOCK: u64 = 250; - -// NOTE: Currently it is not possible to change the slot duration after the chain has started. -// Attempting to do so will brick block production. -pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; - -// Time is measured by number of blocks. -pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); -pub const HOURS: BlockNumber = MINUTES * 60; -pub const DAYS: BlockNumber = HOURS * 24; - pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(4u64 * WEIGHT_REF_TIME_PER_SECOND, u64::MAX); @@ -694,33 +652,6 @@ parameter_types! { pub const AnnouncementDepositFactor: Balance = deposit(0, 68); } -#[derive( - Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, MaxEncodedLen, TypeInfo, -)] -pub enum ProxyType { - Any, - Owner, // Subnet owner Calls - NonCritical, - NonTransfer, - Senate, - NonFungibile, // Nothing involving moving TAO - Triumvirate, - Governance, // Both above governance - Staking, - Registration, - Transfer, - SmallTransfer, - RootWeights, - ChildKeys, - SudoUncheckedSetCode, -} -// Transfers below SMALL_TRANSFER_LIMIT are considered small transfers -pub const SMALL_TRANSFER_LIMIT: Balance = 500_000_000; // 0.5 TAO -impl Default for ProxyType { - fn default() -> Self { - Self::Any - } -} // allow all Calls; required to be most permissive impl InstanceFilter for ProxyType { fn filter(&self, c: &RuntimeCall) -> bool { match self { From c5c11603ce2591823579dbca5cf015ee8b9143c0 Mon Sep 17 00:00:00 2001 From: Aliaksandr Tsurko Date: Mon, 3 Mar 2025 17:01:07 +0100 Subject: [PATCH 2/7] Reformat --- common/src/lib.rs | 12 ++++++------ precompiles/src/lib.rs | 9 ++++----- precompiles/src/staking.rs | 4 +++- precompiles/src/subnet.rs | 2 +- runtime/src/lib.rs | 2 +- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/common/src/lib.rs b/common/src/lib.rs index ad038cfb00..75b18e3b14 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -60,14 +60,14 @@ impl Default for ProxyType { } pub mod time { - use super::*; + use super::*; - /// This determines the average expected block time that we are targeting. Blocks will be - /// produced at a minimum duration defined by `SLOT_DURATION`. `SLOT_DURATION` is picked up by - /// `pallet_timestamp` which is in turn picked up by `pallet_aura` to implement `fn - /// slot_duration()`. + /// This determines the average expected block time that we are targeting. Blocks will be + /// produced at a minimum duration defined by `SLOT_DURATION`. `SLOT_DURATION` is picked up by + /// `pallet_timestamp` which is in turn picked up by `pallet_aura` to implement `fn + /// slot_duration()`. /// - /// Change this to adjust the block time. + /// Change this to adjust the block time. #[cfg(not(feature = "fast-blocks"))] pub const MILLISECS_PER_BLOCK: u64 = 12000; diff --git a/precompiles/src/lib.rs b/precompiles/src/lib.rs index b69a2ec6b8..f85deaee07 100644 --- a/precompiles/src/lib.rs +++ b/precompiles/src/lib.rs @@ -8,17 +8,16 @@ use core::marker::PhantomData; use frame_support::dispatch::{GetDispatchInfo, Pays, PostDispatchInfo}; use frame_system::RawOrigin; use pallet_evm::{ - AddressMapping, BalanceConverter, ExitError, GasWeightMapping, HashedAddressMapping, - IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, - PrecompileSet, + AddressMapping, BalanceConverter, ExitError, GasWeightMapping, IsPrecompileResult, Precompile, + PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, }; use pallet_evm_precompile_modexp::Modexp; use pallet_evm_precompile_sha3fips::Sha3FIPS256; use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256}; use precompile_utils::EvmResult; use sp_core::{H160, U256, crypto::ByteArray}; -use sp_runtime::traits::{BlakeTwo256, StaticLookup}; -use sp_runtime::{AccountId32, traits::Dispatchable}; +use sp_runtime::traits::Dispatchable; +use sp_runtime::traits::StaticLookup; use subtensor_runtime_common::ProxyType; use pallet_admin_utils::{PrecompileEnable, PrecompileEnum}; diff --git a/precompiles/src/staking.rs b/precompiles/src/staking.rs index 9df3cc74e7..fceaab2651 100644 --- a/precompiles/src/staking.rs +++ b/precompiles/src/staking.rs @@ -29,7 +29,9 @@ use core::marker::PhantomData; use frame_support::dispatch::{GetDispatchInfo, PostDispatchInfo}; use frame_system::RawOrigin; -use pallet_evm::{BalanceConverter, AddressMapping, ExitError, PrecompileFailure, PrecompileHandle}; +use pallet_evm::{ + AddressMapping, BalanceConverter, ExitError, PrecompileFailure, PrecompileHandle, +}; use precompile_utils::EvmResult; use sp_core::{H256, U256}; use sp_runtime::traits::{Dispatchable, StaticLookup, UniqueSaturatedInto}; diff --git a/precompiles/src/subnet.rs b/precompiles/src/subnet.rs index bcf5d2df00..82cec11626 100644 --- a/precompiles/src/subnet.rs +++ b/precompiles/src/subnet.rs @@ -6,7 +6,7 @@ use frame_system::RawOrigin; use pallet_evm::{AddressMapping, PrecompileHandle}; use precompile_utils::{EvmResult, prelude::BoundedString}; use sp_core::H256; -use sp_runtime::{AccountId32, traits::Dispatchable}; +use sp_runtime::traits::Dispatchable; use crate::{PrecompileExt, PrecompileHandleExt, parse_pubkey}; diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index f9d1448db7..fb04ede735 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -62,7 +62,7 @@ use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; -use subtensor_runtime_common::{*, time::*}; +use subtensor_runtime_common::{time::*, *}; // A few exports that help ease life for downstream crates. pub use frame_support::{ From d7cc03f3b1b501837cd01fdb40eeb68b1ac79c5e Mon Sep 17 00:00:00 2001 From: Aliaksandr Tsurko Date: Mon, 3 Mar 2025 18:05:18 +0100 Subject: [PATCH 3/7] Adapt node and runtime to changes --- Cargo.lock | 2 + Cargo.toml | 3 +- node/Cargo.toml | 13 +- node/src/benchmarking.rs | 5 +- node/src/chain_spec/mod.rs | 3 +- node/src/rpc.rs | 2 +- node/src/service.rs | 2 +- precompiles/src/balance_transfer.rs | 4 +- precompiles/src/lib.rs | 6 +- precompiles/src/staking.rs | 4 +- runtime/Cargo.toml | 1 + runtime/src/lib.rs | 14 +- runtime/src/precompiles/balance_transfer.rs | 40 - runtime/src/precompiles/ed25519.rs | 48 - runtime/src/precompiles/metagraph.rs | 171 ---- runtime/src/precompiles/mod.rs | 292 ------ runtime/src/precompiles/neuron.rs | 173 ---- .../precompiles/solidity/balanceTransfer.abi | 15 - .../precompiles/solidity/balanceTransfer.sol | 7 - .../precompiles/solidity/ed25519Verify.abi | 14 - .../precompiles/solidity/ed25519Verify.sol | 17 - .../src/precompiles/solidity/metagraph.abi | 389 -------- .../src/precompiles/solidity/metagraph.sol | 134 --- runtime/src/precompiles/solidity/neuron.abi | 233 ----- runtime/src/precompiles/solidity/neuron.sol | 122 --- runtime/src/precompiles/solidity/staking.abi | 98 -- runtime/src/precompiles/solidity/staking.sol | 79 -- runtime/src/precompiles/solidity/subnet.abi | 887 ------------------ runtime/src/precompiles/solidity/subnet.sol | 173 ---- runtime/src/precompiles/staking.rs | 171 ---- runtime/src/precompiles/subnet.rs | 522 ----------- runtime/tests/pallet_proxy.rs | 5 +- 32 files changed, 34 insertions(+), 3615 deletions(-) delete mode 100644 runtime/src/precompiles/balance_transfer.rs delete mode 100644 runtime/src/precompiles/ed25519.rs delete mode 100644 runtime/src/precompiles/metagraph.rs delete mode 100644 runtime/src/precompiles/mod.rs delete mode 100644 runtime/src/precompiles/neuron.rs delete mode 100644 runtime/src/precompiles/solidity/balanceTransfer.abi delete mode 100644 runtime/src/precompiles/solidity/balanceTransfer.sol delete mode 100644 runtime/src/precompiles/solidity/ed25519Verify.abi delete mode 100644 runtime/src/precompiles/solidity/ed25519Verify.sol delete mode 100644 runtime/src/precompiles/solidity/metagraph.abi delete mode 100644 runtime/src/precompiles/solidity/metagraph.sol delete mode 100644 runtime/src/precompiles/solidity/neuron.abi delete mode 100644 runtime/src/precompiles/solidity/neuron.sol delete mode 100644 runtime/src/precompiles/solidity/staking.abi delete mode 100644 runtime/src/precompiles/solidity/staking.sol delete mode 100644 runtime/src/precompiles/solidity/subnet.abi delete mode 100644 runtime/src/precompiles/solidity/subnet.sol delete mode 100644 runtime/src/precompiles/staking.rs delete mode 100644 runtime/src/precompiles/subnet.rs diff --git a/Cargo.lock b/Cargo.lock index 8efcdc5ac0..e6bbe9432c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5805,6 +5805,7 @@ dependencies = [ "substrate-prometheus-endpoint", "subtensor-custom-rpc", "subtensor-custom-rpc-runtime-api", + "subtensor-runtime-common", "thiserror 1.0.69", ] @@ -5883,6 +5884,7 @@ dependencies = [ "substrate-wasm-builder", "subtensor-custom-rpc-runtime-api", "subtensor-macros", + "subtensor-precompiles", "subtensor-runtime-common", "tle", "w3f-bls", diff --git a/Cargo.toml b/Cargo.toml index b00c098913..781fe6dfe9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,6 @@ members = [ "precompiles", "primitives/*", "runtime", - "common", "support/*", ] resolver = "2" @@ -48,9 +47,11 @@ pallet-collective = { default-features = false, path = "pallets/collective" } pallet-commitments = { default-features = false, path = "pallets/commitments" } pallet-registry = { default-features = false, path = "pallets/registry" } pallet-subtensor = { default-features = false, path = "pallets/subtensor" } +subtensor-custom-rpc = { default-features = false, path = "pallets/subtensor/rpc" } subtensor-custom-rpc-runtime-api = { default-features = false, path = "pallets/subtensor/runtime-api" } subtensor-precompiles = { default-features = false, path = "precompiles" } subtensor-runtime-common = { default-features = false, path = "common" } +node-subtensor-runtime = { default-features = false, path = "runtime" } async-trait = "0.1" cargo-husky = { version = "1", default-features = false } diff --git a/node/Cargo.toml b/node/Cargo.toml index f97425ba9a..44a7bd0cc7 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -66,7 +66,7 @@ pallet-transaction-payment = { workspace = true } pallet-commitments = { path = "../pallets/commitments" } pallet-drand = { workspace = true } sp-crypto-ec-utils = { workspace = true } -sp-keystore = { workspace = true, default-features = false } +sp-keystore = { workspace = true, default-features = false } # These dependencies are used for the subtensor's RPCs @@ -105,9 +105,10 @@ thiserror = { workspace = true } num-traits = { version = "0.2", features = ["std"] } # Local Dependencies -node-subtensor-runtime = { path = "../runtime" } -subtensor-custom-rpc = { path = "../pallets/subtensor/rpc" } -subtensor-custom-rpc-runtime-api = { path = "../pallets/subtensor/runtime-api" } +node-subtensor-runtime = { workspace = true } +subtensor-runtime-common = { workspace = true } +subtensor-custom-rpc = { workspace = true } +subtensor-custom-rpc-runtime-api = { workspace = true } [build-dependencies] substrate-build-script-utils = { workspace = true } @@ -133,7 +134,7 @@ runtime-benchmarks = [ "sc-service/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "pallet-commitments/runtime-benchmarks", - "pallet-drand/runtime-benchmarks" + "pallet-drand/runtime-benchmarks", ] pow-faucet = [] @@ -145,7 +146,7 @@ try-runtime = [ "pallet-transaction-payment/try-runtime", "sp-runtime/try-runtime", "pallet-commitments/try-runtime", - "pallet-drand/try-runtime" + "pallet-drand/try-runtime", ] metadata-hash = ["node-subtensor-runtime/metadata-hash"] diff --git a/node/src/benchmarking.rs b/node/src/benchmarking.rs index cee1cb4ac8..40031ac1aa 100644 --- a/node/src/benchmarking.rs +++ b/node/src/benchmarking.rs @@ -7,13 +7,14 @@ use crate::client::FullClient; use node_subtensor_runtime as runtime; use node_subtensor_runtime::check_nonce; use node_subtensor_runtime::pallet_subtensor; -use runtime::{AccountId, Balance, BalancesCall, SystemCall}; +use runtime::{BalancesCall, SystemCall}; use sc_cli::Result; use sc_client_api::BlockBackend; use sp_core::{Encode, Pair}; use sp_inherents::{InherentData, InherentDataProvider}; use sp_keyring::Sr25519Keyring; use sp_runtime::{OpaqueExtrinsic, SaturatedConversion}; +use subtensor_runtime_common::{AccountId, Balance, Signature}; use std::{sync::Arc, time::Duration}; @@ -161,7 +162,7 @@ pub fn create_benchmark_extrinsic( runtime::UncheckedExtrinsic::new_signed( call.clone(), sp_runtime::AccountId32::from(sender.public()).into(), - runtime::Signature::Sr25519(signature), + Signature::Sr25519(signature), extra.clone(), ) } diff --git a/node/src/chain_spec/mod.rs b/node/src/chain_spec/mod.rs index 25942658d5..e8efbb1647 100644 --- a/node/src/chain_spec/mod.rs +++ b/node/src/chain_spec/mod.rs @@ -6,7 +6,7 @@ pub mod finney; pub mod localnet; pub mod testnet; -use node_subtensor_runtime::{AccountId, Block, Signature, WASM_BINARY}; +use node_subtensor_runtime::{Block, WASM_BINARY}; use sc_chain_spec_derive::ChainSpecExtension; use sc_service::ChainType; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -18,6 +18,7 @@ use sp_runtime::traits::{IdentifyAccount, Verify}; use std::collections::HashSet; use std::env; use std::str::FromStr; +use subtensor_runtime_common::{AccountId, Signature}; // The URL for the telemetry server. // const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; diff --git a/node/src/rpc.rs b/node/src/rpc.rs index 39a63c602e..0d4cd355de 100644 --- a/node/src/rpc.rs +++ b/node/src/rpc.rs @@ -13,7 +13,6 @@ pub use fc_rpc::EthBlockDataCacheTask; pub use fc_rpc_core::types::{FeeHistoryCache, FeeHistoryCacheLimit, FilterPool}; use fc_storage::StorageOverride; use jsonrpsee::RpcModule; -use node_subtensor_runtime::Hash; use node_subtensor_runtime::opaque::Block; use sc_consensus_manual_seal::EngineCommand; use sc_network::service::traits::NetworkService; @@ -24,6 +23,7 @@ use sc_transaction_pool_api::TransactionPool; use sp_core::H256; use sp_inherents::CreateInherentDataProviders; use sp_runtime::traits::Block as BlockT; +use subtensor_runtime_common::Hash; use crate::{ client::{FullBackend, FullClient}, diff --git a/node/src/service.rs b/node/src/service.rs index a0b7cb1c6a..4ce041b0a4 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -796,7 +796,7 @@ fn run_manual_seal_authorship( ) -> Result<(), sp_inherents::Error> { TIMESTAMP.with(|x| { let mut x_ref = x.borrow_mut(); - *x_ref = x_ref.saturating_add(node_subtensor_runtime::SLOT_DURATION); + *x_ref = x_ref.saturating_add(subtensor_runtime_common::time::SLOT_DURATION); inherent_data.put_data(sp_timestamp::INHERENT_IDENTIFIER, &*x.borrow()) }) } diff --git a/precompiles/src/balance_transfer.rs b/precompiles/src/balance_transfer.rs index 83897bdfeb..2f2103e9d0 100644 --- a/precompiles/src/balance_transfer.rs +++ b/precompiles/src/balance_transfer.rs @@ -20,7 +20,7 @@ where + GetDispatchInfo + Dispatchable, <::Lookup as StaticLookup>::Source: From, - ::Balance: From, + ::Balance: TryFrom, { const INDEX: u64 = 2048; const ADDRESS_SS58: [u8; 32] = [ @@ -41,7 +41,7 @@ where + GetDispatchInfo + Dispatchable, <::Lookup as StaticLookup>::Source: From, - ::Balance: From, + ::Balance: TryFrom, { #[precompile::public("transfer(bytes32)")] #[precompile::payable] diff --git a/precompiles/src/lib.rs b/precompiles/src/lib.rs index f85deaee07..51963ca099 100644 --- a/precompiles/src/lib.rs +++ b/precompiles/src/lib.rs @@ -55,7 +55,7 @@ where + GetDispatchInfo + Dispatchable, ::AddressMapping: AddressMapping, - ::Balance: From, + ::Balance: TryFrom, <::Lookup as StaticLookup>::Source: From, { fn default() -> Self { @@ -79,7 +79,7 @@ where + GetDispatchInfo + Dispatchable, ::AddressMapping: AddressMapping, - ::Balance: From, + ::Balance: TryFrom, <::Lookup as StaticLookup>::Source: From, { pub fn new() -> Self { @@ -120,7 +120,7 @@ where + GetDispatchInfo + Dispatchable, ::AddressMapping: AddressMapping, - ::Balance: From, + ::Balance: TryFrom, <::Lookup as StaticLookup>::Source: From, { fn execute(&self, handle: &mut impl PrecompileHandle) -> Option { diff --git a/precompiles/src/staking.rs b/precompiles/src/staking.rs index fceaab2651..6e7a1100bc 100644 --- a/precompiles/src/staking.rs +++ b/precompiles/src/staking.rs @@ -55,7 +55,7 @@ where + GetDispatchInfo + Dispatchable, ::AddressMapping: AddressMapping, - ::Balance: From, + ::Balance: TryFrom, <::Lookup as StaticLookup>::Source: From, { const INDEX: u64 = 2049; @@ -81,7 +81,7 @@ where + GetDispatchInfo + Dispatchable, ::AddressMapping: AddressMapping, - ::Balance: From, + ::Balance: TryFrom, <::Lookup as StaticLookup>::Source: From, { #[precompile::public("addStake(bytes32,uint256)")] diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index a90daa47a7..0ce6848406 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -56,6 +56,7 @@ sp-std = { workspace = true } sp-transaction-pool = { workspace = true } sp-version = { workspace = true } subtensor-runtime-common = { workspace = true } +subtensor-precompiles = { workspace = true } # Temporary sudo pallet-sudo = { workspace = true } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index fb04ede735..3b22442d96 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -39,7 +39,6 @@ use pallet_subtensor::rpc_info::{ stake_info::StakeInfo, subnet_info::{SubnetHyperparams, SubnetInfo, SubnetInfov2}, }; -use scale_info::TypeInfo; use smallvec::smallvec; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -49,11 +48,10 @@ use sp_core::{ }; use sp_runtime::generic::Era; use sp_runtime::{ - AccountId32, ApplyExtrinsicResult, ConsensusEngineId, MultiSignature, create_runtime_str, + AccountId32, ApplyExtrinsicResult, ConsensusEngineId, create_runtime_str, generic, impl_opaque_keys, traits::{ - AccountIdLookup, BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, - IdentifyAccount, NumberFor, One, PostDispatchInfoOf, UniqueSaturatedInto, Verify, + AccountIdLookup, BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, NumberFor, One, PostDispatchInfoOf, UniqueSaturatedInto, Verify, }, transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError}, }; @@ -62,6 +60,7 @@ use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; +use subtensor_precompiles::Precompiles; use subtensor_runtime_common::{time::*, *}; // A few exports that help ease life for downstream crates. @@ -89,9 +88,6 @@ pub use sp_runtime::{Perbill, Permill}; use core::marker::PhantomData; -mod precompiles; -use precompiles::FrontierPrecompiles; - // Frontier use fp_rpc::TransactionStatus; use pallet_ethereum::{Call::transact, PostLogContent, Transaction as EthereumTransaction}; @@ -1163,7 +1159,7 @@ fn weight_per_gas() -> Weight { parameter_types! { pub BlockGasLimit: U256 = U256::from(BLOCK_GAS_LIMIT); pub const GasLimitPovSizeRatio: u64 = 0; - pub PrecompilesValue: FrontierPrecompiles = FrontierPrecompiles::<_>::new(); + pub PrecompilesValue: Precompiles = Precompiles::<_>::new(); pub WeightPerGas: Weight = weight_per_gas(); pub SuicideQuickClearLimit: u32 = 0; } @@ -1235,7 +1231,7 @@ impl pallet_evm::Config for Runtime { type AddressMapping = pallet_evm::HashedAddressMapping; type Currency = Balances; type RuntimeEvent = RuntimeEvent; - type PrecompilesType = FrontierPrecompiles; + type PrecompilesType = Precompiles; type PrecompilesValue = PrecompilesValue; type ChainId = ConfigurableChainId; type BlockGasLimit = BlockGasLimit; diff --git a/runtime/src/precompiles/balance_transfer.rs b/runtime/src/precompiles/balance_transfer.rs deleted file mode 100644 index c1b68d4f74..0000000000 --- a/runtime/src/precompiles/balance_transfer.rs +++ /dev/null @@ -1,40 +0,0 @@ -use pallet_evm::PrecompileHandle; -use precompile_utils::EvmResult; -use sp_core::H256; -use sp_runtime::traits::UniqueSaturatedInto; - -use crate::Runtime; -use crate::precompiles::{PrecompileExt, PrecompileHandleExt, contract_to_origin, parse_pubkey}; - -pub struct BalanceTransferPrecompile; - -impl PrecompileExt for BalanceTransferPrecompile { - const INDEX: u64 = 2048; - const ADDRESS_SS58: [u8; 32] = [ - 0x07, 0xec, 0x71, 0x2a, 0x5d, 0x38, 0x43, 0x4d, 0xdd, 0x03, 0x3f, 0x8f, 0x02, 0x4e, 0xcd, - 0xfc, 0x4b, 0xb5, 0x95, 0x1c, 0x13, 0xc3, 0x08, 0x5c, 0x39, 0x9c, 0x8a, 0x5f, 0x62, 0x93, - 0x70, 0x5d, - ]; -} - -#[precompile_utils::precompile] -impl BalanceTransferPrecompile { - #[precompile::public("transfer(bytes32)")] - #[precompile::payable] - fn transfer(handle: &mut impl PrecompileHandle, address: H256) -> EvmResult<()> { - let amount_sub = handle.try_convert_apparent_value()?; - - if amount_sub.is_zero() { - return Ok(()); - } - - let dest = parse_pubkey(address.as_bytes())?.0.into(); - - let call = pallet_balances::Call::::transfer_allow_death { - dest, - value: amount_sub.unique_saturated_into(), - }; - - handle.try_dispatch_runtime_call(call, contract_to_origin(&Self::ADDRESS_SS58)?) - } -} diff --git a/runtime/src/precompiles/ed25519.rs b/runtime/src/precompiles/ed25519.rs deleted file mode 100644 index 601247f4e8..0000000000 --- a/runtime/src/precompiles/ed25519.rs +++ /dev/null @@ -1,48 +0,0 @@ -extern crate alloc; - -use alloc::vec::Vec; - -use ed25519_dalek::{Signature, Verifier, VerifyingKey}; -use fp_evm::{ExitError, ExitSucceed, LinearCostPrecompile, PrecompileFailure}; - -use crate::precompiles::{PrecompileExt, parse_slice}; - -pub struct Ed25519Verify; - -impl PrecompileExt for Ed25519Verify { - const INDEX: u64 = 1026; - const ADDRESS_SS58: [u8; 32] = [0; 32]; -} - -impl LinearCostPrecompile for Ed25519Verify { - const BASE: u64 = 15; - const WORD: u64 = 3; - - fn execute(input: &[u8], _: u64) -> Result<(ExitSucceed, Vec), PrecompileFailure> { - if input.len() < 132 { - return Err(PrecompileFailure::Error { - exit_status: ExitError::Other("input must contain 128 bytes".into()), - }); - }; - - let mut buf = [0u8; 32]; - - let msg = parse_slice(input, 4, 36)?; - let pk = VerifyingKey::try_from(parse_slice(input, 36, 68)?).map_err(|_| { - PrecompileFailure::Error { - exit_status: ExitError::Other("Public key recover failed".into()), - } - })?; - let sig = Signature::try_from(parse_slice(input, 68, 132)?).map_err(|_| { - PrecompileFailure::Error { - exit_status: ExitError::Other("Signature recover failed".into()), - } - })?; - - if pk.verify(msg, &sig).is_ok() { - buf[31] = 1u8; - }; - - Ok((ExitSucceed::Returned, buf.to_vec())) - } -} diff --git a/runtime/src/precompiles/metagraph.rs b/runtime/src/precompiles/metagraph.rs deleted file mode 100644 index e7a9243503..0000000000 --- a/runtime/src/precompiles/metagraph.rs +++ /dev/null @@ -1,171 +0,0 @@ -extern crate alloc; -use alloc::string::String; - -use fp_evm::{ExitError, PrecompileFailure, PrecompileHandle}; -use pallet_subtensor::AxonInfo as SubtensorModuleAxonInfo; -use precompile_utils::{EvmResult, solidity::Codec}; -use sp_core::{ByteArray, H256}; - -use crate::Runtime; -use crate::precompiles::PrecompileExt; - -pub struct MetagraphPrecompile; - -impl PrecompileExt for MetagraphPrecompile { - const INDEX: u64 = 2050; - const ADDRESS_SS58: [u8; 32] = [0; 32]; -} - -#[precompile_utils::precompile] -impl MetagraphPrecompile { - #[precompile::public("getUidCount(uint16)")] - #[precompile::view] - fn get_uid_count(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::SubnetworkN::::get(netuid)) - } - - #[precompile::public("getStake(uint16,uint16)")] - #[precompile::view] - fn get_stake(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) - .map_err(|_| PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - })?; - - Ok(pallet_subtensor::Pallet::::get_total_stake_for_hotkey(&hotkey)) - } - - #[precompile::public("getRank(uint16,uint16)")] - #[precompile::view] - fn get_rank(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - Ok(pallet_subtensor::Pallet::::get_rank_for_uid( - netuid, uid, - )) - } - - #[precompile::public("getTrust(uint16,uint16)")] - #[precompile::view] - fn get_trust(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - Ok(pallet_subtensor::Pallet::::get_trust_for_uid( - netuid, uid, - )) - } - - #[precompile::public("getConsensus(uint16,uint16)")] - #[precompile::view] - fn get_consensus(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - Ok(pallet_subtensor::Pallet::::get_consensus_for_uid( - netuid, uid, - )) - } - - #[precompile::public("getIncentive(uint16,uint16)")] - #[precompile::view] - fn get_incentive(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - Ok(pallet_subtensor::Pallet::::get_incentive_for_uid( - netuid, uid, - )) - } - - #[precompile::public("getDividends(uint16,uint16)")] - #[precompile::view] - fn get_dividends(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - Ok(pallet_subtensor::Pallet::::get_dividends_for_uid( - netuid, uid, - )) - } - - #[precompile::public("getEmission(uint16,uint16)")] - #[precompile::view] - fn get_emission(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - Ok(pallet_subtensor::Pallet::::get_emission_for_uid( - netuid, uid, - )) - } - - #[precompile::public("getVtrust(uint16,uint16)")] - #[precompile::view] - fn get_vtrust(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - Ok(pallet_subtensor::Pallet::::get_validator_trust_for_uid(netuid, uid)) - } - - #[precompile::public("getValidatorStatus(uint16,uint16)")] - #[precompile::view] - fn get_validator_status( - _: &mut impl PrecompileHandle, - netuid: u16, - uid: u16, - ) -> EvmResult { - Ok(pallet_subtensor::Pallet::::get_validator_permit_for_uid(netuid, uid)) - } - - #[precompile::public("getLastUpdate(uint16,uint16)")] - #[precompile::view] - fn get_last_update(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - Ok(pallet_subtensor::Pallet::::get_last_update_for_uid(netuid, uid)) - } - - #[precompile::public("getIsActive(uint16,uint16)")] - #[precompile::view] - fn get_is_active(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - Ok(pallet_subtensor::Pallet::::get_active_for_uid( - netuid, uid, - )) - } - - #[precompile::public("getAxon(uint16,uint16)")] - #[precompile::view] - fn get_axon(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) - .map_err(|_| PrecompileFailure::Error { - exit_status: ExitError::Other("hotkey not found".into()), - })?; - - Ok(pallet_subtensor::Pallet::::get_axon_info(netuid, &hotkey).into()) - } - - #[precompile::public("getHotkey(uint16,uint16)")] - #[precompile::view] - fn get_hotkey(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) - .map(|acc| H256::from_slice(acc.as_slice())) - .map_err(|_| PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }) - } - - #[precompile::public("getColdkey(uint16,uint16)")] - #[precompile::view] - fn get_coldkey(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) - .map_err(|_| PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - })?; - let coldkey = pallet_subtensor::Owner::::get(&hotkey); - - Ok(H256::from_slice(coldkey.as_slice())) - } -} - -#[derive(Codec)] -struct AxonInfo { - block: u64, - version: u32, - ip: u128, - port: u16, - ip_type: u8, - protocol: u8, -} - -impl From for AxonInfo { - fn from(value: SubtensorModuleAxonInfo) -> Self { - Self { - block: value.block, - version: value.version, - ip: value.ip, - port: value.port, - ip_type: value.ip_type, - protocol: value.protocol, - } - } -} diff --git a/runtime/src/precompiles/mod.rs b/runtime/src/precompiles/mod.rs deleted file mode 100644 index bba70eb027..0000000000 --- a/runtime/src/precompiles/mod.rs +++ /dev/null @@ -1,292 +0,0 @@ -extern crate alloc; - -use alloc::format; -use core::marker::PhantomData; - -use frame_support::dispatch::{GetDispatchInfo, Pays}; -use frame_system::RawOrigin; -use pallet_evm::{ - AddressMapping, BalanceConverter, ExitError, GasWeightMapping, HashedAddressMapping, - IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, - PrecompileSet, -}; -use pallet_evm_precompile_modexp::Modexp; -use pallet_evm_precompile_sha3fips::Sha3FIPS256; -use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256}; -use precompile_utils::EvmResult; -use sp_core::{H160, U256}; -use sp_runtime::traits::BlakeTwo256; -use sp_runtime::{AccountId32, traits::Dispatchable}; - -use pallet_admin_utils::{PrecompileEnable, PrecompileEnum}; -use sp_std::vec; - -use crate::{Runtime, RuntimeCall}; - -// Include custom precompiles -mod balance_transfer; -mod ed25519; -mod metagraph; -mod neuron; -mod staking; -mod subnet; - -use balance_transfer::*; -use ed25519::*; -use metagraph::*; -use neuron::*; -use staking::*; -use subnet::*; - -pub struct FrontierPrecompiles(PhantomData); -impl Default for FrontierPrecompiles -where - R: pallet_evm::Config, -{ - fn default() -> Self { - Self::new() - } -} - -impl FrontierPrecompiles -where - R: pallet_evm::Config, -{ - pub fn new() -> Self { - Self(Default::default()) - } - pub fn used_addresses() -> [H160; 13] { - [ - hash(1), - hash(2), - hash(3), - hash(4), - hash(5), - hash(1024), - hash(1025), - hash(Ed25519Verify::INDEX), - hash(BalanceTransferPrecompile::INDEX), - hash(StakingPrecompile::INDEX), - hash(SubnetPrecompile::INDEX), - hash(MetagraphPrecompile::INDEX), - hash(NeuronPrecompile::INDEX), - ] - } -} -impl PrecompileSet for FrontierPrecompiles -where - R: pallet_evm::Config, -{ - fn execute(&self, handle: &mut impl PrecompileHandle) -> Option { - match handle.code_address() { - // Ethereum precompiles : - a if a == hash(1) => Some(ECRecover::execute(handle)), - a if a == hash(2) => Some(Sha256::execute(handle)), - a if a == hash(3) => Some(Ripemd160::execute(handle)), - a if a == hash(4) => Some(Identity::execute(handle)), - a if a == hash(5) => Some(Modexp::execute(handle)), - // Non-Frontier specific nor Ethereum precompiles : - a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), - a if a == hash(1025) => Some(ECRecoverPublicKey::execute(handle)), - a if a == hash(Ed25519Verify::INDEX) => Some(Ed25519Verify::execute(handle)), - // Subtensor specific precompiles : - a if a == hash(BalanceTransferPrecompile::INDEX) => { - if PrecompileEnable::::get(PrecompileEnum::BalanceTransfer) { - Some(BalanceTransferPrecompile::execute(handle)) - } else { - Some(Err(PrecompileFailure::Error { - exit_status: ExitError::Other( - "Precompile Balance Transfer is disabled".into(), - ), - })) - } - } - a if a == hash(StakingPrecompile::INDEX) => { - if PrecompileEnable::::get(PrecompileEnum::Staking) { - Some(StakingPrecompile::execute(handle)) - } else { - Some(Err(PrecompileFailure::Error { - exit_status: ExitError::Other( - "Precompile Balance Transfer is disabled".into(), - ), - })) - } - } - - a if a == hash(SubnetPrecompile::INDEX) => { - if PrecompileEnable::::get(PrecompileEnum::Subnet) { - Some(SubnetPrecompile::execute(handle)) - } else { - Some(Err(PrecompileFailure::Error { - exit_status: ExitError::Other("Precompile Subnet is disabled".into()), - })) - } - } - a if a == hash(MetagraphPrecompile::INDEX) => { - if PrecompileEnable::::get(PrecompileEnum::Metagraph) { - Some(MetagraphPrecompile::execute(handle)) - } else { - Some(Err(PrecompileFailure::Error { - exit_status: ExitError::Other("Precompile Metagrah is disabled".into()), - })) - } - } - a if a == hash(NeuronPrecompile::INDEX) => { - if PrecompileEnable::::get(PrecompileEnum::Neuron) { - Some(NeuronPrecompile::execute(handle)) - } else { - Some(Err(PrecompileFailure::Error { - exit_status: ExitError::Other("Precompile Neuron is disabled".into()), - })) - } - } - - _ => None, - } - } - - fn is_precompile(&self, address: H160, _gas: u64) -> IsPrecompileResult { - IsPrecompileResult::Answer { - is_precompile: Self::used_addresses().contains(&address), - extra_cost: 0, - } - } -} - -fn hash(a: u64) -> H160 { - H160::from_low_u64_be(a) -} - -/// Takes a slice from bytes with PrecompileFailure as Error -fn parse_slice(data: &[u8], from: usize, to: usize) -> Result<&[u8], PrecompileFailure> { - let maybe_slice = data.get(from..to); - if let Some(slice) = maybe_slice { - Ok(slice) - } else { - log::error!( - "fail to get slice from data, {:?}, from {}, to {}", - &data, - from, - to - ); - Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }) - } -} - -fn parse_pubkey(data: &[u8]) -> Result<(AccountId32, vec::Vec), PrecompileFailure> { - let mut pubkey = [0u8; 32]; - pubkey.copy_from_slice(parse_slice(data, 0, 32)?); - - Ok(( - pubkey.into(), - data.get(32..) - .map_or_else(vec::Vec::new, |slice| slice.to_vec()), - )) -} - -fn try_u16_from_u256(value: U256) -> Result { - value.try_into().map_err(|_| PrecompileFailure::Error { - exit_status: ExitError::Other("the value is outside of u16 bounds".into()), - }) -} - -fn contract_to_origin(contract: &[u8; 32]) -> Result, PrecompileFailure> { - let (account_id, _) = parse_pubkey(contract)?; - Ok(RawOrigin::Signed(account_id)) -} - -trait PrecompileHandleExt: PrecompileHandle { - fn caller_account_id(&self) -> AccountId32 { - as AddressMapping>::into_account_id( - self.context().caller, - ) - } - - fn try_convert_apparent_value(&self) -> EvmResult { - let amount = self.context().apparent_value; - ::BalanceConverter::into_substrate_balance(amount).ok_or( - PrecompileFailure::Error { - exit_status: ExitError::Other( - "error converting balance from ETH to subtensor".into(), - ), - }, - ) - } - - /// Dispatches a runtime call, but also checks and records the gas costs. - fn try_dispatch_runtime_call( - &mut self, - call: impl Into, - origin: RawOrigin, - ) -> EvmResult<()> { - let call = Into::::into(call); - let info = call.get_dispatch_info(); - - let target_gas = self.gas_limit(); - if let Some(gas) = target_gas { - let valid_weight = - ::GasWeightMapping::gas_to_weight(gas, false) - .ref_time(); - if info.weight.ref_time() > valid_weight { - return Err(PrecompileFailure::Error { - exit_status: ExitError::OutOfGas, - }); - } - } - - self.record_external_cost( - Some(info.weight.ref_time()), - Some(info.weight.proof_size()), - None, - )?; - - match call.dispatch(origin.into()) { - Ok(post_info) => { - if post_info.pays_fee(&info) == Pays::Yes { - let actual_weight = post_info.actual_weight.unwrap_or(info.weight); - let cost = ::GasWeightMapping::weight_to_gas( - actual_weight, - ); - self.record_cost(cost)?; - - self.refund_external_cost( - Some( - info.weight - .ref_time() - .saturating_sub(actual_weight.ref_time()), - ), - Some( - info.weight - .proof_size() - .saturating_sub(actual_weight.proof_size()), - ), - ); - } - - log::info!("Dispatch succeeded. Post info: {:?}", post_info); - - Ok(()) - } - Err(e) => { - log::error!("Dispatch failed. Error: {:?}", e); - log::warn!("Returning error PrecompileFailure::Error"); - Err(PrecompileFailure::Error { - exit_status: ExitError::Other( - format!("dispatch execution failed: {}", <&'static str>::from(e)).into(), - ), - }) - } - } - } -} - -impl PrecompileHandleExt for T where T: PrecompileHandle {} - -trait PrecompileExt: Precompile { - const INDEX: u64; - // ss58 public key i.e., the contract sends funds it received to the destination address from - // the method parameter. - const ADDRESS_SS58: [u8; 32]; -} diff --git a/runtime/src/precompiles/neuron.rs b/runtime/src/precompiles/neuron.rs deleted file mode 100644 index 65306f87cc..0000000000 --- a/runtime/src/precompiles/neuron.rs +++ /dev/null @@ -1,173 +0,0 @@ -use frame_system::RawOrigin; -use pallet_evm::PrecompileHandle; -use precompile_utils::{EvmResult, prelude::UnboundedBytes}; -use sp_core::H256; -use sp_std::vec::Vec; - -use crate::Runtime; -use crate::precompiles::{PrecompileExt, PrecompileHandleExt, parse_pubkey}; - -pub struct NeuronPrecompile; - -impl PrecompileExt for NeuronPrecompile { - const INDEX: u64 = 2052; - const ADDRESS_SS58: [u8; 32] = [ - 0xbc, 0x46, 0x35, 0x79, 0xbc, 0x99, 0xf9, 0xee, 0x7c, 0x59, 0xed, 0xee, 0x20, 0x61, 0xa3, - 0x09, 0xd2, 0x1e, 0x68, 0xd5, 0x39, 0xb6, 0x40, 0xec, 0x66, 0x46, 0x90, 0x30, 0xab, 0x74, - 0xc1, 0xdb, - ]; -} - -#[precompile_utils::precompile] -impl NeuronPrecompile { - #[precompile::public("setWeights(uint16,uint16[],uint16[],uint64)")] - #[precompile::payable] - pub fn set_weights( - handle: &mut impl PrecompileHandle, - netuid: u16, - dests: Vec, - weights: Vec, - version_key: u64, - ) -> EvmResult<()> { - let call = pallet_subtensor::Call::::set_weights { - netuid, - dests, - weights, - version_key, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("commitWeights(uint16,bytes32)")] - #[precompile::payable] - pub fn commit_weights( - handle: &mut impl PrecompileHandle, - netuid: u16, - commit_hash: H256, - ) -> EvmResult<()> { - let call = pallet_subtensor::Call::::commit_weights { - netuid, - commit_hash, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("revealWeights(uint16,uint16[],uint16[],uint16[],uint64)")] - #[precompile::payable] - pub fn reveal_weights( - handle: &mut impl PrecompileHandle, - netuid: u16, - uids: Vec, - values: Vec, - salt: Vec, - version_key: u64, - ) -> EvmResult<()> { - let call = pallet_subtensor::Call::::reveal_weights { - netuid, - uids, - values, - salt, - version_key, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("burnedRegister(uint16,bytes32)")] - #[precompile::payable] - fn burned_register( - handle: &mut impl PrecompileHandle, - netuid: u16, - hotkey: H256, - ) -> EvmResult<()> { - let coldkey = handle.caller_account_id(); - let (hotkey, _) = parse_pubkey(hotkey.as_bytes())?; - let call = pallet_subtensor::Call::::burned_register { netuid, hotkey }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(coldkey)) - } - - #[precompile::public("serveAxon(uint16,uint32,uint128,uint16,uint8,uint8,uint8,uint8)")] - #[precompile::payable] - #[allow(clippy::too_many_arguments)] - fn serve_axon( - handle: &mut impl PrecompileHandle, - netuid: u16, - version: u32, - ip: u128, - port: u16, - ip_type: u8, - protocol: u8, - placeholder1: u8, - placeholder2: u8, - ) -> EvmResult<()> { - let call = pallet_subtensor::Call::::serve_axon { - netuid, - version, - ip, - port, - ip_type, - protocol, - placeholder1, - placeholder2, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public( - "serveAxonTls(uint16,uint32,uint128,uint16,uint8,uint8,uint8,uint8,bytes)" - )] - #[precompile::payable] - #[allow(clippy::too_many_arguments)] - fn serve_axon_tls( - handle: &mut impl PrecompileHandle, - netuid: u16, - version: u32, - ip: u128, - port: u16, - ip_type: u8, - protocol: u8, - placeholder1: u8, - placeholder2: u8, - certificate: UnboundedBytes, - ) -> EvmResult<()> { - let call = pallet_subtensor::Call::::serve_axon_tls { - netuid, - version, - ip, - port, - ip_type, - protocol, - placeholder1, - placeholder2, - certificate: certificate.into(), - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("servePrometheus(uint16,uint32,uint128,uint16,uint8)")] - #[precompile::payable] - #[allow(clippy::too_many_arguments)] - fn serve_prometheus( - handle: &mut impl PrecompileHandle, - netuid: u16, - version: u32, - ip: u128, - port: u16, - ip_type: u8, - ) -> EvmResult<()> { - let call = pallet_subtensor::Call::::serve_prometheus { - netuid, - version, - ip, - port, - ip_type, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } -} diff --git a/runtime/src/precompiles/solidity/balanceTransfer.abi b/runtime/src/precompiles/solidity/balanceTransfer.abi deleted file mode 100644 index 99913b9005..0000000000 --- a/runtime/src/precompiles/solidity/balanceTransfer.abi +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - } - ], - "name": "transfer", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } -] \ No newline at end of file diff --git a/runtime/src/precompiles/solidity/balanceTransfer.sol b/runtime/src/precompiles/solidity/balanceTransfer.sol deleted file mode 100644 index 42790b9005..0000000000 --- a/runtime/src/precompiles/solidity/balanceTransfer.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma solidity ^0.8.0; - -address constant ISUBTENSOR_BALANCE_TRANSFER_ADDRESS = 0x0000000000000000000000000000000000000800; - -interface ISubtensorBalanceTransfer { - function transfer(bytes32 data) external payable; -} \ No newline at end of file diff --git a/runtime/src/precompiles/solidity/ed25519Verify.abi b/runtime/src/precompiles/solidity/ed25519Verify.abi deleted file mode 100644 index 05d75ae6cc..0000000000 --- a/runtime/src/precompiles/solidity/ed25519Verify.abi +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "inputs": [ - { "internalType": "bytes32", "name": "message", "type": "bytes32" }, - { "internalType": "bytes32", "name": "publicKey", "type": "bytes32" }, - { "internalType": "bytes32", "name": "r", "type": "bytes32" }, - { "internalType": "bytes32", "name": "s", "type": "bytes32" } - ], - "name": "verify", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "pure", - "type": "function" - } -] \ No newline at end of file diff --git a/runtime/src/precompiles/solidity/ed25519Verify.sol b/runtime/src/precompiles/solidity/ed25519Verify.sol deleted file mode 100644 index 035feb4cc4..0000000000 --- a/runtime/src/precompiles/solidity/ed25519Verify.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.0; - -address constant IED25519VERIFY_ADDRESS = 0x0000000000000000000000000000000000000402; - -interface IEd25519Verify { - /** - * @dev Verifies Ed25519 signature using provided message and public key. - * - * @param message The 32-byte signature payload message. - * @param publicKey 32-byte public key matching to private key used to sign the message. - * @param r The Ed25519 signature commitment (first 32 bytes). - * @param s The Ed25519 signature response (second 32 bytes). - * @return bool Returns true if the signature is valid for the given message and public key, false otherwise. - */ - function verify(bytes32 message, bytes32 publicKey, bytes32 r, bytes32 s) external pure returns (bool); -} diff --git a/runtime/src/precompiles/solidity/metagraph.abi b/runtime/src/precompiles/solidity/metagraph.abi deleted file mode 100644 index eb4b9be6ab..0000000000 --- a/runtime/src/precompiles/solidity/metagraph.abi +++ /dev/null @@ -1,389 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "uid", - "type": "uint16" - } - ], - "name": "getAxon", - "outputs": [ - { - "components": [ - { - "internalType": "uint64", - "name": "block", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "version", - "type": "uint32" - }, - { - "internalType": "uint128", - "name": "ip", - "type": "uint128" - }, - { - "internalType": "uint16", - "name": "port", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "ip_type", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "protocol", - "type": "uint8" - } - ], - "internalType": "struct AxonInfo", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "uid", - "type": "uint16" - } - ], - "name": "getColdkey", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "uid", - "type": "uint16" - } - ], - "name": "getConsensus", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "uid", - "type": "uint16" - } - ], - "name": "getDividends", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "uid", - "type": "uint16" - } - ], - "name": "getEmission", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "uid", - "type": "uint16" - } - ], - "name": "getHotkey", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "uid", - "type": "uint16" - } - ], - "name": "getIncentive", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "uid", - "type": "uint16" - } - ], - "name": "getIsActive", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "uid", - "type": "uint16" - } - ], - "name": "getLastUpdate", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "uid", - "type": "uint16" - } - ], - "name": "getRank", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "uid", - "type": "uint16" - } - ], - "name": "getStake", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "uid", - "type": "uint16" - } - ], - "name": "getTrust", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getUidCount", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "uid", - "type": "uint16" - } - ], - "name": "getValidatorStatus", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "uid", - "type": "uint16" - } - ], - "name": "getVtrust", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - } -] \ No newline at end of file diff --git a/runtime/src/precompiles/solidity/metagraph.sol b/runtime/src/precompiles/solidity/metagraph.sol deleted file mode 100644 index 3a19281a57..0000000000 --- a/runtime/src/precompiles/solidity/metagraph.sol +++ /dev/null @@ -1,134 +0,0 @@ -pragma solidity ^0.8.0; - -address constant IMetagraph_ADDRESS = 0x0000000000000000000000000000000000000802; - -struct AxonInfo { - uint64 block; - uint32 version; - uint128 ip; - uint16 port; - uint8 ip_type; - uint8 protocol; -} - -interface IMetagraph { - - /** - * @dev Returns the count of unique identifiers (UIDs) associated with a given network identifier (netuid). - * @param netuid The network identifier for which to retrieve the UID count. - * @return The count of UIDs associated with the specified netuid. - */ - function getUidCount(uint16 netuid) external view returns (uint16); - - /** - * @dev Retrieves the stake amount associated with a given network identifier (netuid) and unique identifier (uid). - * @param netuid The network identifier for which to retrieve the stake. - * @param uid The unique identifier for which to retrieve the stake. - * @return The stake amount associated with the specified netuid and uid. - */ - function getStake(uint16 netuid, uint16 uid) external view returns (uint64); - - /** - * @dev Retrieves the rank of a node with a given network identifier (netuid) and unique identifier (uid). - * @param netuid The network identifier for which to retrieve the rank. - * @param uid The unique identifier for which to retrieve the rank. - * @return The rank of the node with the specified netuid and uid. - */ - function getRank(uint16 netuid, uint16 uid) external view returns (uint16); - - /** - * @dev Retrieves the trust value of a node with a given network identifier (netuid) and unique identifier (uid). - * @param netuid The network identifier for which to retrieve the trust value. - * @param uid The unique identifier for which to retrieve the trust value. - * @return The trust value of the node with the specified netuid and uid. - */ - function getTrust(uint16 netuid, uint16 uid) external view returns (uint16); - - /** - * @dev Retrieves the consensus value of a node with a given network identifier (netuid) and unique identifier (uid). - * @param netuid The network identifier for which to retrieve the consensus value. - * @param uid The unique identifier for which to retrieve the consensus value. - * @return The consensus value of the node with the specified netuid and uid. - */ - function getConsensus(uint16 netuid, uint16 uid) external view returns (uint16); - - /** - * @dev Retrieves the incentive value of a node with a given network identifier (netuid) and unique identifier (uid). - * @param netuid The network identifier for which to retrieve the incentive value. - * @param uid The unique identifier for which to retrieve the incentive value. - * @return The incentive value of the node with the specified netuid and uid. - */ - function getIncentive(uint16 netuid, uint16 uid) external view returns (uint16); - - /** - * @dev Retrieves the dividend value of a node with a given network identifier (netuid) and unique identifier (uid). - * @param netuid The network identifier for which to retrieve the dividend value. - * @param uid The unique identifier for which to retrieve the dividend value. - * @return The dividend value of the node with the specified netuid and uid. - */ - function getDividends(uint16 netuid, uint16 uid) external view returns (uint16); - - /** - * @dev Retrieves the emission value of a node with a given network identifier (netuid) and unique identifier (uid). - * @param netuid The network identifier for which to retrieve the emission value. - * @param uid The unique identifier for which to retrieve the emission value. - * @return The emission value of the node with the specified netuid and uid. - */ - function getEmission(uint16 netuid, uint16 uid) external view returns (uint64); - - /** - * @dev Retrieves the v-trust value of a node with a given network identifier (netuid) and unique identifier (uid). - * @param netuid The network identifier for which to retrieve the v-trust value. - * @param uid The unique identifier for which to retrieve the v-trust value. - * @return The v-trust value of the node with the specified netuid and uid. - */ - function getVtrust(uint16 netuid, uint16 uid) external view returns (uint16); - - /** - * @dev Checks the validator status of a node with a given network identifier (netuid) and unique identifier (uid). - * @param netuid The network identifier for which to check the validator status. - * @param uid The unique identifier for which to check the validator status. - * @return Returns true if the node is a validator, false otherwise. - */ - function getValidatorStatus(uint16 netuid, uint16 uid) external view returns (bool); - - /** - * @dev Retrieves the last update timestamp of a node with a given network identifier (netuid) and unique identifier (uid). - * @param netuid The network identifier for which to retrieve the last update timestamp. - * @param uid The unique identifier for which to retrieve the last update timestamp. - * @return The last update timestamp of the node with the specified netuid and uid. - */ - function getLastUpdate(uint16 netuid, uint16 uid) external view returns (uint64); - - /** - * @dev Checks if a node with a given network identifier (netuid) and unique identifier (uid) is active. - * @param netuid The network identifier for which to check the node's activity. - * @param uid The unique identifier for which to check the node's activity. - * @return Returns true if the node is active, false otherwise. - */ - function getIsActive(uint16 netuid, uint16 uid) external view returns (bool); - - /** - * @dev Retrieves the axon information of a node with a given network identifier (netuid) and unique identifier (uid). - * @param netuid The network identifier for which to retrieve the axon information. - * @param uid The unique identifier for which to retrieve the axon information. - * @return The axon information of the node with the specified netuid and uid. - */ - function getAxon(uint16 netuid, uint16 uid) external view returns (AxonInfo memory); - - /** - * @dev Retrieves the hotkey of a node with a given network identifier (netuid) and unique identifier (uid). - * @param netuid The network identifier for which to retrieve the hotkey. - * @param uid The unique identifier for which to retrieve the hotkey. - * @return The hotkey of the node with the specified netuid and uid. - */ - function getHotkey(uint16 netuid, uint16 uid) external view returns (bytes32); - - /** - * @dev Retrieves the coldkey of a node with a given network identifier (netuid) and unique identifier (uid). - * @param netuid The network identifier for which to retrieve the coldkey. - * @param uid The unique identifier for which to retrieve the coldkey. - * @return The coldkey of the node with the specified netuid and uid. - */ - function getColdkey(uint16 netuid, uint16 uid) external view returns (bytes32); -} diff --git a/runtime/src/precompiles/solidity/neuron.abi b/runtime/src/precompiles/solidity/neuron.abi deleted file mode 100644 index e4ffb6fa18..0000000000 --- a/runtime/src/precompiles/solidity/neuron.abi +++ /dev/null @@ -1,233 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "bytes32", - "name": "hotkey", - "type": "bytes32" - } - ], - "name": "burnedRegister", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "bytes32", - "name": "commitHash", - "type": "bytes32" - } - ], - "name": "commitWeights", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16[]", - "name": "uids", - "type": "uint16[]" - }, - { - "internalType": "uint16[]", - "name": "values", - "type": "uint16[]" - }, - { - "internalType": "uint16[]", - "name": "salt", - "type": "uint16[]" - }, - { - "internalType": "uint64", - "name": "versionKey", - "type": "uint64" - } - ], - "name": "revealWeights", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "version", - "type": "uint32" - }, - { - "internalType": "uint128", - "name": "ip", - "type": "uint128" - }, - { - "internalType": "uint16", - "name": "port", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "ipType", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "protocol", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "placeholder1", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "placeholder2", - "type": "uint8" - } - ], - "name": "serveAxon", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "version", - "type": "uint32" - }, - { - "internalType": "uint128", - "name": "ip", - "type": "uint128" - }, - { - "internalType": "uint16", - "name": "port", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "ipType", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "protocol", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "placeholder1", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "placeholder2", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "certificate", - "type": "bytes" - } - ], - "name": "serveAxonTls", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "version", - "type": "uint32" - }, - { - "internalType": "uint128", - "name": "ip", - "type": "uint128" - }, - { - "internalType": "uint16", - "name": "port", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "ipType", - "type": "uint8" - } - ], - "name": "servePrometheus", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16[]", - "name": "dests", - "type": "uint16[]" - }, - { - "internalType": "uint16[]", - "name": "weights", - "type": "uint16[]" - }, - { - "internalType": "uint64", - "name": "versionKey", - "type": "uint64" - } - ], - "name": "setWeights", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/runtime/src/precompiles/solidity/neuron.sol b/runtime/src/precompiles/solidity/neuron.sol deleted file mode 100644 index 204bc3f600..0000000000 --- a/runtime/src/precompiles/solidity/neuron.sol +++ /dev/null @@ -1,122 +0,0 @@ -pragma solidity ^0.8.0; - -address constant INeuron_ADDRESS = 0x0000000000000000000000000000000000000804; - -interface INeuron { - /** - * @dev Registers a neuron by calling `do_burned_registration` internally with the origin set to the ss58 mirror of the H160 address. - * This allows the H160 to further call neuron-related methods and receive emissions. - * - * @param netuid The subnet to register the neuron to (uint16). - * @param hotkey The hotkey public key (32 bytes). - */ - function burnedRegister(uint16 netuid, bytes32 hotkey) external payable; - - /** - * @dev Registers axon information for a neuron. - * This function is used to serve axon information, including the subnet to register to, version, IP address, port, IP type, protocol, and placeholders for future use. - * - * @param netuid The subnet to register the axon to (uint16). - * @param version The version of the axon (uint32). - * @param ip The IP address of the axon (uint128). - * @param port The port number of the axon (uint16). - * @param ipType The type of IP address (uint8). - * @param protocol The protocol used by the axon (uint8). - * @param placeholder1 Placeholder for future use (uint8). - * @param placeholder2 Placeholder for future use (uint8). - */ - function serveAxon( - uint16 netuid, - uint32 version, - uint128 ip, - uint16 port, - uint8 ipType, - uint8 protocol, - uint8 placeholder1, - uint8 placeholder2 - ) external payable; - - /** - * @dev Serves axon information for a neuron over TLS. - * This function is used to serve axon information, including the subnet to register to, version, IP address, port, IP type, protocol, and placeholders for future use. - * - * @param netuid The subnet to register the axon to (uint16). - * @param version The version of the axon (uint32). - * @param ip The IP address of the axon (uint128). - * @param port The port number of the axon (uint16). - * @param ipType The type of IP address (uint8). - * @param protocol The protocol used by the axon (uint8). - * @param placeholder1 Placeholder for future use (uint8). - * @param placeholder2 Placeholder for future use (uint8). - * @param certificate The TLS certificate for the axon (bytes). - */ - function serveAxonTls( - uint16 netuid, - uint32 version, - uint128 ip, - uint16 port, - uint8 ipType, - uint8 protocol, - uint8 placeholder1, - uint8 placeholder2, - bytes memory certificate - ) external payable; - - /** - * @dev Serves Prometheus information for a neuron. - * This function is used to serve Prometheus information, including the subnet to register to, version, IP address, port, and IP type. - * - * @param netuid The subnet to register the Prometheus information to (uint16). - * @param version The version of the Prometheus information (uint32). - * @param ip The IP address of the Prometheus information (uint128). - * @param port The port number of the Prometheus information (uint16). - * @param ipType The type of IP address (uint8). - */ - function servePrometheus( - uint16 netuid, - uint32 version, - uint128 ip, - uint16 port, - uint8 ipType - ) external payable; - - /** - * @dev Sets the weights for a neuron. - * - * @param netuid The subnet to set the weights for (uint16). - * @param dests The destinations of the weights (uint16[]). - * @param weights The weights to set (uint16[]). - * @param versionKey The version key for the weights (uint64). - */ - function setWeights( - uint16 netuid, - uint16[] memory dests, - uint16[] memory weights, - uint64 versionKey - ) external payable; - - /** - * @dev Commits the weights for a neuron. - * - * @param netuid The subnet to commit the weights for (uint16). - * @param commitHash The commit hash for the weights (bytes32). - */ - function commitWeights(uint16 netuid, bytes32 commitHash) external payable; - - /** - * @dev Reveals the weights for a neuron. - * - * @param netuid The subnet to reveal the weights for (uint16). - * @param uids The unique identifiers for the weights (uint16[]). - * @param values The values of the weights (uint16[]). - * @param salt The salt values for the weights (uint16[]). - * @param versionKey The version key for the weights (uint64). - */ - function revealWeights( - uint16 netuid, - uint16[] memory uids, - uint16[] memory values, - uint16[] memory salt, - uint64 versionKey - ) external payable; -} diff --git a/runtime/src/precompiles/solidity/staking.abi b/runtime/src/precompiles/solidity/staking.abi deleted file mode 100644 index 3c4a018c90..0000000000 --- a/runtime/src/precompiles/solidity/staking.abi +++ /dev/null @@ -1,98 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "delegate", - "type": "bytes32" - } - ], - "name": "addProxy", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hotkey", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "netuid", - "type": "uint256" - } - ], - "name": "addStake", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "delegate", - "type": "bytes32" - } - ], - "name": "removeProxy", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hotkey", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "coldkey", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "netuid", - "type": "uint256" - } - ], - "name": "getStake", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hotkey", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "netuid", - "type": "uint256" - } - ], - "name": "removeStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] \ No newline at end of file diff --git a/runtime/src/precompiles/solidity/staking.sol b/runtime/src/precompiles/solidity/staking.sol deleted file mode 100644 index 19d51d0470..0000000000 --- a/runtime/src/precompiles/solidity/staking.sol +++ /dev/null @@ -1,79 +0,0 @@ -pragma solidity ^0.8.0; - -address constant ISTAKING_ADDRESS = 0x0000000000000000000000000000000000000801; - -interface IStaking { - /** - * @dev Adds a subtensor stake corresponding to the value sent with the transaction, associated - * with the `hotkey`. - * - * This function allows external accounts and contracts to stake TAO into the subtensor pallet, - * which effectively calls `add_stake` on the subtensor pallet with specified hotkey as a parameter - * and coldkey being the hashed address mapping of H160 sender address to Substrate ss58 address as - * implemented in Frontier HashedAddressMapping: - * https://github.com/polkadot-evm/frontier/blob/2e219e17a526125da003e64ef22ec037917083fa/frame/evm/src/lib.rs#L739 - * - * @param hotkey The hotkey public key (32 bytes). - * @param netuid The subnet to stake to (uint256). - * - * Requirements: - * - `hotkey` must be a valid hotkey registered on the network, ensuring that the stake is - * correctly attributed. - */ - function addStake(bytes32 hotkey, uint256 netuid) external payable; - - /** - * @dev Removes a subtensor stake `amount` from the specified `hotkey`. - * - * This function allows external accounts and contracts to unstake TAO from the subtensor pallet, - * which effectively calls `remove_stake` on the subtensor pallet with specified hotkey as a parameter - * and coldkey being the hashed address mapping of H160 sender address to Substrate ss58 address as - * implemented in Frontier HashedAddressMapping: - * https://github.com/polkadot-evm/frontier/blob/2e219e17a526125da003e64ef22ec037917083fa/frame/evm/src/lib.rs#L739 - * - * @param hotkey The hotkey public key (32 bytes). - * @param amount The amount to unstake in rao. - * @param netuid The subnet to stake to (uint256). - * - * Requirements: - * - `hotkey` must be a valid hotkey registered on the network, ensuring that the stake is - * correctly attributed. - * - The existing stake amount must be not lower than specified amount - */ - function removeStake( - bytes32 hotkey, - uint256 amount, - uint256 netuid - ) external; - - /** - * @dev Delegates staking to a proxy account. - * - * @param delegate The public key (32 bytes) of the delegate. - */ - function addProxy(bytes32 delegate) external; - - /** - * @dev Removes staking proxy account. - * - * @param delegate The public key (32 bytes) of the delegate. - */ - function removeProxy(bytes32 delegate) external; - - /** - * @dev Returns the stake amount associated with the specified `hotkey` and `coldkey`. - * - * This function retrieves the current stake amount linked to a specific hotkey and coldkey pair. - * It is a view function, meaning it does not modify the state of the contract and is free to call. - * - * @param hotkey The hotkey public key (32 bytes). - * @param coldkey The coldkey public key (32 bytes). - * @param netuid The subnet the stake is on (uint256). - * @return The current stake amount in uint256 format. - */ - function getStake( - bytes32 hotkey, - bytes32 coldkey, - uint256 netuid - ) external view returns (uint256); -} diff --git a/runtime/src/precompiles/solidity/subnet.abi b/runtime/src/precompiles/solidity/subnet.abi deleted file mode 100644 index 3cc16d9df7..0000000000 --- a/runtime/src/precompiles/solidity/subnet.abi +++ /dev/null @@ -1,887 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getActivityCutoff", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getAdjustmentAlpha", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getAlphaValues", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getBondsMovingAverage", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getCommitRevealWeightsEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getCommitRevealWeightsInterval", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getDifficulty", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "name": "getImmunityPeriod", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "name": "getKappa", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getLiquidAlphaEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getMaxBurn", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getMaxDifficulty", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getMaxWeightLimit", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getMinAllowedWeights", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getMinBurn", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getMinDifficulty", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getNetworkPowRegistrationAllowed", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getNetworkRegistrationAllowed", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "name": "getRho", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getServingRateLimit", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getWeightsSetRateLimit", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - } - ], - "name": "getWeightsVersionKey", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hotkey", - "type": "bytes32" - } - ], - "name": "registerNetwork", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hotkey", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "subnetName", - "type": "string" - }, - { - "internalType": "string", - "name": "githubRepo", - "type": "string" - }, - { - "internalType": "string", - "name": "subnetContact", - "type": "string" - }, - { - "internalType": "string", - "name": "subnetUrl", - "type": "string" - }, - { - "internalType": "string", - "name": "discord", - "type": "string" - }, - { - "internalType": "string", - "name": "description", - "type": "string" - }, - { - "internalType": "string", - "name": "additional", - "type": "string" - } - ], - "name": "registerNetwork", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "activityCutoff", - "type": "uint16" - } - ], - "name": "setActivityCutoff", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "adjustmentAlpha", - "type": "uint64" - } - ], - "name": "setAdjustmentAlpha", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "alphaLow", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "alphaHigh", - "type": "uint16" - } - ], - "name": "setAlphaValues", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "bondsMovingAverage", - "type": "uint64" - } - ], - "name": "setBondsMovingAverage", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "bool", - "name": "commitRevealWeightsEnabled", - "type": "bool" - } - ], - "name": "setCommitRevealWeightsEnabled", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "commitRevealWeightsInterval", - "type": "uint64" - } - ], - "name": "setCommitRevealWeightsInterval", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "difficulty", - "type": "uint64" - } - ], - "name": "setDifficulty", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "immunityPeriod", - "type": "uint16" - } - ], - "name": "setImmunityPeriod", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "kappa", - "type": "uint16" - } - ], - "name": "setKappa", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "bool", - "name": "liquidAlphaEnabled", - "type": "bool" - } - ], - "name": "setLiquidAlphaEnabled", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "maxBurn", - "type": "uint64" - } - ], - "name": "setMaxBurn", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "maxDifficulty", - "type": "uint64" - } - ], - "name": "setMaxDifficulty", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "maxWeightLimit", - "type": "uint16" - } - ], - "name": "setMaxWeightLimit", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "minAllowedWeights", - "type": "uint16" - } - ], - "name": "setMinAllowedWeights", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "minBurn", - "type": "uint64" - } - ], - "name": "setMinBurn", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "minDifficulty", - "type": "uint64" - } - ], - "name": "setMinDifficulty", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "bool", - "name": "networkPowRegistrationAllowed", - "type": "bool" - } - ], - "name": "setNetworkPowRegistrationAllowed", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "bool", - "name": "networkRegistrationAllowed", - "type": "bool" - } - ], - "name": "setNetworkRegistrationAllowed", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "rho", - "type": "uint16" - } - ], - "name": "setRho", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "servingRateLimit", - "type": "uint64" - } - ], - "name": "setServingRateLimit", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "weightsSetRateLimit", - "type": "uint64" - } - ], - "name": "setWeightsSetRateLimit", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "netuid", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "weightsVersionKey", - "type": "uint64" - } - ], - "name": "setWeightsVersionKey", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/runtime/src/precompiles/solidity/subnet.sol b/runtime/src/precompiles/solidity/subnet.sol deleted file mode 100644 index d5ef0916d9..0000000000 --- a/runtime/src/precompiles/solidity/subnet.sol +++ /dev/null @@ -1,173 +0,0 @@ -pragma solidity ^0.8.0; - -address constant ISUBNET_ADDRESS = 0x0000000000000000000000000000000000000803; - -interface ISubnet { - /// Registers a new network without specifying details. - function registerNetwork(bytes32 hotkey) external payable; - /// Registers a new network with specified subnet name, GitHub repository, and contact information. - function registerNetwork( - bytes32 hotkey, - string memory subnetName, - string memory githubRepo, - string memory subnetContact, - string memory subnetUrl, - string memory discord, - string memory description, - string memory additional - ) external payable; - - function getServingRateLimit(uint16 netuid) external view returns (uint64); - - function setServingRateLimit( - uint16 netuid, - uint64 servingRateLimit - ) external payable; - - function getMinDifficulty(uint16 netuid) external view returns (uint64); - - function setMinDifficulty( - uint16 netuid, - uint64 minDifficulty - ) external payable; - - function getMaxDifficulty(uint16 netuid) external view returns (uint64); - - function setMaxDifficulty( - uint16 netuid, - uint64 maxDifficulty - ) external payable; - - function getWeightsVersionKey(uint16 netuid) external view returns (uint64); - - function setWeightsVersionKey( - uint16 netuid, - uint64 weightsVersionKey - ) external payable; - - function getWeightsSetRateLimit( - uint16 netuid - ) external view returns (uint64); - - function setWeightsSetRateLimit( - uint16 netuid, - uint64 weightsSetRateLimit - ) external payable; - - function getAdjustmentAlpha(uint16 netuid) external view returns (uint64); - - function setAdjustmentAlpha( - uint16 netuid, - uint64 adjustmentAlpha - ) external payable; - - function getMaxWeightLimit(uint16 netuid) external view returns (uint16); - - function setMaxWeightLimit( - uint16 netuid, - uint16 maxWeightLimit - ) external payable; - - function getImmunityPeriod(uint16) external view returns (uint16); - - function setImmunityPeriod( - uint16 netuid, - uint64 immunityPeriod - ) external payable; - - function getMinAllowedWeights(uint16 netuid) external view returns (uint16); - - function setMinAllowedWeights( - uint16 netuid, - uint16 minAllowedWeights - ) external payable; - - function getKappa(uint16) external view returns (uint16); - - function setKappa(uint16 netuid, uint16 kappa) external payable; - - function getRho(uint16) external view returns (uint16); - - function setRho(uint16 netuid, uint16 rho) external payable; - - function getActivityCutoff(uint16 netuid) external view returns (uint16); - - function setActivityCutoff( - uint16 netuid, - uint16 activityCutoff - ) external payable; - - function getNetworkRegistrationAllowed( - uint16 netuid - ) external view returns (bool); - - function setNetworkRegistrationAllowed( - uint16 netuid, - bool networkRegistrationAllowed - ) external payable; - - function getNetworkPowRegistrationAllowed( - uint16 netuid - ) external view returns (bool); - - function setNetworkPowRegistrationAllowed( - uint16 netuid, - bool networkPowRegistrationAllowed - ) external payable; - - function getMinBurn(uint16 netuid) external view returns (uint64); - - function setMinBurn(uint16 netuid, uint64 minBurn) external payable; - - function getMaxBurn(uint16 netuid) external view returns (uint64); - - function setMaxBurn(uint16 netuid, uint64 maxBurn) external payable; - - function getDifficulty(uint16 netuid) external view returns (uint64); - - function setDifficulty(uint16 netuid, uint64 difficulty) external payable; - - function getBondsMovingAverage( - uint16 netuid - ) external view returns (uint64); - - function setBondsMovingAverage( - uint16 netuid, - uint64 bondsMovingAverage - ) external payable; - - function getCommitRevealWeightsEnabled( - uint16 netuid - ) external view returns (bool); - - function setCommitRevealWeightsEnabled( - uint16 netuid, - bool commitRevealWeightsEnabled - ) external payable; - - function getLiquidAlphaEnabled(uint16 netuid) external view returns (bool); - - function setLiquidAlphaEnabled( - uint16 netuid, - bool liquidAlphaEnabled - ) external payable; - - function getAlphaValues( - uint16 netuid - ) external view returns (uint16, uint16); - - function setAlphaValues( - uint16 netuid, - uint16 alphaLow, - uint16 alphaHigh - ) external payable; - - function getCommitRevealWeightsInterval( - uint16 netuid - ) external view returns (uint64); - - function setCommitRevealWeightsInterval( - uint16 netuid, - uint64 commitRevealWeightsInterval - ) external payable; -} diff --git a/runtime/src/precompiles/staking.rs b/runtime/src/precompiles/staking.rs deleted file mode 100644 index 848fe8e750..0000000000 --- a/runtime/src/precompiles/staking.rs +++ /dev/null @@ -1,171 +0,0 @@ -// The goal of staking precompile is to allow interaction between EVM users and smart contracts and -// subtensor staking functionality, namely add_stake, and remove_stake extrinsicsk, as well as the -// staking state. -// -// Additional requirement is to preserve compatibility with Ethereum indexers, which requires -// no balance transfers from EVM accounts without a corresponding transaction that can be -// parsed by an indexer. -// -// Implementation of add_stake: -// - User transfers balance that will be staked to the precompile address with a payable -// method addStake. This method also takes hotkey public key (bytes32) of the hotkey -// that the stake should be assigned to. -// - Precompile transfers the balance back to the signing address, and then invokes -// do_add_stake from subtensor pallet with signing origin that mmatches to HashedAddressMapping -// of the message sender, which will effectively withdraw and stake balance from the message -// sender. -// - Precompile checks the result of do_add_stake and, in case of a failure, reverts the transaction, -// and leaves the balance on the message sender account. -// -// Implementation of remove_stake: -// - User involkes removeStake method and specifies hotkey public key (bytes32) of the hotkey -// to remove stake from, and the amount to unstake. -// - Precompile calls do_remove_stake method of the subtensor pallet with the signing origin of message -// sender, which effectively unstakes the specified amount and credits it to the message sender -// - Precompile checks the result of do_remove_stake and, in case of a failure, reverts the transaction. -// - -use frame_system::RawOrigin; -use pallet_evm::{BalanceConverter, ExitError, PrecompileFailure, PrecompileHandle}; -use precompile_utils::EvmResult; -use sp_core::{H256, U256}; -use sp_runtime::AccountId32; -use sp_runtime::traits::{Dispatchable, StaticLookup, UniqueSaturatedInto}; - -use crate::precompiles::{PrecompileExt, PrecompileHandleExt, parse_pubkey, try_u16_from_u256}; -use crate::{ProxyType, Runtime, RuntimeCall}; - -pub struct StakingPrecompile; - -impl PrecompileExt for StakingPrecompile { - const INDEX: u64 = 2049; - const ADDRESS_SS58: [u8; 32] = [ - 0x26, 0xf4, 0x10, 0x1e, 0x52, 0xb7, 0x57, 0x34, 0x33, 0x24, 0x5b, 0xc3, 0x0a, 0xe1, 0x8b, - 0x63, 0x99, 0x53, 0xd8, 0x41, 0x79, 0x33, 0x03, 0x61, 0x4d, 0xfa, 0xcf, 0xf0, 0x37, 0xf7, - 0x12, 0x94, - ]; -} - -#[precompile_utils::precompile] -impl StakingPrecompile { - #[precompile::public("addStake(bytes32,uint256)")] - #[precompile::payable] - fn add_stake(handle: &mut impl PrecompileHandle, address: H256, netuid: U256) -> EvmResult<()> { - let account_id = handle.caller_account_id(); - let amount = handle.context().apparent_value; - - if !amount.is_zero() { - Self::transfer_back_to_caller(&account_id, amount)?; - } - - let amount_sub = handle.try_convert_apparent_value()?; - let (hotkey, _) = parse_pubkey(address.as_bytes())?; - let netuid = try_u16_from_u256(netuid)?; - let call = pallet_subtensor::Call::::add_stake { - hotkey, - netuid, - amount_staked: amount_sub.unique_saturated_into(), - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(account_id)) - } - - #[precompile::public("removeStake(bytes32,uint256,uint256)")] - fn remove_stake( - handle: &mut impl PrecompileHandle, - address: H256, - amount: U256, - netuid: U256, - ) -> EvmResult<()> { - let account_id = handle.caller_account_id(); - let (hotkey, _) = parse_pubkey(address.as_bytes())?; - let netuid = try_u16_from_u256(netuid)?; - let amount_unstaked = amount.unique_saturated_into(); - let call = pallet_subtensor::Call::::remove_stake { - hotkey, - netuid, - amount_unstaked, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(account_id)) - } - - #[precompile::public("addProxy(bytes32)")] - fn add_proxy(handle: &mut impl PrecompileHandle, delegate: H256) -> EvmResult<()> { - let account_id = handle.caller_account_id(); - let (delegate, _) = parse_pubkey(delegate.as_bytes())?; - let delegate = ::Lookup::unlookup(delegate); - let call = pallet_proxy::Call::::add_proxy { - delegate, - proxy_type: ProxyType::Staking, - delay: 0, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(account_id)) - } - - #[precompile::public("removeProxy(bytes32)")] - fn remove_proxy(handle: &mut impl PrecompileHandle, delegate: H256) -> EvmResult<()> { - let account_id = handle.caller_account_id(); - let (delegate, _) = parse_pubkey(delegate.as_bytes())?; - let delegate = ::Lookup::unlookup(delegate); - let call = pallet_proxy::Call::::remove_proxy { - delegate, - proxy_type: ProxyType::Staking, - delay: 0, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(account_id)) - } - - #[precompile::public("getStake(bytes32,bytes32,uint256)")] - #[precompile::view] - fn get_stake( - _: &mut impl PrecompileHandle, - hotkey: H256, - coldkey: H256, - netuid: U256, - ) -> EvmResult { - let (hotkey, _) = parse_pubkey(hotkey.as_bytes())?; - let (coldkey, _) = parse_pubkey(coldkey.as_bytes())?; - let netuid = try_u16_from_u256(netuid)?; - let stake = pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey, netuid, - ); - - Ok(stake.into()) - } - - fn transfer_back_to_caller( - account_id: &AccountId32, - amount: U256, - ) -> Result<(), PrecompileFailure> { - let smart_contract_account_id: AccountId32 = Self::ADDRESS_SS58.into(); - let amount_sub = - ::BalanceConverter::into_substrate_balance(amount) - .ok_or(ExitError::OutOfFund)?; - - // Create a transfer call from the smart contract to the caller - let transfer_call = - RuntimeCall::Balances(pallet_balances::Call::::transfer_allow_death { - dest: account_id.clone().into(), - value: amount_sub.unique_saturated_into(), - }); - - // Execute the transfer - let transfer_result = - transfer_call.dispatch(RawOrigin::Signed(smart_contract_account_id).into()); - - if let Err(dispatch_error) = transfer_result { - log::error!( - "Transfer back to caller failed. Error: {:?}", - dispatch_error - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::Other("Transfer back to caller failed".into()), - }); - } - - Ok(()) - } -} diff --git a/runtime/src/precompiles/subnet.rs b/runtime/src/precompiles/subnet.rs deleted file mode 100644 index db46b3033b..0000000000 --- a/runtime/src/precompiles/subnet.rs +++ /dev/null @@ -1,522 +0,0 @@ -use frame_support::traits::ConstU32; -use frame_system::RawOrigin; -use pallet_evm::PrecompileHandle; -use precompile_utils::{EvmResult, prelude::BoundedString}; -use sp_core::H256; - -use crate::Runtime; -use crate::precompiles::{PrecompileExt, PrecompileHandleExt, parse_pubkey}; - -pub struct SubnetPrecompile; - -impl PrecompileExt for SubnetPrecompile { - const INDEX: u64 = 2051; - const ADDRESS_SS58: [u8; 32] = [ - 0x3a, 0x86, 0x18, 0xfb, 0xbb, 0x1b, 0xbc, 0x47, 0x86, 0x64, 0xff, 0x53, 0x46, 0x18, 0x0c, - 0x35, 0xd0, 0x9f, 0xac, 0x26, 0xf2, 0x02, 0x70, 0x85, 0xb3, 0x1c, 0x56, 0xc1, 0x06, 0x3c, - 0x1c, 0xd3, - ]; -} - -#[precompile_utils::precompile] -impl SubnetPrecompile { - #[precompile::public("registerNetwork(bytes32)")] - #[precompile::payable] - fn register_network(handle: &mut impl PrecompileHandle, hotkey: H256) -> EvmResult<()> { - let (hotkey, _) = parse_pubkey(hotkey.as_bytes())?; - let call = pallet_subtensor::Call::::register_network_with_identity { - hotkey, - identity: None, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public( - "registerNetwork(bytes32,string,string,string,string,string,string,string)" - )] - #[precompile::payable] - #[allow(clippy::too_many_arguments)] - fn register_network_with_identity( - handle: &mut impl PrecompileHandle, - hotkey: H256, - subnet_name: BoundedString>, - github_repo: BoundedString>, - subnet_contact: BoundedString>, - subnet_url: BoundedString>, - discord: BoundedString>, - description: BoundedString>, - additional: BoundedString>, - ) -> EvmResult<()> { - let (hotkey, _) = parse_pubkey(hotkey.as_bytes())?; - let identity = pallet_subtensor::SubnetIdentityOfV2 { - subnet_name: subnet_name.into(), - github_repo: github_repo.into(), - subnet_contact: subnet_contact.into(), - subnet_url: subnet_url.into(), - discord: discord.into(), - description: description.into(), - additional: additional.into(), - }; - - let call = pallet_subtensor::Call::::register_network_with_identity { - hotkey, - identity: Some(identity), - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getServingRateLimit(uint16)")] - #[precompile::view] - fn get_serving_rate_limit(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::ServingRateLimit::::get(netuid)) - } - - #[precompile::public("setServingRateLimit(uint16,uint64)")] - #[precompile::payable] - fn set_serving_rate_limit( - handle: &mut impl PrecompileHandle, - netuid: u16, - serving_rate_limit: u64, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_serving_rate_limit { - netuid, - serving_rate_limit, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getMinDifficulty(uint16)")] - #[precompile::view] - fn get_min_difficulty(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::MinDifficulty::::get(netuid)) - } - - #[precompile::public("setMinDifficulty(uint16,uint64)")] - #[precompile::payable] - fn set_min_difficulty( - handle: &mut impl PrecompileHandle, - netuid: u16, - min_difficulty: u64, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_min_difficulty { - netuid, - min_difficulty, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getMaxDifficulty(uint16)")] - #[precompile::view] - fn get_max_difficulty(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::MaxDifficulty::::get(netuid)) - } - - #[precompile::public("setMaxDifficulty(uint16,uint64)")] - #[precompile::payable] - fn set_max_difficulty( - handle: &mut impl PrecompileHandle, - netuid: u16, - max_difficulty: u64, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_max_difficulty { - netuid, - max_difficulty, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getWeightsVersionKey(uint16)")] - #[precompile::view] - fn get_weights_version_key(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::WeightsVersionKey::::get(netuid)) - } - - #[precompile::public("setWeightsVersionKey(uint16,uint64)")] - #[precompile::payable] - fn set_weights_version_key( - handle: &mut impl PrecompileHandle, - netuid: u16, - weights_version_key: u64, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_weights_version_key { - netuid, - weights_version_key, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getWeightsSetRateLimit(uint16)")] - #[precompile::view] - fn get_weights_set_rate_limit(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::WeightsSetRateLimit::::get( - netuid, - )) - } - - #[precompile::public("setWeightsSetRateLimit(uint16,uint64)")] - #[precompile::payable] - fn set_weights_set_rate_limit( - handle: &mut impl PrecompileHandle, - netuid: u16, - weights_set_rate_limit: u64, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_weights_set_rate_limit { - netuid, - weights_set_rate_limit, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getAdjustmentAlpha(uint16)")] - #[precompile::view] - fn get_adjustment_alpha(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::AdjustmentAlpha::::get(netuid)) - } - - #[precompile::public("setAdjustmentAlpha(uint16,uint64)")] - #[precompile::payable] - fn set_adjustment_alpha( - handle: &mut impl PrecompileHandle, - netuid: u16, - adjustment_alpha: u64, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_adjustment_alpha { - netuid, - adjustment_alpha, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getMaxWeightLimit(uint16)")] - #[precompile::view] - fn get_max_weight_limit(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::MaxWeightsLimit::::get(netuid)) - } - - #[precompile::public("setMaxWeightLimit(uint16,uint16)")] - #[precompile::payable] - fn set_max_weight_limit( - handle: &mut impl PrecompileHandle, - netuid: u16, - max_weight_limit: u16, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_max_weight_limit { - netuid, - max_weight_limit, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getImmunityPeriod(uint16)")] - #[precompile::view] - fn get_immunity_period(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::ImmunityPeriod::::get(netuid)) - } - - #[precompile::public("setImmunityPeriod(uint16,uint16)")] - #[precompile::payable] - fn set_immunity_period( - handle: &mut impl PrecompileHandle, - netuid: u16, - immunity_period: u16, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_immunity_period { - netuid, - immunity_period, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getMinAllowedWeights(uint16)")] - #[precompile::view] - fn get_min_allowed_weights(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::MinAllowedWeights::::get(netuid)) - } - - #[precompile::public("setMinAllowedWeights(uint16,uint16)")] - #[precompile::payable] - fn set_min_allowed_weights( - handle: &mut impl PrecompileHandle, - netuid: u16, - min_allowed_weights: u16, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_min_allowed_weights { - netuid, - min_allowed_weights, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getKappa(uint16)")] - #[precompile::view] - fn get_kappa(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::Kappa::::get(netuid)) - } - - #[precompile::public("setKappa(uint16,uint16)")] - #[precompile::payable] - fn set_kappa(handle: &mut impl PrecompileHandle, netuid: u16, kappa: u16) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_kappa { netuid, kappa }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getRho(uint16)")] - #[precompile::view] - fn get_rho(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::Rho::::get(netuid)) - } - - #[precompile::public("setRho(uint16,uint16)")] - #[precompile::payable] - fn set_rho(handle: &mut impl PrecompileHandle, netuid: u16, rho: u16) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_rho { netuid, rho }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getActivityCutoff(uint16)")] - #[precompile::view] - fn get_activity_cutoff(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::ActivityCutoff::::get(netuid)) - } - - #[precompile::public("setActivityCutoff(uint16,uint16)")] - #[precompile::payable] - fn set_activity_cutoff( - handle: &mut impl PrecompileHandle, - netuid: u16, - activity_cutoff: u16, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_activity_cutoff { - netuid, - activity_cutoff, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getNetworkRegistrationAllowed(uint16)")] - #[precompile::view] - fn get_network_registration_allowed( - _: &mut impl PrecompileHandle, - netuid: u16, - ) -> EvmResult { - Ok(pallet_subtensor::NetworkRegistrationAllowed::::get(netuid)) - } - - #[precompile::public("setNetworkRegistrationAllowed(uint16,bool)")] - #[precompile::payable] - fn set_network_registration_allowed( - handle: &mut impl PrecompileHandle, - netuid: u16, - registration_allowed: bool, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_network_registration_allowed { - netuid, - registration_allowed, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getNetworkPowRegistrationAllowed(uint16)")] - #[precompile::view] - fn get_network_pow_registration_allowed( - _: &mut impl PrecompileHandle, - netuid: u16, - ) -> EvmResult { - Ok(pallet_subtensor::NetworkPowRegistrationAllowed::::get(netuid)) - } - - #[precompile::public("setNetworkPowRegistrationAllowed(uint16,bool)")] - #[precompile::payable] - fn set_network_pow_registration_allowed( - handle: &mut impl PrecompileHandle, - netuid: u16, - registration_allowed: bool, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_network_pow_registration_allowed { - netuid, - registration_allowed, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getMinBurn(uint16)")] - #[precompile::view] - fn get_min_burn(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::MinBurn::::get(netuid)) - } - - #[precompile::public("setMinBurn(uint16,uint64)")] - #[precompile::payable] - fn set_min_burn( - handle: &mut impl PrecompileHandle, - netuid: u16, - min_burn: u64, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_min_burn { netuid, min_burn }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getMaxBurn(uint16)")] - #[precompile::view] - fn get_max_burn(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::MaxBurn::::get(netuid)) - } - - #[precompile::public("setMaxBurn(uint16,uint64)")] - #[precompile::payable] - fn set_max_burn( - handle: &mut impl PrecompileHandle, - netuid: u16, - max_burn: u64, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_max_burn { netuid, max_burn }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getDifficulty(uint16)")] - #[precompile::view] - fn get_difficulty(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::Difficulty::::get(netuid)) - } - - #[precompile::public("setDifficulty(uint16,uint64)")] - #[precompile::payable] - fn set_difficulty( - handle: &mut impl PrecompileHandle, - netuid: u16, - difficulty: u64, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_difficulty { netuid, difficulty }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getBondsMovingAverage(uint16)")] - #[precompile::view] - fn get_bonds_moving_average(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::BondsMovingAverage::::get(netuid)) - } - - #[precompile::public("setBondsMovingAverage(uint16,uint64)")] - #[precompile::payable] - fn set_bonds_moving_average( - handle: &mut impl PrecompileHandle, - netuid: u16, - bonds_moving_average: u64, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_bonds_moving_average { - netuid, - bonds_moving_average, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getCommitRevealWeightsEnabled(uint16)")] - #[precompile::view] - fn get_commit_reveal_weights_enabled( - _: &mut impl PrecompileHandle, - netuid: u16, - ) -> EvmResult { - Ok(pallet_subtensor::CommitRevealWeightsEnabled::::get(netuid)) - } - - #[precompile::public("setCommitRevealWeightsEnabled(uint16,bool)")] - #[precompile::payable] - fn set_commit_reveal_weights_enabled( - handle: &mut impl PrecompileHandle, - netuid: u16, - enabled: bool, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_commit_reveal_weights_enabled { - netuid, - enabled, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getLiquidAlphaEnabled(uint16)")] - #[precompile::view] - fn get_liquid_alpha_enabled(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::LiquidAlphaOn::::get(netuid)) - } - - #[precompile::public("setLiquidAlphaEnabled(uint16,bool)")] - #[precompile::payable] - fn set_liquid_alpha_enabled( - handle: &mut impl PrecompileHandle, - netuid: u16, - enabled: bool, - ) -> EvmResult<()> { - let call = - pallet_admin_utils::Call::::sudo_set_liquid_alpha_enabled { netuid, enabled }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getAlphaValues(uint16)")] - #[precompile::view] - fn get_alpha_values(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult<(u16, u16)> { - Ok(pallet_subtensor::AlphaValues::::get(netuid)) - } - - #[precompile::public("setAlphaValues(uint16,uint16,uint16)")] - #[precompile::payable] - fn set_alpha_values( - handle: &mut impl PrecompileHandle, - netuid: u16, - alpha_low: u16, - alpha_high: u16, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_alpha_values { - netuid, - alpha_low, - alpha_high, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } - - #[precompile::public("getCommitRevealWeightsInterval(uint16)")] - #[precompile::view] - fn get_commit_reveal_weights_interval( - _: &mut impl PrecompileHandle, - netuid: u16, - ) -> EvmResult { - Ok(pallet_subtensor::RevealPeriodEpochs::::get(netuid)) - } - - #[precompile::public("setCommitRevealWeightsInterval(uint16,uint64)")] - #[precompile::payable] - fn set_commit_reveal_weights_interval( - handle: &mut impl PrecompileHandle, - netuid: u16, - interval: u64, - ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_commit_reveal_weights_interval { - netuid, - interval, - }; - - handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) - } -} diff --git a/runtime/tests/pallet_proxy.rs b/runtime/tests/pallet_proxy.rs index 7d0dec9679..563c274bb9 100644 --- a/runtime/tests/pallet_proxy.rs +++ b/runtime/tests/pallet_proxy.rs @@ -3,9 +3,10 @@ use codec::Encode; use frame_support::{BoundedVec, assert_ok, traits::InstanceFilter}; use node_subtensor_runtime::{ - AccountId, BalancesCall, BuildStorage, Proxy, ProxyType, Runtime, RuntimeCall, RuntimeEvent, - RuntimeGenesisConfig, RuntimeOrigin, SubtensorModule, System, SystemCall, + BalancesCall, BuildStorage, Proxy, Runtime, RuntimeCall, RuntimeEvent, RuntimeGenesisConfig, + RuntimeOrigin, SubtensorModule, System, SystemCall, }; +use subtensor_runtime_common::{AccountId, ProxyType}; const ACCOUNT: [u8; 32] = [1_u8; 32]; const DELEGATE: [u8; 32] = [2_u8; 32]; From f0f625fa260d0614f7577cdb871b76e0d0762d8b Mon Sep 17 00:00:00 2001 From: Aliaksandr Tsurko Date: Mon, 3 Mar 2025 18:20:55 +0100 Subject: [PATCH 4/7] Reformat --- runtime/src/lib.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 3b22442d96..726bbf7754 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -11,7 +11,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod check_nonce; mod migrations; -use codec::{Compact, Decode, Encode, MaxEncodedLen}; +use codec::{Compact, Decode, Encode}; use frame_support::traits::Imbalance; use frame_support::{ dispatch::DispatchResultWithPostInfo, @@ -48,10 +48,11 @@ use sp_core::{ }; use sp_runtime::generic::Era; use sp_runtime::{ - AccountId32, ApplyExtrinsicResult, ConsensusEngineId, create_runtime_str, - generic, impl_opaque_keys, + AccountId32, ApplyExtrinsicResult, ConsensusEngineId, create_runtime_str, generic, + impl_opaque_keys, traits::{ - AccountIdLookup, BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, NumberFor, One, PostDispatchInfoOf, UniqueSaturatedInto, Verify, + AccountIdLookup, BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, NumberFor, + One, PostDispatchInfoOf, UniqueSaturatedInto, Verify, }, transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError}, }; From 741c09f085795b6aa81baa739256236555248999 Mon Sep 17 00:00:00 2001 From: Aliaksandr Tsurko Date: Mon, 3 Mar 2025 18:30:38 +0100 Subject: [PATCH 5/7] Clean up precompiles crate --- precompiles/src/balance_transfer.rs | 3 +- precompiles/src/ed25519.rs | 3 +- precompiles/src/lib.rs | 44 +------------------------ precompiles/src/neuron.rs | 3 +- precompiles/src/parser.rs | 50 +++++++++++++++++++++++++++++ precompiles/src/staking.rs | 3 +- precompiles/src/subnet.rs | 3 +- 7 files changed, 61 insertions(+), 48 deletions(-) create mode 100644 precompiles/src/parser.rs diff --git a/precompiles/src/balance_transfer.rs b/precompiles/src/balance_transfer.rs index 2f2103e9d0..6cf76a1110 100644 --- a/precompiles/src/balance_transfer.rs +++ b/precompiles/src/balance_transfer.rs @@ -6,7 +6,8 @@ use precompile_utils::EvmResult; use sp_core::{H256, U256}; use sp_runtime::traits::{Dispatchable, StaticLookup, UniqueSaturatedInto}; -use crate::{PrecompileExt, PrecompileHandleExt, contract_to_origin, parse_pubkey}; +use crate::parser::{contract_to_origin, parse_pubkey}; +use crate::{PrecompileExt, PrecompileHandleExt}; pub(crate) struct BalanceTransferPrecompile(PhantomData); diff --git a/precompiles/src/ed25519.rs b/precompiles/src/ed25519.rs index 236da80a27..e3791e2485 100644 --- a/precompiles/src/ed25519.rs +++ b/precompiles/src/ed25519.rs @@ -5,7 +5,8 @@ use alloc::vec::Vec; use ed25519_dalek::{Signature, Verifier, VerifyingKey}; use fp_evm::{ExitError, ExitSucceed, LinearCostPrecompile, PrecompileFailure}; -use crate::{PrecompileExt, parse_slice}; +use crate::PrecompileExt; +use crate::parser::parse_slice; pub(crate) struct Ed25519Verify; diff --git a/precompiles/src/lib.rs b/precompiles/src/lib.rs index 51963ca099..499b3a5f0d 100644 --- a/precompiles/src/lib.rs +++ b/precompiles/src/lib.rs @@ -21,7 +21,6 @@ use sp_runtime::traits::StaticLookup; use subtensor_runtime_common::ProxyType; use pallet_admin_utils::{PrecompileEnable, PrecompileEnum}; -use sp_std::vec; use crate::balance_transfer::*; use crate::ed25519::*; @@ -34,6 +33,7 @@ mod balance_transfer; mod ed25519; mod metagraph; mod neuron; +mod parser; mod staking; mod subnet; @@ -202,48 +202,6 @@ fn hash(a: u64) -> H160 { H160::from_low_u64_be(a) } -/// Takes a slice from bytes with PrecompileFailure as Error -fn parse_slice(data: &[u8], from: usize, to: usize) -> Result<&[u8], PrecompileFailure> { - let maybe_slice = data.get(from..to); - if let Some(slice) = maybe_slice { - Ok(slice) - } else { - log::error!( - "fail to get slice from data, {:?}, from {}, to {}", - &data, - from, - to - ); - Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }) - } -} - -fn parse_pubkey>(data: &[u8]) -> Result<(A, vec::Vec), PrecompileFailure> { - let mut pubkey = [0u8; 32]; - pubkey.copy_from_slice(parse_slice(data, 0, 32)?); - - Ok(( - pubkey.into(), - data.get(32..) - .map_or_else(vec::Vec::new, |slice| slice.to_vec()), - )) -} - -fn contract_to_origin>( - contract: &[u8; 32], -) -> Result, PrecompileFailure> { - let (account_id, _) = parse_pubkey::(contract)?; - Ok(RawOrigin::Signed(account_id)) -} - -fn try_u16_from_u256(value: U256) -> Result { - value.try_into().map_err(|_| PrecompileFailure::Error { - exit_status: ExitError::Other("the value is outside of u16 bounds".into()), - }) -} - trait PrecompileHandleExt: PrecompileHandle { fn caller_account_id(&self) -> R::AccountId where diff --git a/precompiles/src/neuron.rs b/precompiles/src/neuron.rs index e4c1895543..9091aa8694 100644 --- a/precompiles/src/neuron.rs +++ b/precompiles/src/neuron.rs @@ -8,7 +8,8 @@ use sp_core::H256; use sp_runtime::traits::Dispatchable; use sp_std::vec::Vec; -use crate::{PrecompileExt, PrecompileHandleExt, parse_pubkey}; +use crate::parser::parse_pubkey; +use crate::{PrecompileExt, PrecompileHandleExt}; pub struct NeuronPrecompile(PhantomData); diff --git a/precompiles/src/parser.rs b/precompiles/src/parser.rs new file mode 100644 index 0000000000..8abc96fbbe --- /dev/null +++ b/precompiles/src/parser.rs @@ -0,0 +1,50 @@ +extern crate alloc; + +use frame_system::RawOrigin; +use pallet_evm::{ExitError, PrecompileFailure}; +use sp_core::U256; +use sp_std::vec; + +/// Takes a slice from bytes with PrecompileFailure as Error +pub(crate) fn parse_slice(data: &[u8], from: usize, to: usize) -> Result<&[u8], PrecompileFailure> { + let maybe_slice = data.get(from..to); + if let Some(slice) = maybe_slice { + Ok(slice) + } else { + log::error!( + "fail to get slice from data, {:?}, from {}, to {}", + &data, + from, + to + ); + Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }) + } +} + +pub(crate) fn parse_pubkey>( + data: &[u8], +) -> Result<(A, vec::Vec), PrecompileFailure> { + let mut pubkey = [0u8; 32]; + pubkey.copy_from_slice(parse_slice(data, 0, 32)?); + + Ok(( + pubkey.into(), + data.get(32..) + .map_or_else(vec::Vec::new, |slice| slice.to_vec()), + )) +} + +pub(crate) fn contract_to_origin>( + contract: &[u8; 32], +) -> Result, PrecompileFailure> { + let (account_id, _) = parse_pubkey::(contract)?; + Ok(RawOrigin::Signed(account_id)) +} + +pub(crate) fn try_u16_from_u256(value: U256) -> Result { + value.try_into().map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::Other("the value is outside of u16 bounds".into()), + }) +} diff --git a/precompiles/src/staking.rs b/precompiles/src/staking.rs index 6e7a1100bc..c41e6bb4c6 100644 --- a/precompiles/src/staking.rs +++ b/precompiles/src/staking.rs @@ -37,7 +37,8 @@ use sp_core::{H256, U256}; use sp_runtime::traits::{Dispatchable, StaticLookup, UniqueSaturatedInto}; use subtensor_runtime_common::ProxyType; -use crate::{PrecompileExt, PrecompileHandleExt, parse_pubkey, try_u16_from_u256}; +use crate::parser::{parse_pubkey, try_u16_from_u256}; +use crate::{PrecompileExt, PrecompileHandleExt}; pub(crate) struct StakingPrecompile(PhantomData); diff --git a/precompiles/src/subnet.rs b/precompiles/src/subnet.rs index 82cec11626..1a6bfcf058 100644 --- a/precompiles/src/subnet.rs +++ b/precompiles/src/subnet.rs @@ -8,7 +8,8 @@ use precompile_utils::{EvmResult, prelude::BoundedString}; use sp_core::H256; use sp_runtime::traits::Dispatchable; -use crate::{PrecompileExt, PrecompileHandleExt, parse_pubkey}; +use crate::parser::parse_pubkey; +use crate::{PrecompileExt, PrecompileHandleExt}; pub struct SubnetPrecompile(PhantomData); From d9cb94f9258391049663f8096c43094ffcd6853a Mon Sep 17 00:00:00 2001 From: Aliaksandr Tsurko Date: Mon, 3 Mar 2025 19:16:30 +0100 Subject: [PATCH 6/7] Reformat --- precompiles/src/staking.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/precompiles/src/staking.rs b/precompiles/src/staking.rs index fb35c89fcd..e9bebcf67c 100644 --- a/precompiles/src/staking.rs +++ b/precompiles/src/staking.rs @@ -135,13 +135,11 @@ where let (coldkey, _) = parse_pubkey(coldkey_h256.as_bytes())?; // get total stake of coldkey - let total_stake = - pallet_subtensor::Pallet::::get_total_stake_for_coldkey(&coldkey); + let total_stake = pallet_subtensor::Pallet::::get_total_stake_for_coldkey(&coldkey); // Convert to EVM decimals let stake_u256 = U256::from(total_stake); - let stake_eth = - ::BalanceConverter::into_evm_balance(stake_u256) - .ok_or(ExitError::InvalidRange)?; + let stake_eth = ::BalanceConverter::into_evm_balance(stake_u256) + .ok_or(ExitError::InvalidRange)?; Ok(stake_eth) } @@ -157,9 +155,8 @@ where let total_stake = pallet_subtensor::Pallet::::get_total_stake_for_hotkey(&hotkey); // Convert to EVM decimals let stake_u256 = U256::from(total_stake); - let stake_eth = - ::BalanceConverter::into_evm_balance(stake_u256) - .ok_or(ExitError::InvalidRange)?; + let stake_eth = ::BalanceConverter::into_evm_balance(stake_u256) + .ok_or(ExitError::InvalidRange)?; Ok(stake_eth) } From 42059ae53461d484d27be29092e44f0af5dd5341 Mon Sep 17 00:00:00 2001 From: Aliaksandr Tsurko Date: Mon, 3 Mar 2025 19:27:03 +0100 Subject: [PATCH 7/7] Enable std for node dependencies --- node/Cargo.toml | 8 ++++---- runtime/Cargo.toml | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/node/Cargo.toml b/node/Cargo.toml index 44a7bd0cc7..6cea8f6950 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -105,10 +105,10 @@ thiserror = { workspace = true } num-traits = { version = "0.2", features = ["std"] } # Local Dependencies -node-subtensor-runtime = { workspace = true } -subtensor-runtime-common = { workspace = true } -subtensor-custom-rpc = { workspace = true } -subtensor-custom-rpc-runtime-api = { workspace = true } +node-subtensor-runtime = { workspace = true, features = ["std"] } +subtensor-runtime-common = { workspace = true, features = ["std"] } +subtensor-custom-rpc = { workspace = true, features = ["std"] } +subtensor-custom-rpc-runtime-api = { workspace = true, features = ["std"] } [build-dependencies] substrate-build-script-utils = { workspace = true } diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 0ce6848406..67add266a4 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -189,6 +189,7 @@ std = [ "log/std", "sp-storage/std", "sp-genesis-builder/std", + "subtensor-precompiles/std", "subtensor-runtime-common/std", # Frontier "fp-evm/std",