diff --git a/.github/workflows/cargo-audit.yml b/.github/workflows/cargo-audit.yml new file mode 100644 index 000000000..3197150b1 --- /dev/null +++ b/.github/workflows/cargo-audit.yml @@ -0,0 +1,42 @@ +name: cargo audit +on: + pull_request: + types: + - labeled + - unlabeled + - synchronize +concurrency: + group: cargo-audit-${{ github.ref }} + cancel-in-progress: true + +jobs: + cargo-audit: + name: cargo audit + runs-on: SubtensorCI + if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-cargo-audit') }} + steps: + - name: Check-out repositoroy under $GITHUB_WORKSPACE + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update && + sudo apt-get install -y clang curl libssl-dev llvm libudev-dev protobuf-compiler + + - name: Install Rust Stable + uses: actions-rs/toolchain@v1.0.6 + with: + toolchain: stable + components: rustfmt, clippy + profile: minimal + + - name: Utilize Shared Rust Cache + uses: Swatinem/rust-cache@v2.2.1 + with: + key: ubuntu-latest-${{ env.RUST_BIN_DIR }} + + - name: Install cargo-audit + run: cargo install --version 0.20.1 cargo-audit + + - name: cargo audit + run: cargo audit --ignore RUSTSEC-2024-0336 # rustls issue; wait for upstream to resolve this diff --git a/.github/workflows/check-devnet.yml b/.github/workflows/check-devnet.yml index 2cb586348..8f04d78cf 100644 --- a/.github/workflows/check-devnet.yml +++ b/.github/workflows/check-devnet.yml @@ -39,18 +39,3 @@ jobs: echo "network spec_version: $spec_version" if (( $(echo "$local_spec_version <= $spec_version" | bc -l) )); then echo "$local_spec_version ≯ $spec_version ❌"; exit 1; fi echo "$local_spec_version > $spec_version ✅" - - check-devnet-migrations: - name: check devnet migrations - runs-on: ubuntu-22.04 - steps: - - name: Checkout sources - uses: actions/checkout@v3 - - - name: Run Try Runtime Checks - uses: "paritytech/try-runtime-gha@v0.1.0" - with: - runtime-package: "node-subtensor-runtime" - node-uri: "wss://dev.chain.opentensor.ai:443" - checks: "pre-and-post" - extra-args: "--disable-spec-version-check --no-weight-warnings" diff --git a/.github/workflows/check-finney.yml b/.github/workflows/check-finney.yml index 665c9c8a9..947b9a902 100644 --- a/.github/workflows/check-finney.yml +++ b/.github/workflows/check-finney.yml @@ -39,17 +39,3 @@ jobs: echo "network spec_version: $spec_version" if (( $(echo "$local_spec_version <= $spec_version" | bc -l) )); then echo "$local_spec_version ≯ $spec_version ❌"; exit 1; fi echo "$local_spec_version > $spec_version ✅" - - check-finney-migrations: - name: check finney migrations - runs-on: SubtensorCI - steps: - - name: Checkout sources - uses: actions/checkout@v4 - - name: Run Try Runtime Checks - uses: "paritytech/try-runtime-gha@v0.1.0" - with: - runtime-package: "node-subtensor-runtime" - node-uri: "wss://entrypoint-finney.opentensor.ai:443" - checks: "pre-and-post" - extra-args: "--disable-spec-version-check --no-weight-warnings" diff --git a/.github/workflows/check-rust.yml b/.github/workflows/check-rust.yml index e42e369cf..80d543163 100644 --- a/.github/workflows/check-rust.yml +++ b/.github/workflows/check-rust.yml @@ -208,46 +208,6 @@ jobs: - name: cargo clippy --workspace --all-targets --all-features -- -D warnings run: cargo clippy --workspace --all-targets --all-features -- -D warnings - # runs cargo audit - cargo-audit: - name: cargo audit - runs-on: SubtensorCI - strategy: - matrix: - rust-branch: - - stable - rust-target: - - x86_64-unknown-linux-gnu - # - x86_64-apple-darwin - os: - - ubuntu-latest - # - macos-latest - steps: - - name: Check-out repositoroy under $GITHUB_WORKSPACE - uses: actions/checkout@v4 - - - name: Install dependencies - run: | - sudo apt-get update && - sudo apt-get install -y clang curl libssl-dev llvm libudev-dev protobuf-compiler - - - name: Install Rust ${{ matrix.rust-branch }} - uses: actions-rs/toolchain@v1.0.6 - with: - toolchain: ${{ matrix.rust-branch }} - components: rustfmt, clippy - profile: minimal - - - name: Utilize Shared Rust Cache - uses: Swatinem/rust-cache@v2.2.1 - with: - key: ${{ matrix.os }}-${{ env.RUST_BIN_DIR }} - - - name: Install cargo-audit - run: cargo install cargo-audit - - - name: cargo audit - run: cargo audit --ignore RUSTSEC-2024-0336 # rustls issue; wait for upstream to resolve this # runs cargo test --workspace cargo-test: diff --git a/.github/workflows/check-testnet.yml b/.github/workflows/check-testnet.yml index 95277c94a..a869129ab 100644 --- a/.github/workflows/check-testnet.yml +++ b/.github/workflows/check-testnet.yml @@ -39,18 +39,3 @@ jobs: echo "network spec_version: $spec_version" if (( $(echo "$local_spec_version <= $spec_version" | bc -l) )); then echo "$local_spec_version ≯ $spec_version ❌"; exit 1; fi echo "$local_spec_version > $spec_version ✅" - - check-testnet-migrations: - name: check testnet migrations - runs-on: ubuntu-22.04 - steps: - - name: Checkout sources - uses: actions/checkout@v3 - - - name: Run Try Runtime Checks - uses: "paritytech/try-runtime-gha@v0.1.0" - with: - runtime-package: "node-subtensor-runtime" - node-uri: "wss://test.chain.opentensor.ai:443" - checks: "pre-and-post" - extra-args: "--disable-spec-version-check --no-weight-warnings" diff --git a/.github/workflows/try-runtime.yml b/.github/workflows/try-runtime.yml new file mode 100644 index 000000000..174e6db37 --- /dev/null +++ b/.github/workflows/try-runtime.yml @@ -0,0 +1,54 @@ +name: Try Runtime + +on: + pull_request: + branches: [main, devnet-ready, devnet, testnet, finney] + types: [labeled, unlabeled, synchronize] + +env: + CARGO_TERM_COLOR: always + +jobs: + check-devnet: + name: check devnet + runs-on: SubtensorCI + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Run Try Runtime Checks + uses: "paritytech/try-runtime-gha@v0.1.0" + with: + runtime-package: "node-subtensor-runtime" + node-uri: "wss://dev.chain.opentensor.ai:443" + checks: "all" + extra-args: "--disable-spec-version-check --no-weight-warnings" + + check-testnet: + name: check testnet + runs-on: SubtensorCI + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Run Try Runtime Checks + uses: "paritytech/try-runtime-gha@v0.1.0" + with: + runtime-package: "node-subtensor-runtime" + node-uri: "wss://test.chain.opentensor.ai:443" + checks: "all" + extra-args: "--disable-spec-version-check --no-weight-warnings" + + check-finney: + name: check finney + runs-on: SubtensorCI + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Run Try Runtime Checks + uses: "paritytech/try-runtime-gha@v0.1.0" + with: + runtime-package: "node-subtensor-runtime" + node-uri: "wss://archive.chain.opentensor.ai:443" + checks: "all" + extra-args: "--disable-spec-version-check --no-weight-warnings" diff --git a/Cargo.lock b/Cargo.lock index cd645616b..2f328dfd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -214,18 +214,6 @@ dependencies = [ "ark-std", ] -[[package]] -name = "ark-bls12-377-ext" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c7021f180a0cbea0380eba97c2af3c57074cdaffe0eef7e840e1c9f2841e55" -dependencies = [ - "ark-bls12-377", - "ark-ec", - "ark-models-ext", - "ark-std", -] - [[package]] name = "ark-bls12-381" version = "0.4.0" @@ -238,45 +226,6 @@ dependencies = [ "ark-std", ] -[[package]] -name = "ark-bls12-381-ext" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1dc4b3d08f19e8ec06e949712f95b8361e43f1391d94f65e4234df03480631c" -dependencies = [ - "ark-bls12-381", - "ark-ec", - "ark-ff", - "ark-models-ext", - "ark-serialize", - "ark-std", -] - -[[package]] -name = "ark-bw6-761" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e0605daf0cc5aa2034b78d008aaf159f56901d92a52ee4f6ecdfdac4f426700" -dependencies = [ - "ark-bls12-377", - "ark-ec", - "ark-ff", - "ark-std", -] - -[[package]] -name = "ark-bw6-761-ext" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccee5fba47266f460067588ee1bf070a9c760bf2050c1c509982c5719aadb4f2" -dependencies = [ - "ark-bw6-761", - "ark-ec", - "ark-ff", - "ark-models-ext", - "ark-std", -] - [[package]] name = "ark-ec" version = "0.4.2" @@ -291,60 +240,9 @@ dependencies = [ "hashbrown 0.13.2", "itertools 0.10.5", "num-traits", - "rayon", "zeroize", ] -[[package]] -name = "ark-ed-on-bls12-377" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b10d901b9ac4b38f9c32beacedfadcdd64e46f8d7f8e88c1ae1060022cf6f6c6" -dependencies = [ - "ark-bls12-377", - "ark-ec", - "ark-ff", - "ark-std", -] - -[[package]] -name = "ark-ed-on-bls12-377-ext" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524a4fb7540df2e1a8c2e67a83ba1d1e6c3947f4f9342cc2359fc2e789ad731d" -dependencies = [ - "ark-ec", - "ark-ed-on-bls12-377", - "ark-ff", - "ark-models-ext", - "ark-std", -] - -[[package]] -name = "ark-ed-on-bls12-381-bandersnatch" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9cde0f2aa063a2a5c28d39b47761aa102bda7c13c84fc118a61b87c7b2f785c" -dependencies = [ - "ark-bls12-381", - "ark-ec", - "ark-ff", - "ark-std", -] - -[[package]] -name = "ark-ed-on-bls12-381-bandersnatch-ext" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15185f1acb49a07ff8cbe5f11a1adc5a93b19e211e325d826ae98e98e124346" -dependencies = [ - "ark-ec", - "ark-ed-on-bls12-381-bandersnatch", - "ark-ff", - "ark-models-ext", - "ark-std", -] - [[package]] name = "ark-ff" version = "0.4.2" @@ -388,19 +286,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "ark-models-ext" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e9eab5d4b5ff2f228b763d38442adc9b084b0a465409b059fac5c2308835ec2" -dependencies = [ - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", - "derivative", -] - [[package]] name = "ark-poly" version = "0.4.2" @@ -414,35 +299,6 @@ dependencies = [ "hashbrown 0.13.2", ] -[[package]] -name = "ark-scale" -version = "0.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f69c00b3b529be29528a6f2fd5fa7b1790f8bed81b9cdca17e326538545a179" -dependencies = [ - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", - "parity-scale-codec", - "scale-info", -] - -[[package]] -name = "ark-secret-scalar" -version = "0.0.2" -source = "git+https://github.com/w3f/ring-vrf?rev=0fef826#0fef8266d851932ad25d6b41bc4b34d834d1e11d" -dependencies = [ - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", - "ark-transcript", - "digest 0.10.7", - "getrandom_or_panic", - "zeroize", -] - [[package]] name = "ark-serialize" version = "0.4.2" @@ -474,20 +330,6 @@ checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", "rand", - "rayon", -] - -[[package]] -name = "ark-transcript" -version = "0.0.2" -source = "git+https://github.com/w3f/ring-vrf?rev=0fef826#0fef8266d851932ad25d6b41bc4b34d834d1e11d" -dependencies = [ - "ark-ff", - "ark-serialize", - "ark-std", - "digest 0.10.7", - "rand_core", - "sha3", ] [[package]] @@ -586,6 +428,12 @@ dependencies = [ "syn 2.0.79", ] +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + [[package]] name = "async-channel" version = "1.9.0" @@ -651,6 +499,15 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -668,6 +525,17 @@ dependencies = [ "url", ] +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "autocfg" version = "1.4.0" @@ -689,27 +557,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "bandersnatch_vrfs" -version = "0.0.4" -source = "git+https://github.com/w3f/ring-vrf?rev=0fef826#0fef8266d851932ad25d6b41bc4b34d834d1e11d" -dependencies = [ - "ark-bls12-381", - "ark-ec", - "ark-ed-on-bls12-381-bandersnatch", - "ark-ff", - "ark-serialize", - "ark-std", - "dleq_vrf", - "rand_chacha", - "rand_core", - "ring 0.1.0", - "sha2 0.10.8", - "sp-ark-bls12-381", - "sp-ark-ed-on-bls12-381-bandersnatch", - "zeroize", -] - [[package]] name = "base-x" version = "0.2.11" @@ -1240,22 +1087,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "common" -version = "0.1.0" -source = "git+https://github.com/w3f/ring-proof?rev=665f5f5#665f5f51af5734c7b6d90b985dd6861d4c5b4752" -dependencies = [ - "ark-ec", - "ark-ff", - "ark-poly", - "ark-serialize", - "ark-std", - "fflonk", - "getrandom_or_panic", - "merlin", - "rand_chacha", -] - [[package]] name = "common-path" version = "1.0.0" @@ -1512,6 +1343,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.20" @@ -1893,22 +1733,6 @@ dependencies = [ "syn 2.0.79", ] -[[package]] -name = "dleq_vrf" -version = "0.0.2" -source = "git+https://github.com/w3f/ring-vrf?rev=0fef826#0fef8266d851932ad25d6b41bc4b34d834d1e11d" -dependencies = [ - "ark-ec", - "ark-ff", - "ark-scale", - "ark-secret-scalar", - "ark-serialize", - "ark-std", - "ark-transcript", - "arrayvec", - "zeroize", -] - [[package]] name = "docify" version = "0.2.8" @@ -1936,6 +1760,12 @@ dependencies = [ "walkdir", ] +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + [[package]] name = "downcast" version = "0.11.0" @@ -2035,6 +1865,9 @@ name = "either" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +dependencies = [ + "serde", +] [[package]] name = "elliptic-curve" @@ -2149,11 +1982,31 @@ checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" dependencies = [ "crunchy", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", + "scale-info", "tiny-keccak", ] +[[package]] +name = "ethereum" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e04d24d20b8ff2235cffbf242d5092de3aa45f77c5270ddbfadd2778ca13fea" +dependencies = [ + "bytes", + "ethereum-types", + "hash-db", + "hash256-std-hasher", + "parity-scale-codec", + "rlp", + "scale-info", + "serde", + "sha3", + "trie-root", +] + [[package]] name = "ethereum-types" version = "0.14.1" @@ -2162,9 +2015,11 @@ checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" dependencies = [ "ethbloom", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", "primitive-types", + "scale-info", "uint", ] @@ -2195,6 +2050,64 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "evm" +version = "0.41.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "767f43e9630cc36cf8ff2777cbb0121b055f0d1fd6eaaa13b46a1808f0d0e7e9" +dependencies = [ + "auto_impl", + "environmental", + "ethereum", + "evm-core", + "evm-gasometer", + "evm-runtime", + "log", + "parity-scale-codec", + "primitive-types", + "rlp", + "scale-info", + "serde", + "sha3", +] + +[[package]] +name = "evm-core" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1da6cedc5cedb4208e59467106db0d1f50db01b920920589f8e672c02fdc04f" +dependencies = [ + "parity-scale-codec", + "primitive-types", + "scale-info", + "serde", +] + +[[package]] +name = "evm-gasometer" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dc0eb591abc5cd7b05bef6a036c2bb6c66ab6c5e0c5ce94bfe377ab670b1fd7" +dependencies = [ + "environmental", + "evm-core", + "evm-runtime", + "primitive-types", +] + +[[package]] +name = "evm-runtime" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84bbe09b64ae13a29514048c1bb6fda6374ac0b4f6a1f15a443348ab88ef42cd" +dependencies = [ + "auto_impl", + "environmental", + "evm-core", + "primitive-types", + "sha3", +] + [[package]] name = "exit-future" version = "0.2.0" @@ -2237,6 +2150,173 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +[[package]] +name = "fc-api" +version = "1.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "async-trait", + "fp-storage", + "parity-scale-codec", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "fc-consensus" +version = "2.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "async-trait", + "fp-consensus", + "fp-rpc", + "sc-consensus", + "sp-api", + "sp-block-builder", + "sp-consensus", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "fc-db" +version = "2.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "async-trait", + "ethereum", + "fc-api", + "fc-storage", + "fp-consensus", + "fp-rpc", + "fp-storage", + "futures", + "kvdb-rocksdb", + "log", + "parity-db", + "parity-scale-codec", + "parking_lot 0.12.3", + "sc-client-api", + "sc-client-db", + "smallvec", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-database", + "sp-runtime", + "sqlx", + "tokio", +] + +[[package]] +name = "fc-mapping-sync" +version = "2.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "fc-db", + "fc-storage", + "fp-consensus", + "fp-rpc", + "futures", + "futures-timer", + "log", + "parking_lot 0.12.3", + "sc-client-api", + "sc-utils", + "sp-api", + "sp-blockchain", + "sp-consensus", + "sp-core", + "sp-runtime", + "tokio", +] + +[[package]] +name = "fc-rpc" +version = "2.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "ethereum", + "ethereum-types", + "evm", + "fc-api", + "fc-mapping-sync", + "fc-rpc-core", + "fc-storage", + "fp-evm", + "fp-rpc", + "fp-storage", + "futures", + "hex", + "jsonrpsee", + "libsecp256k1", + "log", + "pallet-evm", + "parity-scale-codec", + "prometheus", + "rand", + "rlp", + "sc-client-api", + "sc-consensus-aura", + "sc-network", + "sc-network-sync", + "sc-rpc", + "sc-service", + "sc-transaction-pool", + "sc-transaction-pool-api", + "sc-utils", + "schnellru", + "serde", + "sp-api", + "sp-block-builder", + "sp-blockchain", + "sp-consensus", + "sp-consensus-aura", + "sp-core", + "sp-externalities", + "sp-inherents", + "sp-io", + "sp-runtime", + "sp-state-machine", + "sp-storage", + "sp-timestamp", + "substrate-prometheus-endpoint", + "thiserror", + "tokio", +] + +[[package]] +name = "fc-rpc-core" +version = "1.1.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "ethereum", + "ethereum-types", + "jsonrpsee", + "rlp", + "rustc-hex", + "serde", + "serde_json", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409)", +] + +[[package]] +name = "fc-storage" +version = "1.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "ethereum", + "ethereum-types", + "fp-rpc", + "fp-storage", + "parity-scale-codec", + "sc-client-api", + "sp-api", + "sp-io", + "sp-runtime", + "sp-storage", +] + [[package]] name = "fdlimit" version = "0.3.0" @@ -2252,22 +2332,9 @@ name = "ff" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core", - "subtle 2.6.1", -] - -[[package]] -name = "fflonk" -version = "0.1.0" -source = "git+https://github.com/w3f/fflonk#1e854f35e9a65d08b11a86291405cdc95baa0a35" -dependencies = [ - "ark-ec", - "ark-ff", - "ark-poly", - "ark-serialize", - "ark-std", - "merlin", +dependencies = [ + "rand_core", + "subtle 2.6.1", ] [[package]] @@ -2351,6 +2418,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" @@ -2374,8 +2452,8 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "fork-tree" -version = "12.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "13.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "parity-scale-codec", ] @@ -2399,6 +2477,110 @@ dependencies = [ "thiserror", ] +[[package]] +name = "fp-account" +version = "1.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "hex", + "impl-serde", + "libsecp256k1", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-runtime-interface", + "staging-xcm", +] + +[[package]] +name = "fp-consensus" +version = "2.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "ethereum", + "parity-scale-codec", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "fp-dynamic-fee" +version = "1.0.0" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "async-trait", + "sp-core", + "sp-inherents", +] + +[[package]] +name = "fp-ethereum" +version = "1.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "ethereum", + "ethereum-types", + "fp-evm", + "frame-support", + "parity-scale-codec", +] + +[[package]] +name = "fp-evm" +version = "3.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "evm", + "frame-support", + "num_enum", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "fp-rpc" +version = "3.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "ethereum", + "ethereum-types", + "fp-evm", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-core", + "sp-runtime", + "sp-state-machine", +] + +[[package]] +name = "fp-self-contained" +version = "1.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "frame-support", + "parity-scale-codec", + "scale-info", + "serde", + "sp-runtime", +] + +[[package]] +name = "fp-storage" +version = "2.0.0" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "parity-scale-codec", + "serde", +] + [[package]] name = "fragile" version = "2.0.0" @@ -2407,8 +2589,8 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" [[package]] name = "frame-benchmarking" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "frame-support", "frame-support-procedural", @@ -2424,15 +2606,15 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-runtime-interface", + "sp-storage", "static_assertions", ] [[package]] name = "frame-benchmarking-cli" -version = "32.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "43.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "Inflector", "array-bytes", @@ -2465,24 +2647,24 @@ dependencies = [ "sp-blockchain", "sp-core", "sp-database", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-externalities", "sp-genesis-builder", "sp-inherents", "sp-io", "sp-keystore", "sp-runtime", "sp-state-machine", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-storage", "sp-trie", - "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-wasm-interface", "thiserror", "thousands", ] [[package]] name = "frame-executive" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "aquamarine", "frame-support", @@ -2494,7 +2676,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-tracing", ] [[package]] @@ -2511,8 +2693,8 @@ dependencies = [ [[package]] name = "frame-metadata-hash-extension" -version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.6.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "array-bytes", "docify", @@ -2526,8 +2708,8 @@ dependencies = [ [[package]] name = "frame-support" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "aquamarine", "array-bytes", @@ -2550,7 +2732,7 @@ dependencies = [ "sp-arithmetic", "sp-core", "sp-crypto-hashing-proc-macro", - "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-debug-derive", "sp-genesis-builder", "sp-inherents", "sp-io", @@ -2558,8 +2740,8 @@ dependencies = [ "sp-runtime", "sp-staking", "sp-state-machine", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-std", + "sp-tracing", "sp-weights", "static_assertions", "tt-call", @@ -2567,21 +2749,21 @@ dependencies = [ [[package]] name = "frame-support-procedural" -version = "23.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "30.0.3" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "Inflector", "cfg-expr", "derive-syn-parse", "docify", "expander", - "frame-support-procedural-tools 10.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "frame-support-procedural-tools 13.0.0", "itertools 0.11.0", "macro_magic", "proc-macro-warning 1.0.2", "proc-macro2", "quote", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409)", "syn 2.0.79", ] @@ -2591,7 +2773,7 @@ version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3363df38464c47a73eb521a4f648bfcc7537a82d70347ef8af3f73b6d019e910" dependencies = [ - "frame-support-procedural-tools-derive 11.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support-procedural-tools-derive 11.0.0", "proc-macro-crate 3.2.0", "proc-macro2", "quote", @@ -2600,10 +2782,10 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools" -version = "10.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "13.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ - "frame-support-procedural-tools-derive 11.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "frame-support-procedural-tools-derive 12.0.0", "proc-macro-crate 3.2.0", "proc-macro2", "quote", @@ -2623,8 +2805,8 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" -version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "12.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "proc-macro2", "quote", @@ -2633,8 +2815,8 @@ dependencies = [ [[package]] name = "frame-system" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "cfg-if", "docify", @@ -2646,15 +2828,15 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-std", "sp-version", "sp-weights", ] [[package]] name = "frame-system-benchmarking" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "frame-benchmarking", "frame-support", @@ -2667,8 +2849,8 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" -version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "docify", "parity-scale-codec", @@ -2677,8 +2859,8 @@ dependencies = [ [[package]] name = "frame-try-runtime" -version = "0.34.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.44.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "frame-support", "parity-scale-codec", @@ -2764,6 +2946,17 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot 0.12.3", +] + [[package]] name = "futures-io" version = "0.3.30" @@ -3081,6 +3274,15 @@ dependencies = [ "hashbrown 0.14.5", ] +[[package]] +name = "hashlink" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +dependencies = [ + "hashbrown 0.14.5", +] + [[package]] name = "heck" version = "0.4.1" @@ -4341,6 +4543,17 @@ dependencies = [ "libsecp256k1-core", ] +[[package]] +name = "libsqlite3-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + [[package]] name = "libz-sys" version = "1.1.20" @@ -4731,7 +4944,7 @@ dependencies = [ "c2-chacha", "curve25519-dalek", "either", - "hashlink", + "hashlink 0.8.4", "lioness", "log", "parking_lot 0.12.3", @@ -4966,6 +5179,23 @@ dependencies = [ "rand", ] +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "ndarray" version = "0.15.6" @@ -5078,11 +5308,22 @@ checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" name = "node-subtensor" version = "4.0.0-dev" dependencies = [ + "async-trait", "clap", + "fc-api", + "fc-consensus", + "fc-db", + "fc-mapping-sync", + "fc-rpc", + "fc-rpc-core", + "fc-storage", + "fp-dynamic-fee", + "fp-rpc", "frame-benchmarking", "frame-benchmarking-cli", "frame-metadata-hash-extension", "frame-system", + "frame-system-rpc-runtime-api", "futures", "jsonrpsee", "memmap2 0.9.5", @@ -5090,6 +5331,8 @@ dependencies = [ "pallet-commitments", "pallet-transaction-payment", "pallet-transaction-payment-rpc", + "pallet-transaction-payment-rpc-runtime-api", + "parity-scale-codec", "sc-basic-authorship", "sc-chain-spec", "sc-chain-spec-derive", @@ -5099,10 +5342,12 @@ dependencies = [ "sc-consensus-aura", "sc-consensus-grandpa", "sc-consensus-grandpa-rpc", + "sc-consensus-manual-seal", "sc-consensus-slots", "sc-executor", "sc-keystore", "sc-network", + "sc-network-sync", "sc-offchain", "sc-rpc", "sc-rpc-api", @@ -5122,10 +5367,14 @@ dependencies = [ "sp-inherents", "sp-io", "sp-keyring", + "sp-offchain", "sp-runtime", + "sp-session", "sp-timestamp", + "sp-transaction-pool", "substrate-build-script-utils", "substrate-frame-rpc-system", + "substrate-prometheus-endpoint", "subtensor-custom-rpc", "subtensor-custom-rpc-runtime-api", ] @@ -5134,6 +5383,11 @@ dependencies = [ name = "node-subtensor-runtime" version = "4.0.0-dev" dependencies = [ + "ed25519-dalek", + "fp-account", + "fp-evm", + "fp-rpc", + "fp-self-contained", "frame-benchmarking", "frame-executive", "frame-metadata", @@ -5147,9 +5401,18 @@ dependencies = [ "pallet-admin-utils", "pallet-aura", "pallet-balances", + "pallet-base-fee", "pallet-collective", "pallet-commitments", + "pallet-dynamic-fee", + "pallet-ethereum", + "pallet-evm", + "pallet-evm-chain-id", + "pallet-evm-precompile-modexp", + "pallet-evm-precompile-sha3fips", + "pallet-evm-precompile-simple", "pallet-grandpa", + "pallet-hotfix-sufficients", "pallet-insecure-randomness-collective-flip", "pallet-membership", "pallet-multisig", @@ -5178,9 +5441,9 @@ dependencies = [ "sp-offchain", "sp-runtime", "sp-session", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-std", + "sp-storage", + "sp-tracing", "sp-transaction-pool", "sp-version", "substrate-wasm-builder", @@ -5232,6 +5495,20 @@ dependencies = [ "winapi", ] +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -5276,12 +5553,24 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-rational" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ + "num-bigint", "num-integer", "num-traits", ] @@ -5306,6 +5595,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate 1.1.3", + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "object" version = "0.30.4" @@ -5458,8 +5768,8 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-std", + "sp-tracing", "sp-weights", "substrate-fixed", "subtensor-macros", @@ -5467,8 +5777,8 @@ dependencies = [ [[package]] name = "pallet-aura" -version = "27.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "37.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "frame-support", "frame-system", @@ -5483,8 +5793,8 @@ dependencies = [ [[package]] name = "pallet-authorship" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "frame-support", "frame-system", @@ -5495,59 +5805,172 @@ dependencies = [ ] [[package]] -name = "pallet-balances" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +name = "pallet-balances" +version = "39.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", +] + +[[package]] +name = "pallet-base-fee" +version = "1.0.0" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "fp-evm", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "pallet-collective" +version = "4.0.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "subtensor-macros", +] + +[[package]] +name = "pallet-commitments" +version = "4.0.0-dev" +dependencies = [ + "enumflags2", + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "subtensor-macros", +] + +[[package]] +name = "pallet-dynamic-fee" +version = "4.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "fp-dynamic-fee", + "fp-evm", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-inherents", +] + +[[package]] +name = "pallet-ethereum" +version = "4.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" dependencies = [ - "docify", - "frame-benchmarking", + "ethereum", + "ethereum-types", + "evm", + "fp-consensus", + "fp-ethereum", + "fp-evm", + "fp-rpc", + "fp-storage", "frame-support", "frame-system", - "log", + "pallet-evm", "parity-scale-codec", "scale-info", + "sp-io", "sp-runtime", ] [[package]] -name = "pallet-collective" -version = "4.0.0-dev" +name = "pallet-evm" +version = "6.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" dependencies = [ + "environmental", + "evm", + "fp-account", + "fp-evm", "frame-benchmarking", "frame-support", "frame-system", + "hash-db", + "hex-literal", + "impl-trait-for-tuples", "log", "parity-scale-codec", "scale-info", "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "subtensor-macros", ] [[package]] -name = "pallet-commitments" -version = "4.0.0-dev" +name = "pallet-evm-chain-id" +version = "1.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" dependencies = [ - "enumflags2", - "frame-benchmarking", "frame-support", "frame-system", - "pallet-balances", "parity-scale-codec", "scale-info", - "sp-core", +] + +[[package]] +name = "pallet-evm-precompile-modexp" +version = "2.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "fp-evm", + "num", +] + +[[package]] +name = "pallet-evm-precompile-sha3fips" +version = "2.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "fp-evm", + "tiny-keccak", +] + +[[package]] +name = "pallet-evm-precompile-simple" +version = "2.0.0-dev" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "fp-evm", + "ripemd", "sp-io", - "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "subtensor-macros", ] [[package]] name = "pallet-grandpa" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "frame-benchmarking", "frame-support", @@ -5566,10 +5989,25 @@ dependencies = [ "sp-staking", ] +[[package]] +name = "pallet-hotfix-sufficients" +version = "1.0.0" +source = "git+https://github.com/gztensor/frontier?rev=b8e3025#b8e3025aa30ea65144372bd68d26090c0f31bea2" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-evm", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", +] + [[package]] name = "pallet-insecure-randomness-collective-flip" -version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "26.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "frame-support", "frame-system", @@ -5581,8 +6019,8 @@ dependencies = [ [[package]] name = "pallet-membership" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "frame-benchmarking", "frame-support", @@ -5597,8 +6035,8 @@ dependencies = [ [[package]] name = "pallet-multisig" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "frame-benchmarking", "frame-support", @@ -5612,8 +6050,8 @@ dependencies = [ [[package]] name = "pallet-preimage" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "frame-benchmarking", "frame-support", @@ -5628,8 +6066,8 @@ dependencies = [ [[package]] name = "pallet-proxy" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "frame-benchmarking", "frame-support", @@ -5653,14 +6091,14 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-std", "subtensor-macros", ] [[package]] name = "pallet-safe-mode" -version = "9.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "19.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "docify", "frame-benchmarking", @@ -5677,8 +6115,8 @@ dependencies = [ [[package]] name = "pallet-scheduler" -version = "29.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "39.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "docify", "frame-benchmarking", @@ -5694,8 +6132,8 @@ dependencies = [ [[package]] name = "pallet-session" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "frame-support", "frame-system", @@ -5744,8 +6182,8 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-std", + "sp-tracing", "sp-version", "substrate-fixed", "subtensor-macros", @@ -5753,8 +6191,8 @@ dependencies = [ [[package]] name = "pallet-sudo" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "docify", "frame-benchmarking", @@ -5768,8 +6206,8 @@ dependencies = [ [[package]] name = "pallet-timestamp" -version = "27.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "37.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "docify", "frame-benchmarking", @@ -5781,14 +6219,14 @@ dependencies = [ "sp-inherents", "sp-io", "sp-runtime", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-storage", "sp-timestamp", ] [[package]] name = "pallet-transaction-payment" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "frame-support", "frame-system", @@ -5802,8 +6240,8 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" -version = "30.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "41.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "jsonrpsee", "pallet-transaction-payment-rpc-runtime-api", @@ -5818,8 +6256,8 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -5830,8 +6268,8 @@ dependencies = [ [[package]] name = "pallet-utility" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "frame-benchmarking", "frame-support", @@ -6448,7 +6886,7 @@ dependencies = [ "cfg-expr", "derive-syn-parse", "expander", - "frame-support-procedural-tools 10.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support-procedural-tools 10.0.0", "itertools 0.10.5", "macro_magic", "proc-macro-warning 1.0.2", @@ -7001,23 +7439,6 @@ dependencies = [ "subtle 2.6.1", ] -[[package]] -name = "ring" -version = "0.1.0" -source = "git+https://github.com/w3f/ring-proof?rev=665f5f5#665f5f51af5734c7b6d90b985dd6861d4c5b4752" -dependencies = [ - "ark-ec", - "ark-ff", - "ark-poly", - "ark-serialize", - "ark-std", - "arrayvec", - "blake2 0.10.6", - "common", - "fflonk", - "merlin", -] - [[package]] name = "ring" version = "0.16.20" @@ -7048,6 +7469,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "rlp" version = "0.5.2" @@ -7055,9 +7485,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ "bytes", + "rlp-derive", "rustc-hex", ] +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "rocksdb" version = "0.21.0" @@ -7294,19 +7736,19 @@ dependencies = [ [[package]] name = "sc-allocator" -version = "23.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "29.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "log", "sp-core", - "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-wasm-interface", "thiserror", ] [[package]] name = "sc-basic-authorship" -version = "0.34.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.45.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "futures", "futures-timer", @@ -7327,8 +7769,8 @@ dependencies = [ [[package]] name = "sc-block-builder" -version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.42.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "parity-scale-codec", "sp-api", @@ -7342,8 +7784,8 @@ dependencies = [ [[package]] name = "sc-chain-spec" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "array-bytes", "docify", @@ -7359,18 +7801,18 @@ dependencies = [ "serde_json", "sp-blockchain", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409)", "sp-genesis-builder", "sp-io", "sp-runtime", "sp-state-machine", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-tracing", ] [[package]] name = "sc-chain-spec-derive" -version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "12.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", @@ -7380,8 +7822,8 @@ dependencies = [ [[package]] name = "sc-cli" -version = "0.36.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.47.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "array-bytes", "chrono", @@ -7421,8 +7863,8 @@ dependencies = [ [[package]] name = "sc-client-api" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "37.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "fnv", "futures", @@ -7437,19 +7879,19 @@ dependencies = [ "sp-consensus", "sp-core", "sp-database", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-externalities", "sp-runtime", "sp-state-machine", "sp-statement-store", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-storage", "sp-trie", "substrate-prometheus-endpoint", ] [[package]] name = "sc-client-db" -version = "0.35.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.44.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "hash-db", "kvdb", @@ -7474,8 +7916,8 @@ dependencies = [ [[package]] name = "sc-consensus" -version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.44.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "async-trait", "futures", @@ -7498,8 +7940,8 @@ dependencies = [ [[package]] name = "sc-consensus-aura" -version = "0.34.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.45.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "async-trait", "futures", @@ -7525,10 +7967,59 @@ dependencies = [ "thiserror", ] +[[package]] +name = "sc-consensus-babe" +version = "0.45.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" +dependencies = [ + "async-trait", + "fork-tree", + "futures", + "log", + "num-bigint", + "num-rational", + "num-traits", + "parity-scale-codec", + "parking_lot 0.12.3", + "sc-client-api", + "sc-consensus", + "sc-consensus-epochs", + "sc-consensus-slots", + "sc-telemetry", + "sc-transaction-pool-api", + "sp-api", + "sp-application-crypto", + "sp-block-builder", + "sp-blockchain", + "sp-consensus", + "sp-consensus-babe", + "sp-consensus-slots", + "sp-core", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409)", + "sp-inherents", + "sp-keystore", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror", +] + +[[package]] +name = "sc-consensus-epochs" +version = "0.44.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" +dependencies = [ + "fork-tree", + "parity-scale-codec", + "sc-client-api", + "sc-consensus", + "sp-blockchain", + "sp-runtime", +] + [[package]] name = "sc-consensus-grandpa" -version = "0.19.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.30.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "ahash 0.8.11", "array-bytes", @@ -7562,7 +8053,7 @@ dependencies = [ "sp-consensus", "sp-consensus-grandpa", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409)", "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", @@ -7571,8 +8062,8 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa-rpc" -version = "0.19.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.30.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "finality-grandpa", "futures", @@ -7589,10 +8080,45 @@ dependencies = [ "thiserror", ] +[[package]] +name = "sc-consensus-manual-seal" +version = "0.46.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" +dependencies = [ + "assert_matches", + "async-trait", + "futures", + "futures-timer", + "jsonrpsee", + "log", + "parity-scale-codec", + "sc-client-api", + "sc-consensus", + "sc-consensus-aura", + "sc-consensus-babe", + "sc-consensus-epochs", + "sc-transaction-pool", + "sc-transaction-pool-api", + "serde", + "sp-api", + "sp-blockchain", + "sp-consensus", + "sp-consensus-aura", + "sp-consensus-babe", + "sp-consensus-slots", + "sp-core", + "sp-inherents", + "sp-keystore", + "sp-runtime", + "sp-timestamp", + "substrate-prometheus-endpoint", + "thiserror", +] + [[package]] name = "sc-consensus-slots" -version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.44.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "async-trait", "futures", @@ -7614,8 +8140,8 @@ dependencies = [ [[package]] name = "sc-executor" -version = "0.32.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.40.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", @@ -7625,44 +8151,44 @@ dependencies = [ "schnellru", "sp-api", "sp-core", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-externalities", "sp-io", "sp-panic-handler", - "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-runtime-interface", "sp-trie", "sp-version", - "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-wasm-interface", "tracing", ] [[package]] name = "sc-executor-common" -version = "0.29.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.35.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "polkavm", "sc-allocator", "sp-maybe-compressed-blob", - "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-wasm-interface", "thiserror", "wasm-instrument", ] [[package]] name = "sc-executor-polkavm" -version = "0.29.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.32.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "log", "polkavm", "sc-executor-common", - "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-wasm-interface", ] [[package]] name = "sc-executor-wasmtime" -version = "0.29.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.35.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "anyhow", "cfg-if", @@ -7672,15 +8198,15 @@ dependencies = [ "rustix 0.36.17", "sc-allocator", "sc-executor-common", - "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-runtime-interface", + "sp-wasm-interface", "wasmtime", ] [[package]] name = "sc-informant" -version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.44.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "console", "futures", @@ -7696,8 +8222,8 @@ dependencies = [ [[package]] name = "sc-keystore" -version = "25.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "33.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "array-bytes", "parking_lot 0.12.3", @@ -7710,8 +8236,8 @@ dependencies = [ [[package]] name = "sc-mixnet" -version = "0.4.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.15.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "array-bytes", "arrayvec", @@ -7739,8 +8265,8 @@ dependencies = [ [[package]] name = "sc-network" -version = "0.34.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.45.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "array-bytes", "async-channel", @@ -7790,8 +8316,8 @@ dependencies = [ [[package]] name = "sc-network-common" -version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.44.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "async-trait", "bitflags 1.3.2", @@ -7808,8 +8334,8 @@ dependencies = [ [[package]] name = "sc-network-gossip" -version = "0.34.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.45.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "ahash 0.8.11", "futures", @@ -7827,8 +8353,8 @@ dependencies = [ [[package]] name = "sc-network-light" -version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.44.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "array-bytes", "async-channel", @@ -7848,8 +8374,8 @@ dependencies = [ [[package]] name = "sc-network-sync" -version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.44.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "array-bytes", "async-channel", @@ -7885,8 +8411,8 @@ dependencies = [ [[package]] name = "sc-network-transactions" -version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.44.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "array-bytes", "futures", @@ -7904,8 +8430,8 @@ dependencies = [ [[package]] name = "sc-network-types" -version = "0.10.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.12.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "bs58 0.5.1", "ed25519-dalek", @@ -7921,8 +8447,8 @@ dependencies = [ [[package]] name = "sc-offchain" -version = "29.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "40.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "array-bytes", "bytes", @@ -7945,7 +8471,7 @@ dependencies = [ "sc-utils", "sp-api", "sp-core", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-externalities", "sp-keystore", "sp-offchain", "sp-runtime", @@ -7955,8 +8481,8 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" -version = "0.17.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.18.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -7964,8 +8490,8 @@ dependencies = [ [[package]] name = "sc-rpc" -version = "29.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "40.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "futures", "jsonrpsee", @@ -7996,8 +8522,8 @@ dependencies = [ [[package]] name = "sc-rpc-api" -version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.44.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -8016,8 +8542,8 @@ dependencies = [ [[package]] name = "sc-rpc-server" -version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "17.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "dyn-clone", "forwarded-header-value", @@ -8040,8 +8566,8 @@ dependencies = [ [[package]] name = "sc-rpc-spec-v2" -version = "0.34.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.45.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "array-bytes", "futures", @@ -8072,8 +8598,8 @@ dependencies = [ [[package]] name = "sc-service" -version = "0.35.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.46.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "async-trait", "directories", @@ -8115,12 +8641,12 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-core", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-externalities", "sp-keystore", "sp-runtime", "sp-session", "sp-state-machine", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-storage", "sp-transaction-pool", "sp-transaction-storage-proof", "sp-trie", @@ -8136,8 +8662,8 @@ dependencies = [ [[package]] name = "sc-state-db" -version = "0.30.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.36.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "log", "parity-scale-codec", @@ -8147,8 +8673,8 @@ dependencies = [ [[package]] name = "sc-sysinfo" -version = "27.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "derive_more", "futures", @@ -8161,15 +8687,15 @@ dependencies = [ "serde", "serde_json", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409)", "sp-io", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-std", ] [[package]] name = "sc-telemetry" -version = "15.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "25.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "chrono", "futures", @@ -8188,8 +8714,8 @@ dependencies = [ [[package]] name = "sc-tracing" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "37.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "chrono", "console", @@ -8208,7 +8734,7 @@ dependencies = [ "sp-core", "sp-rpc", "sp-runtime", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-tracing", "thiserror", "tracing", "tracing-log", @@ -8218,7 +8744,7 @@ dependencies = [ [[package]] name = "sc-tracing-proc-macro" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", @@ -8228,8 +8754,8 @@ dependencies = [ [[package]] name = "sc-transaction-pool" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "37.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "async-trait", "futures", @@ -8245,9 +8771,9 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409)", "sp-runtime", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-tracing", "sp-transaction-pool", "substrate-prometheus-endpoint", "thiserror", @@ -8255,8 +8781,8 @@ dependencies = [ [[package]] name = "sc-transaction-pool-api" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "37.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "async-trait", "futures", @@ -8271,8 +8797,8 @@ dependencies = [ [[package]] name = "sc-utils" -version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "17.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "async-channel", "futures", @@ -8578,6 +9104,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "serde_with" version = "2.0.0" @@ -8832,8 +9370,8 @@ dependencies = [ [[package]] name = "sp-api" -version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "docify", "hash-db", @@ -8842,10 +9380,10 @@ dependencies = [ "scale-info", "sp-api-proc-macro", "sp-core", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-externalities", "sp-metadata-ir", "sp-runtime", - "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-runtime-interface", "sp-state-machine", "sp-trie", "sp-version", @@ -8854,8 +9392,8 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" -version = "15.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "20.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "Inflector", "blake2 0.10.6", @@ -8868,8 +9406,8 @@ dependencies = [ [[package]] name = "sp-application-crypto" -version = "30.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "parity-scale-codec", "scale-info", @@ -8880,40 +9418,22 @@ dependencies = [ [[package]] name = "sp-arithmetic" -version = "23.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "26.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "docify", "integer-sqrt", - "num-traits", - "parity-scale-codec", - "scale-info", - "serde", - "static_assertions", -] - -[[package]] -name = "sp-ark-bls12-381" -version = "0.4.2" -source = "git+https://github.com/paritytech/arkworks-substrate#caa2eed74beb885dd07c7db5f916f2281dad818f" -dependencies = [ - "ark-bls12-381-ext", - "sp-crypto-ec-utils", -] - -[[package]] -name = "sp-ark-ed-on-bls12-381-bandersnatch" -version = "0.4.2" -source = "git+https://github.com/paritytech/arkworks-substrate#caa2eed74beb885dd07c7db5f916f2281dad818f" -dependencies = [ - "ark-ed-on-bls12-381-bandersnatch-ext", - "sp-crypto-ec-utils", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "static_assertions", ] [[package]] name = "sp-block-builder" -version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "sp-api", "sp-inherents", @@ -8922,8 +9442,8 @@ dependencies = [ [[package]] name = "sp-blockchain" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "37.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "futures", "parity-scale-codec", @@ -8941,8 +9461,8 @@ dependencies = [ [[package]] name = "sp-consensus" -version = "0.32.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.40.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "async-trait", "futures", @@ -8956,15 +9476,33 @@ dependencies = [ [[package]] name = "sp-consensus-aura" -version = "0.32.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.40.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" +dependencies = [ + "async-trait", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-application-crypto", + "sp-consensus-slots", + "sp-inherents", + "sp-runtime", + "sp-timestamp", +] + +[[package]] +name = "sp-consensus-babe" +version = "0.40.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "async-trait", "parity-scale-codec", "scale-info", + "serde", "sp-api", "sp-application-crypto", "sp-consensus-slots", + "sp-core", "sp-inherents", "sp-runtime", "sp-timestamp", @@ -8972,8 +9510,8 @@ dependencies = [ [[package]] name = "sp-consensus-grandpa" -version = "13.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "21.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "finality-grandpa", "log", @@ -8989,8 +9527,8 @@ dependencies = [ [[package]] name = "sp-consensus-slots" -version = "0.32.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.40.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "parity-scale-codec", "scale-info", @@ -9000,11 +9538,10 @@ dependencies = [ [[package]] name = "sp-core" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "array-bytes", - "bandersnatch_vrfs", "bitflags 1.3.2", "blake2 0.10.6", "bounded-collections", @@ -9031,12 +9568,12 @@ dependencies = [ "secp256k1", "secrecy", "serde", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409)", + "sp-debug-derive", + "sp-externalities", + "sp-runtime-interface", + "sp-std", + "sp-storage", "ss58-registry", "substrate-bip39", "thiserror", @@ -9045,26 +9582,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "sp-crypto-ec-utils" -version = "0.10.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" -dependencies = [ - "ark-bls12-377", - "ark-bls12-377-ext", - "ark-bls12-381", - "ark-bls12-381-ext", - "ark-bw6-761", - "ark-bw6-761-ext", - "ark-ec", - "ark-ed-on-bls12-377", - "ark-ed-on-bls12-377-ext", - "ark-ed-on-bls12-381-bandersnatch", - "ark-ed-on-bls12-381-bandersnatch-ext", - "ark-scale", - "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk)", -] - [[package]] name = "sp-crypto-hashing" version = "0.1.0" @@ -9082,7 +9599,7 @@ dependencies = [ [[package]] name = "sp-crypto-hashing" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "blake2b_simd", "byteorder", @@ -9095,17 +9612,17 @@ dependencies = [ [[package]] name = "sp-crypto-hashing-proc-macro" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "quote", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409)", "syn 2.0.79", ] [[package]] name = "sp-database" version = "10.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "kvdb", "parking_lot 0.12.3", @@ -9114,17 +9631,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[package]] -name = "sp-debug-derive" -version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "proc-macro2", "quote", @@ -9133,28 +9640,18 @@ dependencies = [ [[package]] name = "sp-externalities" -version = "0.25.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" -dependencies = [ - "environmental", - "parity-scale-codec", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", -] - -[[package]] -name = "sp-externalities" -version = "0.25.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" +version = "0.29.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "environmental", "parity-scale-codec", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk)", + "sp-storage", ] [[package]] name = "sp-genesis-builder" -version = "0.8.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.15.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "parity-scale-codec", "scale-info", @@ -9165,8 +9662,8 @@ dependencies = [ [[package]] name = "sp-inherents" -version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "async-trait", "impl-trait-for-tuples", @@ -9178,8 +9675,8 @@ dependencies = [ [[package]] name = "sp-io" -version = "30.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "bytes", "docify", @@ -9191,12 +9688,12 @@ dependencies = [ "rustversion", "secp256k1", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409)", + "sp-externalities", "sp-keystore", - "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-runtime-interface", "sp-state-machine", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-tracing", "sp-trie", "tracing", "tracing-core", @@ -9204,8 +9701,8 @@ dependencies = [ [[package]] name = "sp-keyring" -version = "31.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "39.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "sp-core", "sp-runtime", @@ -9214,19 +9711,19 @@ dependencies = [ [[package]] name = "sp-keystore" -version = "0.34.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.40.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", "sp-core", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-externalities", ] [[package]] name = "sp-maybe-compressed-blob" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "thiserror", "zstd 0.12.4", @@ -9234,8 +9731,8 @@ dependencies = [ [[package]] name = "sp-metadata-ir" -version = "0.6.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.7.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "frame-metadata", "parity-scale-codec", @@ -9244,8 +9741,8 @@ dependencies = [ [[package]] name = "sp-mixnet" -version = "0.4.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.12.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "parity-scale-codec", "scale-info", @@ -9255,8 +9752,8 @@ dependencies = [ [[package]] name = "sp-offchain" -version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "sp-api", "sp-core", @@ -9266,7 +9763,7 @@ dependencies = [ [[package]] name = "sp-panic-handler" version = "13.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "backtrace", "lazy_static", @@ -9275,8 +9772,8 @@ dependencies = [ [[package]] name = "sp-rpc" -version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "32.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "rustc-hash 1.1.0", "serde", @@ -9285,8 +9782,8 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "31.0.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "39.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "docify", "either", @@ -9304,66 +9801,34 @@ dependencies = [ "sp-arithmetic", "sp-core", "sp-io", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-std", "sp-weights", "tracing", ] [[package]] name = "sp-runtime-interface" -version = "24.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" -dependencies = [ - "bytes", - "impl-trait-for-tuples", - "parity-scale-codec", - "polkavm-derive", - "primitive-types", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-runtime-interface-proc-macro 17.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "static_assertions", -] - -[[package]] -name = "sp-runtime-interface" -version = "24.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" +version = "28.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", "polkavm-derive", "primitive-types", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk)", - "sp-runtime-interface-proc-macro 17.0.0 (git+https://github.com/paritytech/polkadot-sdk)", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk)", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk)", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk)", - "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk)", + "sp-externalities", + "sp-runtime-interface-proc-macro", + "sp-std", + "sp-storage", + "sp-tracing", + "sp-wasm-interface", "static_assertions", ] [[package]] name = "sp-runtime-interface-proc-macro" -version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" -dependencies = [ - "Inflector", - "expander", - "proc-macro-crate 3.2.0", - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[package]] -name = "sp-runtime-interface-proc-macro" -version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" +version = "18.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "Inflector", "expander", @@ -9375,8 +9840,8 @@ dependencies = [ [[package]] name = "sp-session" -version = "27.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "36.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "parity-scale-codec", "scale-info", @@ -9389,8 +9854,8 @@ dependencies = [ [[package]] name = "sp-staking" -version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "36.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -9402,8 +9867,8 @@ dependencies = [ [[package]] name = "sp-state-machine" -version = "0.35.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.43.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "hash-db", "log", @@ -9412,7 +9877,7 @@ dependencies = [ "rand", "smallvec", "sp-core", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-externalities", "sp-panic-handler", "sp-trie", "thiserror", @@ -9422,8 +9887,8 @@ dependencies = [ [[package]] name = "sp-statement-store" -version = "10.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "18.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "aes-gcm", "curve25519-dalek", @@ -9436,10 +9901,10 @@ dependencies = [ "sp-api", "sp-application-crypto", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409)", + "sp-externalities", "sp-runtime", - "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-runtime-interface", "thiserror", "x25519-dalek", ] @@ -9447,41 +9912,24 @@ dependencies = [ [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" - -[[package]] -name = "sp-std" -version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" - -[[package]] -name = "sp-storage" -version = "19.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" -dependencies = [ - "impl-serde", - "parity-scale-codec", - "ref-cast", - "serde", - "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", -] +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" [[package]] name = "sp-storage" -version = "19.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" +version = "21.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "impl-serde", "parity-scale-codec", "ref-cast", "serde", - "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk)", + "sp-debug-derive", ] [[package]] name = "sp-timestamp" -version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "async-trait", "parity-scale-codec", @@ -9492,19 +9940,8 @@ dependencies = [ [[package]] name = "sp-tracing" -version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" -dependencies = [ - "parity-scale-codec", - "tracing", - "tracing-core", - "tracing-subscriber", -] - -[[package]] -name = "sp-tracing" -version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" +version = "17.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "parity-scale-codec", "tracing", @@ -9514,8 +9951,8 @@ dependencies = [ [[package]] name = "sp-transaction-pool" -version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "sp-api", "sp-runtime", @@ -9523,8 +9960,8 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" -version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "async-trait", "parity-scale-codec", @@ -9537,8 +9974,8 @@ dependencies = [ [[package]] name = "sp-trie" -version = "29.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "37.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "ahash 0.8.11", "hash-db", @@ -9551,7 +9988,7 @@ dependencies = [ "scale-info", "schnellru", "sp-core", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-externalities", "thiserror", "tracing", "trie-db", @@ -9560,8 +9997,8 @@ dependencies = [ [[package]] name = "sp-version" -version = "29.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "37.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "impl-serde", "parity-scale-codec", @@ -9570,15 +10007,15 @@ dependencies = [ "serde", "sp-crypto-hashing-proc-macro", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-std", "sp-version-proc-macro", "thiserror", ] [[package]] name = "sp-version-proc-macro" -version = "13.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "14.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "parity-scale-codec", "proc-macro2", @@ -9588,8 +10025,8 @@ dependencies = [ [[package]] name = "sp-wasm-interface" -version = "20.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "21.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -9598,21 +10035,10 @@ dependencies = [ "wasmtime", ] -[[package]] -name = "sp-wasm-interface" -version = "20.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" -dependencies = [ - "anyhow", - "impl-trait-for-tuples", - "log", - "parity-scale-codec", -] - [[package]] name = "sp-weights" -version = "27.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "31.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "bounded-collections", "parity-scale-codec", @@ -9620,7 +10046,7 @@ dependencies = [ "serde", "smallvec", "sp-arithmetic", - "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-debug-derive", ] [[package]] @@ -9634,6 +10060,9 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "spinning_top" @@ -9654,6 +10083,126 @@ dependencies = [ "der", ] +[[package]] +name = "sqlformat" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" +dependencies = [ + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93334716a037193fac19df402f8571269c84a00852f6a7066b5d2616dcd64d3e" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d8060b456358185f7d50c55d9b5066ad956956fddec42ee2e8567134a8936e" +dependencies = [ + "atoi", + "byteorder", + "bytes", + "crc", + "crossbeam-queue", + "either", + "event-listener 5.3.1", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashbrown 0.14.5", + "hashlink 0.9.1", + "hex", + "indexmap 2.6.0", + "log", + "memchr", + "native-tls", + "once_cell", + "paste", + "percent-encoding", + "serde", + "sha2 0.10.8", + "smallvec", + "sqlformat", + "thiserror", + "tokio", + "tokio-stream", + "tracing", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cac0692bcc9de3b073e8d747391827297e075c7710ff6276d9f7a1f3d58c6657" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 2.0.79", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1804e8a7c7865599c9c79be146dc8a9fd8cc86935fa641d3ea58e5f0688abaa5" +dependencies = [ + "dotenvy", + "either", + "heck 0.5.0", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2 0.10.8", + "sqlx-core", + "sqlx-sqlite", + "syn 2.0.79", + "tempfile", + "tokio", + "url", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680" +dependencies = [ + "atoi", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "serde_urlencoded", + "sqlx-core", + "tracing", + "url", +] + [[package]] name = "ss58-registry" version = "1.50.0" @@ -9675,6 +10224,25 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "staging-xcm" +version = "14.2.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" +dependencies = [ + "array-bytes", + "bounded-collections", + "derivative", + "environmental", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-runtime", + "sp-weights", + "xcm-procedural", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -9778,8 +10346,8 @@ dependencies = [ [[package]] name = "substrate-bip39" -version = "0.4.7" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "0.6.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "hmac 0.12.1", "pbkdf2", @@ -9791,7 +10359,7 @@ dependencies = [ [[package]] name = "substrate-build-script-utils" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" [[package]] name = "substrate-fixed" @@ -9806,8 +10374,8 @@ dependencies = [ [[package]] name = "substrate-frame-rpc-system" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "39.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "docify", "frame-system-rpc-runtime-api", @@ -9827,7 +10395,7 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" version = "0.17.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "http-body-util", "hyper 1.4.1", @@ -9840,8 +10408,8 @@ dependencies = [ [[package]] name = "substrate-wasm-builder" -version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1#a427d8fb677b62635dfb78a6e530facdd2c362ec" +version = "24.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" dependencies = [ "array-bytes", "build-helper", @@ -9858,7 +10426,7 @@ dependencies = [ "sp-core", "sp-io", "sp-maybe-compressed-blob", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.16.0-rc1)", + "sp-tracing", "sp-version", "strum 0.26.3", "tempfile", @@ -10619,6 +11187,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "universal-hash" version = "0.5.1" @@ -11511,6 +12085,17 @@ dependencies = [ "time", ] +[[package]] +name = "xcm-procedural" +version = "10.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409#87971b3e92721bdf10bf40b410eaae779d494ca0" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "xml-rs" version = "0.8.22" diff --git a/Cargo.toml b/Cargo.toml index 64313ad79..e94ef3dfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,8 +46,11 @@ unwrap-used = "deny" manual_inspect = "allow" [workspace.dependencies] +async-trait = "0.1" cargo-husky = { version = "1", default-features = false } clap = "4.5.4" +codec = { version = "3.2.2", default-features = false } +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 } @@ -58,6 +61,7 @@ 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-info = { version = "2.11.2", default-features = false } serde = { version = "1.0.199", default-features = false } serde-tuple-vec-map = { version = "1.0.1", default-features = false } @@ -65,7 +69,7 @@ serde_bytes = { version = "0.11.14", default-features = false } serde_json = { version = "1.0.121", default-features = false } serde_with = { version = "=2.0.0", default-features = false } smallvec = "1.13.2" -litep2p = { git = "https://github.com/paritytech/litep2p", branch = "master" } +litep2p = { git = "https://github.com/paritytech/litep2p", tag = "v0.7.0" } syn = { version = "2", features = [ "full", "visit-mut", @@ -79,83 +83,112 @@ walkdir = "2" subtensor-macros = { path = "support/macros" } -codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false } - -frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -frame-executive = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -frame-metadata-hash-extension = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -frame-support = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -frame-system = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -frame-system-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -frame-try-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } - -pallet-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -pallet-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -pallet-membership = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -pallet-multisig = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -pallet-preimage = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -pallet-proxy = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -pallet-safe-mode = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -pallet-scheduler = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -pallet-utility = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } - -sc-basic-authorship = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-client-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-consensus = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-consensus-grandpa-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-chain-spec-derive = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-chain-spec = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-consensus-slots = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-executor = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-keystore = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-network = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-rpc-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-service = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-telemetry = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sc-transaction-pool-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } - -sp-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-blockchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-consensus = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sp-genesis-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-io = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-std = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-storage = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -sp-tracing = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-version = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1", default-features = false } - -substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } +frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +frame-executive = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +frame-metadata-hash-extension = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +frame-try-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } + +pallet-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +pallet-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +pallet-membership = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +pallet-multisig = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +pallet-preimage = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +pallet-proxy = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +pallet-safe-mode = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +pallet-scheduler = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +pallet-utility = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } + +sc-basic-authorship = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-client-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-consensus = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-consensus-grandpa-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-chain-spec-derive = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-chain-spec = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-consensus-slots = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-executor = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-keystore = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-network = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-rpc-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-service = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-telemetry = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sc-transaction-pool-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } + +sp-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-blockchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-consensus = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sp-genesis-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-storage = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +sp-tracing = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-version = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } + +substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } substrate-fixed = { git = "https://github.com/opentensor/substrate-fixed.git", tag = "v0.5.9" } -substrate-frame-rpc-system = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } -substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.16.0-rc1" } +substrate-frame-rpc-system = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } +substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409" } + +sc-consensus-manual-seal = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +sc-network-sync = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false } + +# Frontier +fp-evm = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +fp-rpc = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +fp-self-contained = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false, features = [ + "serde", +] } +fp-account = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +fc-storage = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +fc-db = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +fc-consensus = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +fp-dynamic-fee = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +fc-api = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +fc-rpc = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +fc-rpc-core = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +fc-mapping-sync = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } + +# Frontier FRAME +pallet-base-fee = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +pallet-dynamic-fee = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +pallet-ethereum = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +pallet-evm = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +pallet-evm-chain-id = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +pallet-evm-precompile-modexp = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +pallet-evm-precompile-sha3fips = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +pallet-evm-precompile-simple = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } +pallet-hotfix-sufficients = { git = "https://github.com/gztensor/frontier", rev = "b8e3025", default-features = false } + frame-metadata = "16" [profile.release] diff --git a/node/Cargo.toml b/node/Cargo.toml index 3c5c91b92..2aba49c96 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -20,8 +20,10 @@ targets = ["x86_64-unknown-linux-gnu"] name = "node-subtensor" [dependencies] +async-trait = { workspace = true } clap = { workspace = true, features = ["derive"] } futures = { workspace = true, features = ["thread-pool"] } +scale-codec = { workspace = true } serde = { workspace = true, features = ["derive"] } # Storage import @@ -52,8 +54,11 @@ sc-client-api = { workspace = true } sp-runtime = { workspace = true } sp-io = { workspace = true } sp-timestamp = { workspace = true } +sp-transaction-pool = { workspace = true, features = ["default"] } sp-inherents = { workspace = true } sp-keyring = { workspace = true } +sp-offchain = { workspace = true } +sp-session = { workspace = true } frame-metadata-hash-extension = { workspace = true } frame-system = { workspace = true } pallet-transaction-payment = { workspace = true } @@ -69,11 +74,29 @@ sp-block-builder = { workspace = true } sc-basic-authorship = { workspace = true } substrate-frame-rpc-system = { workspace = true } pallet-transaction-payment-rpc = { workspace = true } +frame-system-rpc-runtime-api = { workspace = true } +pallet-transaction-payment-rpc-runtime-api = { workspace = true } # These dependencies are used for runtime benchmarking frame-benchmarking = { workspace = true } frame-benchmarking-cli = { workspace = true } +# Needed for Frontier +sc-consensus-manual-seal = { workspace = true } +sc-network-sync = { workspace = true } +substrate-prometheus-endpoint = { workspace = true } + +# Frontier +fc-storage = { workspace = true } +fc-db = { workspace = true } +fc-consensus = { workspace = true } +fp-dynamic-fee = { workspace = true } +fc-api = { workspace = true } +fc-rpc = { workspace = true } +fc-rpc-core = { workspace = true } +fp-rpc = { workspace = true } +fc-mapping-sync = { workspace = true } + # Local Dependencies node-subtensor-runtime = { path = "../runtime" } subtensor-custom-rpc = { path = "../pallets/subtensor/rpc" } @@ -83,7 +106,26 @@ subtensor-custom-rpc-runtime-api = { path = "../pallets/subtensor/runtime-api" } substrate-build-script-utils = { workspace = true } [features] -default = [] +default = [ + "rocksdb", + "sql", + "txpool", +] +sql = [ + "fc-db/sql", + "fc-mapping-sync/sql", +] +rocksdb = [ + "sc-service/rocksdb", + "fc-db/rocksdb", + "fc-mapping-sync/rocksdb", + "fc-rpc/rocksdb" +] +txpool = [ + "fc-rpc/txpool", + "fc-rpc-core/txpool" +] + # Dependencies that are only required if runtime benchmarking should be build. runtime-benchmarks = [ "node-subtensor-runtime/runtime-benchmarks", diff --git a/node/src/benchmarking.rs b/node/src/benchmarking.rs index cf48df62f..a97550071 100644 --- a/node/src/benchmarking.rs +++ b/node/src/benchmarking.rs @@ -2,7 +2,7 @@ //! //! Should only be used for benchmarking as it may break in other contexts. -use crate::service::FullClient; +use crate::service::Client; use node_subtensor_runtime as runtime; use node_subtensor_runtime::check_nonce; @@ -21,12 +21,12 @@ use std::{sync::Arc, time::Duration}; // // Note: Should only be used for benchmarking. pub struct RemarkBuilder { - client: Arc, + client: Arc, } impl RemarkBuilder { // Creates a new [`Self`] from the given client. - pub fn new(client: Arc) -> Self { + pub fn new(client: Arc) -> Self { Self { client } } } @@ -58,14 +58,14 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder { // // Note: Should only be used for benchmarking. pub struct TransferKeepAliveBuilder { - client: Arc, + client: Arc, dest: AccountId, value: Balance, } impl TransferKeepAliveBuilder { // Creates a new [`Self`] from the given client. - pub fn new(client: Arc, dest: AccountId, value: Balance) -> Self { + pub fn new(client: Arc, dest: AccountId, value: Balance) -> Self { Self { client, dest, @@ -105,7 +105,7 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder { // // Note: Should only be used for benchmarking. pub fn create_benchmark_extrinsic( - client: &FullClient, + client: &Client, sender: sp_core::sr25519::Pair, call: runtime::RuntimeCall, nonce: u32, diff --git a/node/src/cli.rs b/node/src/cli.rs index 2c9c4c9fd..d9744d44d 100644 --- a/node/src/cli.rs +++ b/node/src/cli.rs @@ -1,3 +1,4 @@ +use crate::ethereum::EthConfiguration; use sc_cli::RunCmd; #[derive(Debug, clap::Parser)] @@ -7,6 +8,13 @@ pub struct Cli { #[clap(flatten)] pub run: RunCmd, + + /// Choose sealing method. + #[arg(long, value_enum, ignore_case = true)] + pub sealing: Option, + + #[command(flatten)] + pub eth: EthConfiguration, } #[allow(clippy::large_enum_variant)] @@ -45,3 +53,13 @@ pub enum Subcommand { // Db meta columns information. ChainInfo(sc_cli::ChainInfoCmd), } + +/// Available Sealing methods. +#[derive(Copy, Clone, Debug, Default, clap::ValueEnum)] +pub enum Sealing { + /// Seal using rpc method. + #[default] + Manual, + /// Seal when transaction is executed. + Instant, +} diff --git a/node/src/client.rs b/node/src/client.rs new file mode 100644 index 000000000..c7196b5a9 --- /dev/null +++ b/node/src/client.rs @@ -0,0 +1,76 @@ +use scale_codec::Codec; +// Substrate +use sc_executor::WasmExecutor; +use sp_runtime::traits::{Block as BlockT, MaybeDisplay}; + +use crate::ethereum::EthCompatRuntimeApiCollection; + +/// Full backend. +pub type FullBackend = sc_service::TFullBackend; +/// Full client. +pub type FullClient = sc_service::TFullClient>; + +/// A set of APIs that every runtime must implement. +pub trait BaseRuntimeApiCollection: + sp_api::ApiExt + + sp_api::Metadata + + sp_block_builder::BlockBuilder + + sp_offchain::OffchainWorkerApi + + sp_session::SessionKeys + + sp_transaction_pool::runtime_api::TaggedTransactionQueue +{ +} + +impl BaseRuntimeApiCollection for Api +where + Block: BlockT, + Api: sp_api::ApiExt + + sp_api::Metadata + + sp_block_builder::BlockBuilder + + sp_offchain::OffchainWorkerApi + + sp_session::SessionKeys + + sp_transaction_pool::runtime_api::TaggedTransactionQueue, +{ +} + +/// A set of APIs that Subtensor runtime must implement. +pub trait RuntimeApiCollection< + Block: BlockT, + AuraId: Codec, + AccountId: Codec, + Nonce: Codec, + Balance: Codec + MaybeDisplay, +>: + BaseRuntimeApiCollection + + EthCompatRuntimeApiCollection + + sp_consensus_aura::AuraApi + + sp_consensus_grandpa::GrandpaApi + + frame_system_rpc_runtime_api::AccountNonceApi + + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + + subtensor_custom_rpc_runtime_api::DelegateInfoRuntimeApi + + subtensor_custom_rpc_runtime_api::NeuronInfoRuntimeApi + + subtensor_custom_rpc_runtime_api::SubnetInfoRuntimeApi + + subtensor_custom_rpc_runtime_api::SubnetRegistrationRuntimeApi +{ +} + +impl + RuntimeApiCollection for Api +where + Block: BlockT, + AuraId: Codec, + AccountId: Codec, + Nonce: Codec, + Balance: Codec + MaybeDisplay, + Api: BaseRuntimeApiCollection + + EthCompatRuntimeApiCollection + + sp_consensus_aura::AuraApi + + sp_consensus_grandpa::GrandpaApi + + frame_system_rpc_runtime_api::AccountNonceApi + + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + + subtensor_custom_rpc_runtime_api::DelegateInfoRuntimeApi + + subtensor_custom_rpc_runtime_api::NeuronInfoRuntimeApi + + subtensor_custom_rpc_runtime_api::SubnetInfoRuntimeApi + + subtensor_custom_rpc_runtime_api::SubnetRegistrationRuntimeApi, +{ +} diff --git a/node/src/command.rs b/node/src/command.rs index 0f3914239..0839649bd 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -1,23 +1,17 @@ use crate::{ chain_spec, cli::{Cli, Subcommand}, + ethereum::db_config_dir, service, }; +use fc_db::{kv::frontier_database_dir, DatabaseSource}; -#[cfg(feature = "runtime-benchmarks")] -pub use crate::benchmarking::{inherent_benchmark_data, RemarkBuilder, TransferKeepAliveBuilder}; -#[cfg(feature = "runtime-benchmarks")] -pub use frame_benchmarking_cli::{BenchmarkCmd, ExtrinsicFactory, SUBSTRATE_REFERENCE_HARDWARE}; -#[cfg(feature = "runtime-benchmarks")] -pub use node_subtensor_runtime::EXISTENTIAL_DEPOSIT; -#[cfg(feature = "runtime-benchmarks")] -pub use sp_keyring::Sr25519Keyring; - +use futures::TryFutureExt; use node_subtensor_runtime::Block; use sc_cli::SubstrateCli; use sc_service::{ config::{ExecutorConfiguration, RpcConfiguration}, - Configuration, PartialComponents, + Configuration, }; impl SubstrateCli for Cli { @@ -69,64 +63,89 @@ pub fn run() -> sc_cli::Result<()> { } Some(Subcommand::CheckBlock(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { - client, - task_manager, - import_queue, - .. - } = service::new_partial(&config)?; + runner.async_run(|mut config| { + let (client, _, import_queue, task_manager, _) = + service::new_chain_ops(&mut config, &cli.eth)?; Ok((cmd.run(client, import_queue), task_manager)) }) } Some(Subcommand::ExportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { - client, - task_manager, - .. - } = service::new_partial(&config)?; + runner.async_run(|mut config| { + let (client, _, _, task_manager, _) = + service::new_chain_ops(&mut config, &cli.eth)?; Ok((cmd.run(client, config.database), task_manager)) }) } Some(Subcommand::ExportState(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { - client, - task_manager, - .. - } = service::new_partial(&config)?; + runner.async_run(|mut config| { + let (client, _, _, task_manager, _) = + service::new_chain_ops(&mut config, &cli.eth)?; Ok((cmd.run(client, config.chain_spec), task_manager)) }) } Some(Subcommand::ImportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { - client, - task_manager, - import_queue, - .. - } = service::new_partial(&config)?; + runner.async_run(|mut config| { + let (client, _, import_queue, task_manager, _) = + service::new_chain_ops(&mut config, &cli.eth)?; Ok((cmd.run(client, import_queue), task_manager)) }) } Some(Subcommand::PurgeChain(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run(config.database)) + runner.sync_run(|config| { + // Remove Frontier offchain db + let db_config_dir = db_config_dir(&config); + match cli.eth.frontier_backend_type { + crate::ethereum::BackendType::KeyValue => { + let frontier_database_config = match config.database { + DatabaseSource::RocksDb { .. } => DatabaseSource::RocksDb { + path: frontier_database_dir(&db_config_dir, "db"), + cache_size: 0, + }, + DatabaseSource::ParityDb { .. } => DatabaseSource::ParityDb { + path: frontier_database_dir(&db_config_dir, "paritydb"), + }, + _ => { + return Err(format!( + "Cannot purge `{:?}` database", + config.database + ) + .into()) + } + }; + cmd.run(frontier_database_config)?; + } + crate::ethereum::BackendType::Sql => { + let db_path = db_config_dir.join("sql"); + match std::fs::remove_dir_all(&db_path) { + Ok(_) => { + println!("{:?} removed.", &db_path); + } + Err(ref err) if err.kind() == std::io::ErrorKind::NotFound => { + eprintln!("{:?} did not exist.", &db_path); + } + Err(err) => { + return Err(format!( + "Cannot purge `{:?}` database: {:?}", + db_path, err, + ) + .into()) + } + }; + } + }; + cmd.run(config.database) + }) } Some(Subcommand::Revert(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { - client, - task_manager, - backend, - .. - } = service::new_partial(&config)?; - let aux_revert = Box::new(|client, _, blocks| { + runner.async_run(|mut config| { + let (client, backend, _, task_manager, _) = + service::new_chain_ops(&mut config, &cli.eth)?; + let aux_revert = Box::new(move |client, _, blocks| { sc_consensus_grandpa::revert(client, blocks)?; Ok(()) }); @@ -135,46 +154,42 @@ pub fn run() -> sc_cli::Result<()> { } #[cfg(feature = "runtime-benchmarks")] Some(Subcommand::Benchmark(cmd)) => { + use crate::benchmarking::{ + inherent_benchmark_data, RemarkBuilder, TransferKeepAliveBuilder, + }; + use frame_benchmarking_cli::{ + BenchmarkCmd, ExtrinsicFactory, SUBSTRATE_REFERENCE_HARDWARE, + }; + use node_subtensor_runtime::EXISTENTIAL_DEPOSIT; + use sc_service::PartialComponents; + use sp_keyring::Sr25519Keyring; + use sp_runtime::traits::HashingFor; + let runner = cli.create_runner(cmd)?; runner.sync_run(|config| { + let PartialComponents { + client, backend, .. + } = crate::service::new_partial( + &config, + &cli.eth, + crate::service::build_manual_seal_import_queue, + )?; + // This switch needs to be in the client, since the client decides // which sub-commands it wants to support. match cmd { BenchmarkCmd::Pallet(cmd) => { - if !cfg!(feature = "runtime-benchmarks") { - return Err( - "Runtime benchmarking wasn't enabled when building the node. \ - You can enable it with `--features runtime-benchmarks`." - .into(), - ); - } - - cmd.run_with_spec::, ()>(Some( - config.chain_spec, - )) - } - BenchmarkCmd::Block(cmd) => { - let PartialComponents { client, .. } = service::new_partial(&config)?; - cmd.run(client) + cmd.run_with_spec::, ()>(Some(config.chain_spec)) } - #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => Err( - "Storage benchmarking can be enabled with `--features runtime-benchmarks`." - .into(), - ), - #[cfg(feature = "runtime-benchmarks")] + BenchmarkCmd::Block(cmd) => cmd.run(client), BenchmarkCmd::Storage(cmd) => { - let PartialComponents { - client, backend, .. - } = service::new_partial(&config)?; let db = backend.expose_db(); let storage = backend.expose_storage(); cmd.run(config, client, db, storage) } BenchmarkCmd::Overhead(cmd) => { - let PartialComponents { client, .. } = service::new_partial(&config)?; let ext_builder = RemarkBuilder::new(client.clone()); cmd.run( @@ -186,7 +201,6 @@ pub fn run() -> sc_cli::Result<()> { ) } BenchmarkCmd::Extrinsic(cmd) => { - let PartialComponents { client, .. } = service::new_partial(&config)?; // Register the *Remark* and *TKA* builders. let ext_factory = ExtrinsicFactory(vec![ Box::new(RemarkBuilder::new(client.clone())), @@ -213,18 +227,9 @@ pub fn run() -> sc_cli::Result<()> { let runner = cli.create_runner(&cli.run)?; runner.run_node_until_exit(|config| async move { let config = override_default_heap_pages(config, 60_000); - match config.network.network_backend { - sc_network::config::NetworkBackendType::Libp2p => service::new_full::< - sc_network::NetworkWorker< - node_subtensor_runtime::opaque::Block, - ::Hash, - >, - >(config) - .map_err(sc_cli::Error::Service), - sc_network::config::NetworkBackendType::Litep2p => - service::new_full::(config) - .map_err(sc_cli::Error::Service), - } + service::build_full(config, cli.eth, cli.sealing) + .map_err(Into::into) + .await }) } } diff --git a/node/src/ethereum.rs b/node/src/ethereum.rs new file mode 100644 index 000000000..337013a56 --- /dev/null +++ b/node/src/ethereum.rs @@ -0,0 +1,488 @@ +use crate::rpc::EthDeps; +use fc_rpc::{ + pending::AuraConsensusDataProvider, Debug, DebugApiServer, Eth, EthApiServer, EthConfig, + EthDevSigner, EthFilter, EthFilterApiServer, EthPubSub, EthPubSubApiServer, EthSigner, EthTask, + Net, NetApiServer, Web3, Web3ApiServer, +}; +use fp_rpc::{ConvertTransaction, ConvertTransactionRuntimeApi, EthereumRuntimeRPCApi}; +use futures::future; +use futures::StreamExt; +use jsonrpsee::RpcModule; +use sc_client_api::{ + backend::{Backend, StorageProvider}, + client::BlockchainEvents, + AuxStore, UsageProvider, +}; +use sc_executor::HostFunctions; +use sc_network_sync::SyncingService; +use sc_rpc::SubscriptionTaskExecutor; +use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; +use sc_transaction_pool::ChainApi; +use sc_transaction_pool_api::TransactionPool; +use sp_api::{CallApiAt, ConstructRuntimeApi, ProvideRuntimeApi}; +use sp_block_builder::BlockBuilder as BlockBuilderApi; +use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_consensus_aura::AuraApi; +use sp_core::H256; +use sp_inherents::CreateInherentDataProviders; +use sp_runtime::traits::Block as BlockT; +use std::path::PathBuf; +use std::time::Duration; +use std::{ + collections::BTreeMap, + sync::{Arc, Mutex}, +}; + +pub use fc_consensus::FrontierBlockImport; +pub use fc_rpc_core::types::{FeeHistoryCache, FeeHistoryCacheLimit, FilterPool}; +/// Frontier DB backend type. +pub use fc_storage::{StorageOverride, StorageOverrideHandler}; + +use crate::client::{FullBackend, FullClient}; + +pub type FrontierBackend = fc_db::Backend; + +/// Avalailable frontier backend types. +#[derive(Debug, Copy, Clone, Default, clap::ValueEnum)] +pub enum BackendType { + /// Either RocksDb or ParityDb as per inherited from the global backend settings. + #[default] + KeyValue, + /// Sql database with custom log indexing. + Sql, +} + +/// The ethereum-compatibility configuration used to run a node. +#[derive(Clone, Debug, clap::Parser)] +pub struct EthConfiguration { + /// Maximum number of logs in a query. + #[arg(long, default_value = "10000")] + pub max_past_logs: u32, + + /// Maximum fee history cache size. + #[arg(long, default_value = "2048")] + pub fee_history_limit: u64, + + #[arg(long)] + pub enable_dev_signer: bool, + + /// The dynamic-fee pallet target gas price set by block author + #[arg(long, default_value = "1")] + pub target_gas_price: u64, + + /// Maximum allowed gas limit will be `block.gas_limit * execute_gas_limit_multiplier` + /// when using eth_call/eth_estimateGas. + #[arg(long, default_value = "10")] + pub execute_gas_limit_multiplier: u64, + + /// Size in bytes of the LRU cache for block data. + #[arg(long, default_value = "50")] + pub eth_log_block_cache: usize, + + /// Size in bytes of the LRU cache for transactions statuses data. + #[arg(long, default_value = "50")] + pub eth_statuses_cache: usize, + + /// Sets the frontier backend type (KeyValue or Sql) + #[arg(long, value_enum, ignore_case = true, default_value_t = BackendType::default())] + pub frontier_backend_type: BackendType, + + // Sets the SQL backend's pool size. + #[arg(long, default_value = "100")] + pub frontier_sql_backend_pool_size: u32, + + /// Sets the SQL backend's query timeout in number of VM ops. + #[arg(long, default_value = "10000000")] + pub frontier_sql_backend_num_ops_timeout: u32, + + /// Sets the SQL backend's auxiliary thread limit. + #[arg(long, default_value = "4")] + pub frontier_sql_backend_thread_count: u32, + + /// Sets the SQL backend's query timeout in number of VM ops. + /// Default value is 200MB. + #[arg(long, default_value = "209715200")] + pub frontier_sql_backend_cache_size: u64, +} + +pub fn db_config_dir(config: &Configuration) -> PathBuf { + config.base_path.config_dir(config.chain_spec.id()) +} + +pub struct FrontierPartialComponents { + pub filter_pool: Option, + pub fee_history_cache: FeeHistoryCache, + pub fee_history_cache_limit: FeeHistoryCacheLimit, +} + +pub fn new_frontier_partial( + config: &EthConfiguration, +) -> Result { + Ok(FrontierPartialComponents { + filter_pool: Some(Arc::new(Mutex::new(BTreeMap::new()))), + fee_history_cache: Arc::new(Mutex::new(BTreeMap::new())), + fee_history_cache_limit: config.fee_history_limit, + }) +} + +/// A set of APIs that ethereum-compatible runtimes must implement. +pub trait EthCompatRuntimeApiCollection: + sp_api::ApiExt + + fp_rpc::ConvertTransactionRuntimeApi + + fp_rpc::EthereumRuntimeRPCApi +{ +} + +impl EthCompatRuntimeApiCollection for Api +where + Block: BlockT, + Api: sp_api::ApiExt + + fp_rpc::ConvertTransactionRuntimeApi + + fp_rpc::EthereumRuntimeRPCApi, +{ +} + +#[allow(clippy::too_many_arguments)] +pub async fn spawn_frontier_tasks( + task_manager: &TaskManager, + client: Arc>, + backend: Arc>, + frontier_backend: Arc>>, + filter_pool: Option, + storage_override: Arc>, + fee_history_cache: FeeHistoryCache, + fee_history_cache_limit: FeeHistoryCacheLimit, + sync: Arc>, + pubsub_notification_sinks: Arc< + fc_mapping_sync::EthereumBlockNotificationSinks< + fc_mapping_sync::EthereumBlockNotification, + >, + >, +) where + B: BlockT, + RA: ConstructRuntimeApi>, + RA: Send + Sync + 'static, + RA::RuntimeApi: EthCompatRuntimeApiCollection, + HF: HostFunctions + 'static, +{ + // Spawn main mapping sync worker background task. + match &*frontier_backend { + fc_db::Backend::KeyValue(b) => { + task_manager.spawn_essential_handle().spawn( + "frontier-mapping-sync-worker", + Some("frontier"), + fc_mapping_sync::kv::MappingSyncWorker::new( + client.import_notification_stream(), + Duration::new(6, 0), + client.clone(), + backend, + storage_override.clone(), + b.clone(), + 3, + 0u32.into(), + fc_mapping_sync::SyncStrategy::Normal, + sync, + pubsub_notification_sinks, + ) + .for_each(|()| future::ready(())), + ); + } + fc_db::Backend::Sql(b) => { + task_manager.spawn_essential_handle().spawn_blocking( + "frontier-mapping-sync-worker", + Some("frontier"), + fc_mapping_sync::sql::SyncWorker::run( + client.clone(), + backend, + b.clone(), + client.import_notification_stream(), + fc_mapping_sync::sql::SyncWorkerConfig { + read_notification_timeout: Duration::from_secs(30), + check_indexed_blocks_interval: Duration::from_secs(60), + }, + fc_mapping_sync::SyncStrategy::Parachain, + sync, + pubsub_notification_sinks, + ), + ); + } + } + + // Spawn Frontier EthFilterApi maintenance task. + if let Some(filter_pool) = filter_pool { + // Each filter is allowed to stay in the pool for 100 blocks. + const FILTER_RETAIN_THRESHOLD: u64 = 100; + task_manager.spawn_essential_handle().spawn( + "frontier-filter-pool", + Some("frontier"), + EthTask::filter_pool_task(client.clone(), filter_pool, FILTER_RETAIN_THRESHOLD), + ); + } + + // Spawn Frontier FeeHistory cache maintenance task. + task_manager.spawn_essential_handle().spawn( + "frontier-fee-history", + Some("frontier"), + EthTask::fee_history_task( + client, + storage_override, + fee_history_cache, + fee_history_cache_limit, + ), + ); +} + +fn extend_rpc_aet_api( + io: &mut RpcModule<()>, + deps: &EthDeps, +) -> Result<(), Box> +where + B: BlockT, + C: CallApiAt + ProvideRuntimeApi, + C::Api: AuraApi + + BlockBuilderApi + + ConvertTransactionRuntimeApi + + EthereumRuntimeRPCApi, + C: HeaderBackend + HeaderMetadata, + C: BlockchainEvents + AuxStore + UsageProvider + StorageProvider + 'static, + BE: Backend + 'static, + P: TransactionPool + 'static, + A: ChainApi + 'static, + CT: ConvertTransaction<::Extrinsic> + Send + Sync + Clone + 'static, + CIDP: CreateInherentDataProviders + Send + Clone + 'static, + EC: EthConfig, +{ + let mut signers = Vec::new(); + if deps.enable_dev_signer { + signers.push(Box::new(EthDevSigner::new()) as Box); + } + + io.merge( + Eth::::new( + deps.client.clone(), + deps.pool.clone(), + deps.graph.clone(), + deps.converter.clone(), + deps.sync.clone(), + signers, + deps.storage_override.clone(), + deps.frontier_backend.clone(), + deps.is_authority, + deps.block_data_cache.clone(), + deps.fee_history_cache.clone(), + deps.fee_history_cache_limit, + deps.execute_gas_limit_multiplier, + deps.forced_parent_hashes.clone(), + deps.pending_create_inherent_data_providers.clone(), + Some(Box::new(AuraConsensusDataProvider::new( + deps.client.clone(), + ))), + ) + .replace_config::() + .into_rpc(), + )?; + Ok(()) +} + +fn extend_rpc_eth_filter( + io: &mut RpcModule<()>, + deps: &EthDeps, +) -> Result<(), Box> +where + B: BlockT, + C: CallApiAt + ProvideRuntimeApi, + C::Api: AuraApi + + BlockBuilderApi + + ConvertTransactionRuntimeApi + + EthereumRuntimeRPCApi, + C: HeaderBackend + HeaderMetadata, + C: BlockchainEvents + AuxStore + UsageProvider + StorageProvider + 'static, + BE: Backend + 'static, + P: TransactionPool + 'static, + A: ChainApi + 'static, + CT: ConvertTransaction<::Extrinsic> + Send + Sync + Clone + 'static, + CIDP: CreateInherentDataProviders + Send + Clone + 'static, +{ + if let Some(filter_pool) = deps.filter_pool.clone() { + io.merge( + EthFilter::new( + deps.client.clone(), + deps.frontier_backend.clone(), + deps.graph.clone(), + filter_pool, + 500_usize, // max stored filters + deps.max_past_logs, + deps.block_data_cache.clone(), + ) + .into_rpc(), + )?; + } + Ok(()) +} + +// Function for EthPubSub merge +fn extend_rpc_eth_pubsub( + io: &mut RpcModule<()>, + deps: &EthDeps, + subscription_task_executor: SubscriptionTaskExecutor, + pubsub_notification_sinks: Arc< + fc_mapping_sync::EthereumBlockNotificationSinks< + fc_mapping_sync::EthereumBlockNotification, + >, + >, +) -> Result<(), Box> +where + B: BlockT, + C: CallApiAt + ProvideRuntimeApi, + C::Api: AuraApi + + BlockBuilderApi + + ConvertTransactionRuntimeApi + + EthereumRuntimeRPCApi, + C: HeaderBackend + HeaderMetadata, + C: BlockchainEvents + AuxStore + UsageProvider + StorageProvider + 'static, + BE: Backend + 'static, + P: TransactionPool + 'static, + A: ChainApi + 'static, + CT: ConvertTransaction<::Extrinsic> + Send + Sync + 'static, + CIDP: CreateInherentDataProviders + Send + 'static, +{ + io.merge( + EthPubSub::new( + deps.pool.clone(), + deps.client.clone(), + deps.sync.clone(), + subscription_task_executor, + deps.storage_override.clone(), + pubsub_notification_sinks, + ) + .into_rpc(), + )?; + Ok(()) +} + +fn extend_rpc_net( + io: &mut RpcModule<()>, + deps: &EthDeps, +) -> Result<(), Box> +where + B: BlockT, + C: CallApiAt + ProvideRuntimeApi, + C::Api: AuraApi + + BlockBuilderApi + + ConvertTransactionRuntimeApi + + EthereumRuntimeRPCApi, + C: HeaderBackend + HeaderMetadata, + C: BlockchainEvents + AuxStore + UsageProvider + StorageProvider + 'static, + BE: Backend + 'static, + P: TransactionPool + 'static, + A: ChainApi + 'static, + CT: ConvertTransaction<::Extrinsic> + Send + Sync + 'static, + CIDP: CreateInherentDataProviders + Send + 'static, +{ + io.merge( + Net::new( + deps.client.clone(), + deps.network.clone(), + true, // Whether to format the `peer_count` response as Hex (default) or not. + ) + .into_rpc(), + )?; + Ok(()) +} + +fn extend_rpc_web3( + io: &mut RpcModule<()>, + deps: &EthDeps, +) -> Result<(), Box> +where + B: BlockT, + C: CallApiAt + ProvideRuntimeApi, + C::Api: AuraApi + + BlockBuilderApi + + ConvertTransactionRuntimeApi + + EthereumRuntimeRPCApi, + C: HeaderBackend + HeaderMetadata, + C: BlockchainEvents + AuxStore + UsageProvider + StorageProvider + 'static, + BE: Backend + 'static, + P: TransactionPool + 'static, + A: ChainApi + 'static, + CT: ConvertTransaction<::Extrinsic> + Send + Sync + 'static, + CIDP: CreateInherentDataProviders + Send + 'static, +{ + io.merge(Web3::new(deps.client.clone()).into_rpc())?; + Ok(()) +} + +fn extend_rpc_debug( + io: &mut RpcModule<()>, + deps: &EthDeps, +) -> Result<(), Box> +where + B: BlockT, + C: CallApiAt + ProvideRuntimeApi, + C::Api: AuraApi + + BlockBuilderApi + + ConvertTransactionRuntimeApi + + EthereumRuntimeRPCApi, + C: HeaderBackend + HeaderMetadata, + C: BlockchainEvents + AuxStore + UsageProvider + StorageProvider + 'static, + BE: Backend + 'static, + P: TransactionPool + 'static, + A: ChainApi + 'static, + CT: ConvertTransaction<::Extrinsic> + Send + Sync + 'static, + CIDP: CreateInherentDataProviders + Send + 'static, +{ + io.merge( + Debug::new( + deps.client.clone(), + deps.frontier_backend.clone(), + deps.storage_override.clone(), + deps.block_data_cache.clone(), + ) + .into_rpc(), + )?; + Ok(()) +} + +/// Extend RpcModule with Eth RPCs +pub fn create_eth( + mut io: RpcModule<()>, + deps: EthDeps, + subscription_task_executor: SubscriptionTaskExecutor, + pubsub_notification_sinks: Arc< + fc_mapping_sync::EthereumBlockNotificationSinks< + fc_mapping_sync::EthereumBlockNotification, + >, + >, +) -> Result, Box> +where + B: BlockT, + C: CallApiAt + ProvideRuntimeApi, + C::Api: AuraApi + + BlockBuilderApi + + ConvertTransactionRuntimeApi + + EthereumRuntimeRPCApi, + C: HeaderBackend + HeaderMetadata, + C: BlockchainEvents + AuxStore + UsageProvider + StorageProvider + 'static, + BE: Backend + 'static, + P: TransactionPool + 'static, + A: ChainApi + 'static, + CT: ConvertTransaction<::Extrinsic> + Send + Sync + Clone + 'static, + CIDP: CreateInherentDataProviders + Send + Clone + 'static, + EC: EthConfig, +{ + extend_rpc_aet_api::(&mut io, &deps)?; + extend_rpc_eth_filter::(&mut io, &deps)?; + extend_rpc_eth_pubsub::( + &mut io, + &deps, + subscription_task_executor, + pubsub_notification_sinks, + )?; + extend_rpc_net::(&mut io, &deps)?; + extend_rpc_web3::(&mut io, &deps)?; + extend_rpc_debug::(&mut io, &deps)?; + + Ok(io) +} diff --git a/node/src/lib.rs b/node/src/lib.rs index f117b8aae..81cae5145 100644 --- a/node/src/lib.rs +++ b/node/src/lib.rs @@ -1,3 +1,6 @@ pub mod chain_spec; +pub mod cli; +pub mod client; +pub mod ethereum; pub mod rpc; pub mod service; diff --git a/node/src/main.rs b/node/src/main.rs index a79d48b1b..bb8cd8e8b 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -7,7 +7,9 @@ mod service; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; mod cli; +mod client; mod command; +mod ethereum; mod rpc; fn main() -> sc_cli::Result<()> { diff --git a/node/src/rpc.rs b/node/src/rpc.rs index 7563bf834..4f2063215 100644 --- a/node/src/rpc.rs +++ b/node/src/rpc.rs @@ -5,62 +5,125 @@ #![warn(missing_docs)] -use std::sync::Arc; +use std::{collections::BTreeMap, sync::Arc}; +use futures::channel::mpsc; + +use crate::{client::RuntimeApiCollection, ethereum::create_eth}; +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::{opaque::Block, AccountId, Balance, BlockNumber, Hash, Index}; -use sc_consensus_grandpa::FinalityProofProvider; +use node_subtensor_runtime::{AccountId, Balance, Hash, Nonce}; +use sc_client_api::{ + backend::{Backend, StorageProvider}, + client::BlockchainEvents, + AuxStore, UsageProvider, +}; +use sc_consensus_manual_seal::EngineCommand; +use sc_network::service::traits::NetworkService; +use sc_network_sync::SyncingService; +use sc_rpc::SubscriptionTaskExecutor; +use sc_transaction_pool::{ChainApi, Pool}; use sc_transaction_pool_api::TransactionPool; -use sp_api::ProvideRuntimeApi; -use sp_block_builder::BlockBuilder; +use sp_api::{CallApiAt, ProvideRuntimeApi}; use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_core::H256; +use sp_inherents::CreateInherentDataProviders; +use sp_runtime::traits::Block as BlockT; -/// Dependencies for GRANDPA -pub struct GrandpaDeps { - /// Voting round info. - pub shared_voter_state: sc_consensus_grandpa::SharedVoterState, - /// Authority set info. - pub shared_authority_set: sc_consensus_grandpa::SharedAuthoritySet, - /// Receives notifications about justification events from Grandpa. - pub justification_stream: sc_consensus_grandpa::GrandpaJustificationStream, - /// Executor to drive the subscription manager in the Grandpa RPC handler. - pub subscription_executor: sc_rpc::SubscriptionTaskExecutor, - /// Finality proof provider. - pub finality_provider: Arc>, +/// Extra dependencies for Ethereum compatibility. +pub struct EthDeps { + /// The client instance to use. + pub client: Arc, + /// Transaction pool instance. + pub pool: Arc

, + /// Graph pool instance. + pub graph: Arc>, + /// Ethereum transaction converter. + pub converter: Option, + /// The Node authority flag + pub is_authority: bool, + /// Whether to enable dev signer + pub enable_dev_signer: bool, + /// Network service + pub network: Arc, + /// Chain syncing service + pub sync: Arc>, + /// Frontier Backend. + pub frontier_backend: Arc>, + /// Ethereum data access overrides. + pub storage_override: Arc>, + /// Cache for Ethereum block data. + pub block_data_cache: Arc>, + /// EthFilterApi pool. + pub filter_pool: Option, + /// Maximum number of logs in a query. + pub max_past_logs: u32, + /// Fee history cache. + pub fee_history_cache: FeeHistoryCache, + /// Maximum fee history cache size. + pub fee_history_cache_limit: FeeHistoryCacheLimit, + /// Maximum allowed gas limit will be ` block.gas_limit * execute_gas_limit_multiplier` when + /// using eth_call/eth_estimateGas. + pub execute_gas_limit_multiplier: u64, + /// Mandated parent hashes for a given block hash. + pub forced_parent_hashes: Option>, + /// Something that can create the inherent data providers for pending state + pub pending_create_inherent_data_providers: CIDP, +} + +/// Default Eth RPC configuration +pub struct DefaultEthConfig(std::marker::PhantomData<(C, BE)>); + +impl fc_rpc::EthConfig for DefaultEthConfig +where + B: BlockT, + C: StorageProvider + Sync + Send + 'static, + BE: Backend + 'static, +{ + type EstimateGasAdapter = (); + type RuntimeStorageOverride = + fc_rpc::frontier_backend_client::SystemAccountId20StorageOverride; } /// Full client dependencies. -pub struct FullDeps { +pub struct FullDeps { /// The client instance to use. pub client: Arc, /// Transaction pool instance. pub pool: Arc

, - /// Grandpa block import setup. - pub grandpa: GrandpaDeps, - /// Backend used by the node. - pub _backend: Arc, + /// Manual seal command sink + pub command_sink: Option>>, + /// Ethereum-compatibility specific dependencies. + pub eth: EthDeps, } /// Instantiate all full RPC extensions. -pub fn create_full( - deps: FullDeps, +pub fn create_full( + deps: FullDeps, + subscription_task_executor: SubscriptionTaskExecutor, + pubsub_notification_sinks: Arc< + fc_mapping_sync::EthereumBlockNotificationSinks< + fc_mapping_sync::EthereumBlockNotification, + >, + >, ) -> Result, Box> where - C: ProvideRuntimeApi, - C: HeaderBackend + HeaderMetadata + 'static, - C: Send + Sync + 'static, - C::Api: substrate_frame_rpc_system::AccountNonceApi, - C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, - C::Api: BlockBuilder, - C::Api: subtensor_custom_rpc_runtime_api::DelegateInfoRuntimeApi, - C::Api: subtensor_custom_rpc_runtime_api::NeuronInfoRuntimeApi, - C::Api: subtensor_custom_rpc_runtime_api::SubnetInfoRuntimeApi, - C::Api: subtensor_custom_rpc_runtime_api::SubnetRegistrationRuntimeApi, - B: sc_client_api::Backend + Send + Sync + 'static, - P: TransactionPool + 'static, + B: BlockT, + C: CallApiAt + ProvideRuntimeApi, + C::Api: RuntimeApiCollection, + C: HeaderBackend + HeaderMetadata + 'static, + C: BlockchainEvents + AuxStore + UsageProvider + StorageProvider, + BE: Backend + 'static, + P: TransactionPool + 'static, + A: ChainApi + 'static, + CIDP: CreateInherentDataProviders + Send + Clone + 'static, + CT: fp_rpc::ConvertTransaction<::Extrinsic> + Send + Sync + Clone + 'static, { use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; - use sc_consensus_grandpa_rpc::{Grandpa, GrandpaApiServer}; + use sc_consensus_manual_seal::rpc::{ManualSeal, ManualSealApiServer}; use substrate_frame_rpc_system::{System, SystemApiServer}; use subtensor_custom_rpc::{SubtensorCustom, SubtensorCustomApiServer}; @@ -68,8 +131,8 @@ where let FullDeps { client, pool, - grandpa, - _backend: _, + command_sink, + eth, } = deps; // Custom RPC methods for Paratensor @@ -78,29 +141,26 @@ where module.merge(System::new(client.clone(), pool.clone()).into_rpc())?; module.merge(TransactionPayment::new(client).into_rpc())?; - let GrandpaDeps { - shared_voter_state, - shared_authority_set, - justification_stream, - subscription_executor, - finality_provider, - } = grandpa; - - module.merge( - Grandpa::new( - subscription_executor, - shared_authority_set.clone(), - shared_voter_state, - justification_stream, - finality_provider, - ) - .into_rpc(), - )?; - // Extend this RPC with a custom API by using the following syntax. // `YourRpcStruct` should have a reference to a client, which is needed // to call into the runtime. // `module.merge(YourRpcTrait::into_rpc(YourRpcStruct::new(ReferenceToClient, ...)))?;` + if let Some(command_sink) = command_sink { + module.merge( + // We provide the rpc handler with the sending end of the channel to allow the rpc + // send EngineCommands to the background block authorship task. + ManualSeal::new(command_sink).into_rpc(), + )?; + } + + // Ethereum compatibility RPCs + let module = create_eth::<_, _, _, _, _, _, _, DefaultEthConfig>( + module, + eth, + subscription_task_executor, + pubsub_notification_sinks, + )?; + Ok(module) } diff --git a/node/src/service.rs b/node/src/service.rs index cc0bf2862..fef86dee6 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -1,49 +1,94 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. -use futures::FutureExt; -use node_subtensor_runtime::{opaque::Block, RuntimeApi}; -use sc_client_api::{Backend, BlockBackend}; -use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; -use sc_consensus_grandpa::SharedVoterState; +use crate::cli::Sealing; +use crate::client::{FullBackend, FullClient, RuntimeApiCollection}; +use crate::ethereum::{ + db_config_dir, new_frontier_partial, spawn_frontier_tasks, BackendType, EthConfiguration, + FrontierBackend, FrontierBlockImport, FrontierPartialComponents, StorageOverride, + StorageOverrideHandler, +}; +use futures::{channel::mpsc, future, FutureExt}; +use sc_client_api::{Backend as BackendT, BlockBackend}; +use sc_consensus::{BasicQueue, BoxBlockImport}; +use sc_consensus_grandpa::BlockNumberOps; use sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging; -pub use sc_executor::WasmExecutor; -use sc_service::{error::Error as ServiceError, Configuration, TaskManager, WarpSyncConfig}; -use sc_telemetry::{Telemetry, TelemetryWorker}; +use sc_executor::HostFunctions as HostFunctionsT; +use sc_network_sync::strategy::warp::{WarpSyncConfig, WarpSyncProvider}; +use sc_service::{error::Error as ServiceError, Configuration, PartialComponents, TaskManager}; +use sc_telemetry::{log, Telemetry, TelemetryHandle, TelemetryWorker}; +use sc_transaction_pool::FullPool; use sc_transaction_pool_api::OffchainTransactionPoolFactory; -use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; +use sp_api::ConstructRuntimeApi; +use sp_consensus_aura::sr25519::{AuthorityId as AuraId, AuthorityPair as AuraPair}; +use sp_core::{H256, U256}; +use sp_runtime::traits::{Block as BlockT, NumberFor}; +use std::{cell::RefCell, path::Path}; use std::{sync::Arc, time::Duration}; +use substrate_prometheus_endpoint::Registry; + +// Runtime +use node_subtensor_runtime::{ + opaque::Block, AccountId, Balance, Nonce, RuntimeApi, TransactionConverter, +}; /// The minimum period of blocks on which justifications will be /// imported and generated. const GRANDPA_JUSTIFICATION_PERIOD: u32 = 512; -pub(crate) type FullClient = - sc_service::TFullClient>; -type FullBackend = sc_service::TFullBackend; -type FullSelectChain = sc_consensus::LongestChain; - -pub fn new_partial( +/// Only enable the benchmarking host functions when we actually want to benchmark. +#[cfg(feature = "runtime-benchmarks")] +pub type HostFunctions = ( + sp_io::SubstrateHostFunctions, + frame_benchmarking::benchmarking::HostFunctions, +); +/// Otherwise we use empty host functions for ext host functions. +#[cfg(not(feature = "runtime-benchmarks"))] +pub type HostFunctions = sp_io::SubstrateHostFunctions; + +pub type Backend = FullBackend; +pub type Client = FullClient; + +type FullSelectChain = sc_consensus::LongestChain, B>; +type GrandpaBlockImport = + sc_consensus_grandpa::GrandpaBlockImport, B, C, FullSelectChain>; +type GrandpaLinkHalf = sc_consensus_grandpa::LinkHalf>; + +pub fn new_partial( config: &Configuration, + eth_config: &EthConfiguration, + build_import_queue: BIQ, ) -> Result< - sc_service::PartialComponents< - FullClient, - FullBackend, - FullSelectChain, - sc_consensus::DefaultImportQueue, - sc_transaction_pool::FullPool, + PartialComponents< + FullClient, + FullBackend, + FullSelectChain, + BasicQueue, + FullPool>, ( - sc_consensus_grandpa::GrandpaBlockImport< - FullBackend, - Block, - FullClient, - FullSelectChain, - >, - sc_consensus_grandpa::LinkHalf, Option, + BoxBlockImport, + GrandpaLinkHalf>, + FrontierBackend>, + Arc>, ), >, ServiceError, -> { +> +where + B: BlockT, + RA: ConstructRuntimeApi>, + RA: Send + Sync + 'static, + RA::RuntimeApi: RuntimeApiCollection, + HF: HostFunctionsT + 'static, + BIQ: FnOnce( + Arc>, + &Configuration, + &EthConfiguration, + &TaskManager, + Option, + GrandpaBlockImport>, + ) -> Result<(BasicQueue, BoxBlockImport), ServiceError>, +{ let telemetry = config .telemetry_endpoints .clone() @@ -55,14 +100,13 @@ pub fn new_partial( }) .transpose()?; - let executor = sc_service::new_wasm_executor::(&config.executor); + let executor = sc_service::new_wasm_executor(&config.executor); - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; + let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; let client = Arc::new(client); let telemetry = telemetry.map(|(worker, telemetry)| { @@ -73,67 +117,180 @@ pub fn new_partial( }); let select_chain = sc_consensus::LongestChain::new(backend.clone()); - - let transaction_pool = sc_transaction_pool::BasicPool::new_full( - config.transaction_pool.clone(), - config.role.is_authority().into(), - config.prometheus_registry(), - task_manager.spawn_essential_handle(), - client.clone(), - ); - let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import( client.clone(), GRANDPA_JUSTIFICATION_PERIOD, - &(client.clone() as Arc<_>), + &client, select_chain.clone(), telemetry.as_ref().map(|x| x.handle()), )?; - let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - - let import_queue = - sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: grandpa_block_import.clone(), - justification_import: Some(Box::new(grandpa_block_import.clone())), - client: client.clone(), - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + let storage_override = Arc::new(StorageOverrideHandler::::new(client.clone())); + let frontier_backend = match eth_config.frontier_backend_type { + BackendType::KeyValue => FrontierBackend::KeyValue(Arc::new(fc_db::kv::Backend::open( + Arc::clone(&client), + &config.database, + &db_config_dir(config), + )?)), + BackendType::Sql => { + let db_path = db_config_dir(config).join("sql"); + std::fs::create_dir_all(&db_path).expect("failed creating sql db directory"); + let backend = futures::executor::block_on(fc_db::sql::Backend::new( + fc_db::sql::BackendConfig::Sqlite(fc_db::sql::SqliteBackendConfig { + path: Path::new("sqlite:///") + .join(db_path) + .join("frontier.db3") + .to_str() + .unwrap_or(""), + create_if_missing: true, + thread_count: eth_config.frontier_sql_backend_thread_count, + cache_size: eth_config.frontier_sql_backend_cache_size, + }), + eth_config.frontier_sql_backend_pool_size, + std::num::NonZeroU32::new(eth_config.frontier_sql_backend_num_ops_timeout), + storage_override.clone(), + )) + .unwrap_or_else(|err| panic!("failed creating sql backend: {:?}", err)); + FrontierBackend::Sql(Arc::new(backend)) + } + }; - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); + let (import_queue, block_import) = build_import_queue( + client.clone(), + config, + eth_config, + &task_manager, + telemetry.as_ref().map(|x| x.handle()), + grandpa_block_import, + )?; - Ok((slot, timestamp)) - }, - spawner: &task_manager.spawn_essential_handle(), - registry: config.prometheus_registry(), - check_for_equivocation: Default::default(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - compatibility_mode: Default::default(), - })?; + let transaction_pool = sc_transaction_pool::BasicPool::new_full( + config.transaction_pool.clone(), + config.role.is_authority().into(), + config.prometheus_registry(), + task_manager.spawn_essential_handle(), + client.clone(), + ); - Ok(sc_service::PartialComponents { + Ok(PartialComponents { client, backend, - task_manager, - import_queue, keystore_container, + task_manager, select_chain, + import_queue, transaction_pool, - other: (grandpa_block_import, grandpa_link, telemetry), + other: ( + telemetry, + block_import, + grandpa_link, + frontier_backend, + storage_override, + ), }) } -// Builds a new service for a full client. -pub fn new_full< - N: sc_network::NetworkBackend::Hash>, ->( - config: Configuration, -) -> Result { - let sc_service::PartialComponents { +/// Build the import queue for the template runtime (aura + grandpa). +pub fn build_aura_grandpa_import_queue( + client: Arc>, + config: &Configuration, + eth_config: &EthConfiguration, + task_manager: &TaskManager, + telemetry: Option, + grandpa_block_import: GrandpaBlockImport>, +) -> Result<(BasicQueue, BoxBlockImport), ServiceError> +where + B: BlockT, + NumberFor: BlockNumberOps, + RA: ConstructRuntimeApi>, + RA: Send + Sync + 'static, + RA::RuntimeApi: RuntimeApiCollection, + HF: HostFunctionsT + 'static, +{ + let frontier_block_import = + FrontierBlockImport::new(grandpa_block_import.clone(), client.clone()); + + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; + let target_gas_price = eth_config.target_gas_price; + let create_inherent_data_providers = move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + let dynamic_fee = fp_dynamic_fee::InherentDataProvider(U256::from(target_gas_price)); + Ok((slot, timestamp, dynamic_fee)) + }; + + let import_queue = sc_consensus_aura::import_queue::( + sc_consensus_aura::ImportQueueParams { + block_import: frontier_block_import.clone(), + justification_import: Some(Box::new(grandpa_block_import)), + client, + create_inherent_data_providers, + spawner: &task_manager.spawn_essential_handle(), + registry: config.prometheus_registry(), + check_for_equivocation: Default::default(), + telemetry, + compatibility_mode: sc_consensus_aura::CompatibilityMode::None, + }, + ) + .map_err::(Into::into)?; + + Ok((import_queue, Box::new(frontier_block_import))) +} + +/// Build the import queue for the template runtime (manual seal). +pub fn build_manual_seal_import_queue( + client: Arc>, + config: &Configuration, + _eth_config: &EthConfiguration, + task_manager: &TaskManager, + _telemetry: Option, + _grandpa_block_import: GrandpaBlockImport>, +) -> Result<(BasicQueue, BoxBlockImport), ServiceError> +where + B: BlockT, + RA: ConstructRuntimeApi>, + RA: Send + Sync + 'static, + RA::RuntimeApi: RuntimeApiCollection, + HF: HostFunctionsT + 'static, +{ + let frontier_block_import = FrontierBlockImport::new(client.clone(), client); + Ok(( + sc_consensus_manual_seal::import_queue( + Box::new(frontier_block_import.clone()), + &task_manager.spawn_essential_handle(), + config.prometheus_registry(), + ), + Box::new(frontier_block_import), + )) +} + +/// Builds a new service for a full client. +pub async fn new_full( + mut config: Configuration, + eth_config: EthConfiguration, + sealing: Option, +) -> Result +where + B: BlockT, + NumberFor: BlockNumberOps, + ::Header: Unpin, + RA: ConstructRuntimeApi>, + RA: Send + Sync + 'static, + RA::RuntimeApi: RuntimeApiCollection, + HF: HostFunctionsT + 'static, + NB: sc_network::NetworkBackend::Hash>, +{ + let build_import_queue = if sealing.is_some() { + build_manual_seal_import_queue:: + } else { + build_aura_grandpa_import_queue:: + }; + + let PartialComponents { client, backend, mut task_manager, @@ -141,39 +298,49 @@ pub fn new_full< keystore_container, select_chain, transaction_pool, - other: (block_import, grandpa_link, mut telemetry), - } = new_partial(&config)?; - - let mut net_config = sc_network::config::FullNetworkConfiguration::< - Block, - ::Hash, - N, - >::new(&config.network, config.prometheus_registry().cloned()); - let metrics = N::register_notification_metrics(config.prometheus_registry()); + other: (mut telemetry, block_import, grandpa_link, frontier_backend, storage_override), + } = new_partial(&config, ð_config, build_import_queue)?; + + let FrontierPartialComponents { + filter_pool, + fee_history_cache, + fee_history_cache_limit, + } = new_frontier_partial(ð_config)?; + + let maybe_registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); + let mut net_config = sc_network::config::FullNetworkConfiguration::<_, _, NB>::new( + &config.network, + maybe_registry.cloned(), + ); + let peer_store_handle = net_config.peer_store_handle(); + let metrics = NB::register_notification_metrics(maybe_registry); let grandpa_protocol_name = sc_consensus_grandpa::protocol_standard_name( &client - .block_hash(0) - .ok() - .flatten() + .block_hash(0u32.into())? .expect("Genesis block exists; qed"), &config.chain_spec, ); - let peer_store_handle = net_config.peer_store_handle(); let (grandpa_protocol_config, grandpa_notification_service) = - sc_consensus_grandpa::grandpa_peers_set_config::<_, N>( + sc_consensus_grandpa::grandpa_peers_set_config::<_, NB>( grandpa_protocol_name.clone(), metrics.clone(), peer_store_handle, ); - net_config.add_notification_protocol(grandpa_protocol_config); - let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new( - backend.clone(), - grandpa_link.shared_authority_set().clone(), - Vec::default(), - )); + let warp_sync_config = if sealing.is_some() { + None + } else { + net_config.add_notification_protocol(grandpa_protocol_config); + let warp_sync: Arc> = + Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new( + backend.clone(), + grandpa_link.shared_authority_set().clone(), + Vec::new(), + )); + Some(WarpSyncConfig::WithProvider(warp_sync)) + }; let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) = sc_service::build_network(sc_service::BuildNetworkParams { @@ -184,7 +351,7 @@ pub fn new_full< spawn_handle: task_manager.spawn_handle(), import_queue, block_announce_validator_builder: None, - warp_sync_config: Some(WarpSyncConfig::WithProvider(warp_sync)), + warp_sync_config, block_relay: None, metrics, })?; @@ -210,64 +377,165 @@ pub fn new_full< ); } - let finality_proof_provider = sc_consensus_grandpa::FinalityProofProvider::new_for_service( - backend.clone(), - Some(grandpa_link.shared_authority_set().clone()), - ); - let rpc_backend = backend.clone(); - let justification_stream = grandpa_link.justification_stream(); - let shared_authority_set = grandpa_link.shared_authority_set().clone(); - let shared_voter_state = SharedVoterState::empty(); - let role = config.role; let force_authoring = config.force_authoring; - let backoff_authoring_blocks = Some(BackoffAuthoringOnFinalizedHeadLagging { - unfinalized_slack: 6, + let backoff_authoring_blocks = Some(BackoffAuthoringOnFinalizedHeadLagging::> { + unfinalized_slack: 6u32.into(), ..Default::default() }); let name = config.network.node_name.clone(); - let enable_grandpa = !config.disable_grandpa; + let frontier_backend = Arc::new(frontier_backend); + let enable_grandpa = !config.disable_grandpa && sealing.is_none(); let prometheus_registry = config.prometheus_registry().cloned(); - let rpc_extensions_builder = { + // Channel for the rpc handler to communicate with the authorship task. + let (command_sink, commands_stream) = mpsc::channel(1000); + + // Sinks for pubsub notifications. + // Everytime a new subscription is created, a new mpsc channel is added to the sink pool. + // The MappingSyncWorker sends through the channel on block import and the subscription emits a notification to the subscriber on receiving a message through this channel. + // This way we avoid race conditions when using native substrate block import notification stream. + let pubsub_notification_sinks: fc_mapping_sync::EthereumBlockNotificationSinks< + fc_mapping_sync::EthereumBlockNotification, + > = Default::default(); + let pubsub_notification_sinks = Arc::new(pubsub_notification_sinks); + + // for ethereum-compatibility rpc. + config.rpc.id_provider = Some(Box::new(fc_rpc::EthereumSubIdProvider)); + + let rpc_builder = { let client = client.clone(); let pool = transaction_pool.clone(); + let network = network.clone(); + let sync_service = sync_service.clone(); + + let is_authority = role.is_authority(); + let enable_dev_signer = eth_config.enable_dev_signer; + let max_past_logs = eth_config.max_past_logs; + let execute_gas_limit_multiplier = eth_config.execute_gas_limit_multiplier; + let filter_pool = filter_pool.clone(); + let frontier_backend = frontier_backend.clone(); + let pubsub_notification_sinks = pubsub_notification_sinks.clone(); + let storage_override = storage_override.clone(); + let fee_history_cache = fee_history_cache.clone(); + let block_data_cache = Arc::new(fc_rpc::EthBlockDataCacheTask::new( + task_manager.spawn_handle(), + storage_override.clone(), + eth_config.eth_log_block_cache, + eth_config.eth_statuses_cache, + prometheus_registry.clone(), + )); - Box::new( - move |subscription_executor: sc_rpc::SubscriptionTaskExecutor| { - let deps = crate::rpc::FullDeps { - client: client.clone(), - pool: pool.clone(), - grandpa: crate::rpc::GrandpaDeps { - shared_voter_state: shared_voter_state.clone(), - shared_authority_set: shared_authority_set.clone(), - justification_stream: justification_stream.clone(), - subscription_executor: subscription_executor.clone(), - finality_provider: finality_proof_provider.clone(), - }, - _backend: rpc_backend.clone(), - }; - crate::rpc::create_full(deps).map_err(Into::into) - }, - ) + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; + let target_gas_price = eth_config.target_gas_price; + let pending_create_inherent_data_providers = move |_, ()| async move { + let current = sp_timestamp::InherentDataProvider::from_system_time(); + let next_slot = current + .timestamp() + .as_millis() + .saturating_add(slot_duration.as_millis()); + let timestamp = sp_timestamp::InherentDataProvider::new(next_slot.into()); + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + let dynamic_fee = fp_dynamic_fee::InherentDataProvider(U256::from(target_gas_price)); + Ok((slot, timestamp, dynamic_fee)) + }; + + Box::new(move |subscription_task_executor| { + let eth_deps = crate::rpc::EthDeps { + client: client.clone(), + pool: pool.clone(), + graph: pool.pool().clone(), + converter: Some(TransactionConverter::::default()), + is_authority, + enable_dev_signer, + network: network.clone(), + sync: sync_service.clone(), + frontier_backend: match &*frontier_backend { + fc_db::Backend::KeyValue(b) => b.clone(), + fc_db::Backend::Sql(b) => b.clone(), + }, + storage_override: storage_override.clone(), + block_data_cache: block_data_cache.clone(), + filter_pool: filter_pool.clone(), + max_past_logs, + fee_history_cache: fee_history_cache.clone(), + fee_history_cache_limit, + execute_gas_limit_multiplier, + forced_parent_hashes: None, + pending_create_inherent_data_providers, + }; + let deps = crate::rpc::FullDeps { + client: client.clone(), + pool: pool.clone(), + command_sink: if sealing.is_some() { + Some(command_sink.clone()) + } else { + None + }, + eth: eth_deps, + }; + crate::rpc::create_full( + deps, + subscription_task_executor, + pubsub_notification_sinks.clone(), + ) + .map_err(Into::into) + }) }; let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { - network: network.clone(), + config, client: client.clone(), - keystore: keystore_container.keystore(), + backend: backend.clone(), task_manager: &mut task_manager, + keystore: keystore_container.keystore(), transaction_pool: transaction_pool.clone(), - rpc_builder: rpc_extensions_builder, - backend, + rpc_builder, + network: network.clone(), system_rpc_tx, tx_handler_controller, sync_service: sync_service.clone(), - config, telemetry: telemetry.as_mut(), })?; + spawn_frontier_tasks( + &task_manager, + client.clone(), + backend, + frontier_backend, + filter_pool, + storage_override, + fee_history_cache, + fee_history_cache_limit, + sync_service.clone(), + pubsub_notification_sinks, + ) + .await; + if role.is_authority() { + // manual-seal authorship + if let Some(sealing) = sealing { + run_manual_seal_authorship( + ð_config, + sealing, + client, + transaction_pool, + select_chain, + block_import, + &task_manager, + prometheus_registry.as_ref(), + telemetry.as_ref(), + commands_stream, + )?; + + network_starter.start_network(); + log::info!("Manual Seal Ready"); + return Ok(task_manager); + } + let proposer_factory = sc_basic_authorship::ProposerFactory::new( task_manager.spawn_handle(), client.clone(), @@ -277,37 +545,36 @@ pub fn new_full< ); let slot_duration = sc_consensus_aura::slot_duration(&*client)?; + let target_gas_price = eth_config.target_gas_price; + let create_inherent_data_providers = move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + let dynamic_fee = fp_dynamic_fee::InherentDataProvider(U256::from(target_gas_price)); + Ok((slot, timestamp, dynamic_fee)) + }; let aura = sc_consensus_aura::start_aura::( - StartAuraParams { + sc_consensus_aura::StartAuraParams { slot_duration, client, select_chain, block_import, proposer_factory, - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - - Ok((slot, timestamp)) - }, + sync_oracle: sync_service.clone(), + justification_sync_link: sync_service.clone(), + create_inherent_data_providers, force_authoring, backoff_authoring_blocks, keystore: keystore_container.keystore(), - sync_oracle: sync_service.clone(), - justification_sync_link: sync_service.clone(), - block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), + block_proposal_slot_portion: sc_consensus_aura::SlotProportion::new(2f32 / 3f32), max_block_proposal_slot_portion: None, telemetry: telemetry.as_ref().map(|x| x.handle()), - compatibility_mode: Default::default(), + compatibility_mode: sc_consensus_aura::CompatibilityMode::None, }, )?; - // the AURA authoring task is considered essential, i.e. if it // fails we take down the service with it. task_manager @@ -342,28 +609,176 @@ pub fn new_full< // and vote data availability than the observer. The observer has not // been tested extensively yet and having most nodes in a network run it // could lead to finality stalls. - let grandpa_config = sc_consensus_grandpa::GrandpaParams { - config: grandpa_config, - link: grandpa_link, - network, - voting_rule: sc_consensus_grandpa::VotingRulesBuilder::default().build(), - prometheus_registry, - shared_voter_state: SharedVoterState::empty(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(transaction_pool), - sync: Arc::new(sync_service), - notification_service: grandpa_notification_service, - }; + let grandpa_voter = + sc_consensus_grandpa::run_grandpa_voter(sc_consensus_grandpa::GrandpaParams { + config: grandpa_config, + link: grandpa_link, + network, + sync: sync_service, + notification_service: grandpa_notification_service, + voting_rule: sc_consensus_grandpa::VotingRulesBuilder::default().build(), + prometheus_registry, + shared_voter_state: sc_consensus_grandpa::SharedVoterState::empty(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(transaction_pool), + })?; // the GRANDPA voter task is considered infallible, i.e. // if it fails we take down the service with it. - task_manager.spawn_essential_handle().spawn_blocking( - "grandpa-voter", - None, - sc_consensus_grandpa::run_grandpa_voter(grandpa_config)?, - ); + task_manager + .spawn_essential_handle() + .spawn_blocking("grandpa-voter", None, grandpa_voter); } network_starter.start_network(); Ok(task_manager) } + +pub async fn build_full( + config: Configuration, + eth_config: EthConfiguration, + sealing: Option, +) -> Result { + match config.network.network_backend { + sc_network::config::NetworkBackendType::Libp2p => { + new_full::>( + config, eth_config, sealing, + ) + .await + } + sc_network::config::NetworkBackendType::Litep2p => { + new_full::( + config, eth_config, sealing, + ) + .await + } + } +} + +pub fn new_chain_ops( + config: &mut Configuration, + eth_config: &EthConfiguration, +) -> Result< + ( + Arc, + Arc, + BasicQueue, + TaskManager, + FrontierBackend, + ), + ServiceError, +> { + config.keystore = sc_service::config::KeystoreConfig::InMemory; + let PartialComponents { + client, + backend, + import_queue, + task_manager, + other, + .. + } = new_partial::( + config, + eth_config, + build_aura_grandpa_import_queue, + )?; + Ok((client, backend, import_queue, task_manager, other.3)) +} + +#[allow(clippy::too_many_arguments)] +fn run_manual_seal_authorship( + eth_config: &EthConfiguration, + sealing: Sealing, + client: Arc>, + transaction_pool: Arc>>, + select_chain: FullSelectChain, + block_import: BoxBlockImport, + task_manager: &TaskManager, + prometheus_registry: Option<&Registry>, + telemetry: Option<&Telemetry>, + commands_stream: mpsc::Receiver< + sc_consensus_manual_seal::rpc::EngineCommand<::Hash>, + >, +) -> Result<(), ServiceError> +where + B: BlockT, + RA: ConstructRuntimeApi>, + RA: Send + Sync + 'static, + RA::RuntimeApi: RuntimeApiCollection, + HF: HostFunctionsT + 'static, +{ + let proposer_factory = sc_basic_authorship::ProposerFactory::new( + task_manager.spawn_handle(), + client.clone(), + transaction_pool.clone(), + prometheus_registry, + telemetry.as_ref().map(|x| x.handle()), + ); + + thread_local!(static TIMESTAMP: RefCell = const { RefCell::new(0) }); + + /// Provide a mock duration starting at 0 in millisecond for timestamp inherent. + /// Each call will increment timestamp by slot_duration making Aura think time has passed. + struct MockTimestampInherentDataProvider; + + #[async_trait::async_trait] + impl sp_inherents::InherentDataProvider for MockTimestampInherentDataProvider { + async fn provide_inherent_data( + &self, + inherent_data: &mut sp_inherents::InherentData, + ) -> 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); + inherent_data.put_data(sp_timestamp::INHERENT_IDENTIFIER, &*x.borrow()) + }) + } + + async fn try_handle_error( + &self, + _identifier: &sp_inherents::InherentIdentifier, + _error: &[u8], + ) -> Option> { + // The pallet never reports error. + None + } + } + + let target_gas_price = eth_config.target_gas_price; + let create_inherent_data_providers = move |_, ()| async move { + let timestamp = MockTimestampInherentDataProvider; + let dynamic_fee = fp_dynamic_fee::InherentDataProvider(U256::from(target_gas_price)); + Ok((timestamp, dynamic_fee)) + }; + + let manual_seal = match sealing { + Sealing::Manual => future::Either::Left(sc_consensus_manual_seal::run_manual_seal( + sc_consensus_manual_seal::ManualSealParams { + block_import, + env: proposer_factory, + client, + pool: transaction_pool, + commands_stream, + select_chain, + consensus_data_provider: None, + create_inherent_data_providers, + }, + )), + Sealing::Instant => future::Either::Right(sc_consensus_manual_seal::run_instant_seal( + sc_consensus_manual_seal::InstantSealParams { + block_import, + env: proposer_factory, + client, + pool: transaction_pool, + select_chain, + consensus_data_provider: None, + create_inherent_data_providers, + }, + )), + }; + + // we spawn the future on a background thread managed by service. + task_manager + .spawn_essential_handle() + .spawn_blocking("manual-seal", None, manual_seal); + Ok(()) +} diff --git a/pallets/admin-utils/src/benchmarking.rs b/pallets/admin-utils/src/benchmarking.rs index 7515525f0..65ccf629e 100644 --- a/pallets/admin-utils/src/benchmarking.rs +++ b/pallets/admin-utils/src/benchmarking.rs @@ -235,7 +235,7 @@ mod benchmarks { ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 3u64/*interval*/)/*set_commit_reveal_weights_interval()*/; + _(RawOrigin::Root, 1u16/*netuid*/, 3u64/*interval*/)/*sudo_set_commit_reveal_weights_interval()*/; } #[benchmark] diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 3e06b822e..85c7ef62c 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -960,32 +960,6 @@ pub mod pallet { Ok(()) } - /// The extrinsic sets the commit/reveal interval for a subnet. - /// It is only callable by the root account or subnet owner. - /// The extrinsic will call the Subtensor pallet to set the interval. - #[pallet::call_index(48)] - #[pallet::weight(T::WeightInfo::sudo_set_commit_reveal_weights_interval())] - pub fn sudo_set_commit_reveal_weights_interval( - origin: OriginFor, - netuid: u16, - interval: u64, - ) -> DispatchResult { - pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; - - ensure!( - pallet_subtensor::Pallet::::if_subnet_exist(netuid), - Error::::SubnetDoesNotExist - ); - - pallet_subtensor::Pallet::::set_commit_reveal_weights_interval(netuid, interval); - log::debug!( - "SetWeightCommitInterval( netuid: {:?}, interval: {:?} ) ", - netuid, - interval - ); - Ok(()) - } - /// The extrinsic enabled/disables commit/reaveal for a given subnet. /// It is only callable by the root account or subnet owner. /// The extrinsic will call the Subtensor pallet to set the value. @@ -1196,6 +1170,45 @@ pub mod pallet { Ok(()) } + + /// Sets the commit-reveal weights periods for a specific subnet. + /// + /// This extrinsic allows the subnet owner or root account to set the duration (in epochs) during which committed weights must be revealed. + /// The commit-reveal mechanism ensures that users commit weights in advance and reveal them only within a specified period. + /// + /// # Arguments + /// * `origin` - The origin of the call, which must be the subnet owner or the root account. + /// * `netuid` - The unique identifier of the subnet for which the periods are being set. + /// * `periods` - The number of epochs that define the commit-reveal period. + /// + /// # Errors + /// * `BadOrigin` - If the caller is neither the subnet owner nor the root account. + /// * `SubnetDoesNotExist` - If the specified subnet does not exist. + /// + /// # Weight + /// Weight is handled by the `#[pallet::weight]` attribute. + #[pallet::call_index(57)] + #[pallet::weight(T::WeightInfo::sudo_set_commit_reveal_weights_interval())] + pub fn sudo_set_commit_reveal_weights_interval( + origin: OriginFor, + netuid: u16, + interval: u64, + ) -> DispatchResult { + pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; + + ensure!( + pallet_subtensor::Pallet::::if_subnet_exist(netuid), + Error::::SubnetDoesNotExist + ); + + pallet_subtensor::Pallet::::set_reveal_period(netuid, interval); + log::debug!( + "SetWeightCommitInterval( netuid: {:?}, interval: {:?} ) ", + netuid, + interval + ); + Ok(()) + } } } diff --git a/pallets/admin-utils/src/weights.rs b/pallets/admin-utils/src/weights.rs index 84fe058f8..bda9c7916 100644 --- a/pallets/admin-utils/src/weights.rs +++ b/pallets/admin-utils/src/weights.rs @@ -415,10 +415,10 @@ impl WeightInfo for SubstrateWeight { } fn sudo_set_commit_reveal_weights_interval() -> Weight { // Proof Size summary in bytes: - // Measured: `1111` - // Estimated: `4697` - // Minimum execution time: 46_450_000 picoseconds. - Weight::from_parts(47_279_000, 4697) + // Measured: `456` + // Estimated: `3921` + // Minimum execution time: 19_070_000 picoseconds. + Weight::from_parts(19_380_000, 456) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -784,14 +784,14 @@ impl WeightInfo for () { fn sudo_set_commit_reveal_weights_interval() -> Weight { // -- Extrinsic Time -- // Model: - // Time ~= 20.42 - // µs + // Time ~= 19.38 + // µs // Reads = 1 // Writes = 1 // Recorded proof Size = 456 - Weight::from_parts(20_420_000, 456) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + Weight::from_parts(19_380_000, 456) + .saturating_add(RocksDbWeight::get().reads(1)) + .saturating_add(RocksDbWeight::get().writes(1)) } fn sudo_set_commit_reveal_weights_enabled() -> Weight { // -- Extrinsic Time -- diff --git a/pallets/admin-utils/tests/tests.rs b/pallets/admin-utils/tests/tests.rs index 8ab85f177..442275052 100644 --- a/pallets/admin-utils/tests/tests.rs +++ b/pallets/admin-utils/tests/tests.rs @@ -1113,29 +1113,6 @@ fn test_sudo_set_min_delegate_take() { }); } -#[test] -fn test_sudo_set_weight_commit_interval() { - new_test_ext().execute_with(|| { - let netuid: u16 = 1; - add_network(netuid, 10); - - let to_be_set = 55; - let init_value = SubtensorModule::get_commit_reveal_weights_interval(netuid); - - assert_ok!(AdminUtils::sudo_set_commit_reveal_weights_interval( - <::RuntimeOrigin>::root(), - netuid, - to_be_set - )); - - assert!(init_value != to_be_set); - assert_eq!( - SubtensorModule::get_commit_reveal_weights_interval(netuid), - to_be_set - ); - }); -} - #[test] fn test_sudo_set_commit_reveal_weights_enabled() { new_test_ext().execute_with(|| { @@ -1435,3 +1412,23 @@ fn test_sudo_set_dissolve_network_schedule_duration() { System::assert_last_event(Event::DissolveNetworkScheduleDurationSet(new_duration).into()); }); } + +#[test] +fn sudo_set_commit_reveal_weights_interval() { + new_test_ext().execute_with(|| { + let netuid: u16 = 1; + add_network(netuid, 10); + + let to_be_set = 55; + let init_value = SubtensorModule::get_reveal_period(netuid); + + assert_ok!(AdminUtils::sudo_set_commit_reveal_weights_interval( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + + assert!(init_value != to_be_set); + assert_eq!(SubtensorModule::get_reveal_period(netuid), to_be_set); + }); +} diff --git a/pallets/subtensor/src/benchmarks.rs b/pallets/subtensor/src/benchmarks.rs index 4915bb3ac..6fd1cbf8b 100644 --- a/pallets/subtensor/src/benchmarks.rs +++ b/pallets/subtensor/src/benchmarks.rs @@ -416,7 +416,6 @@ reveal_weights { ); Subtensor::::set_validator_permit_for_uid(netuid, 0, true); - Subtensor::::set_commit_reveal_weights_interval(netuid, 0); let commit_hash: H256 = BlakeTwo256::hash_of(&( hotkey.clone(), @@ -521,4 +520,82 @@ reveal_weights { // Benchmark setup complete, now execute the extrinsic }: swap_coldkey(RawOrigin::Root, old_coldkey.clone(), new_coldkey.clone()) +batch_reveal_weights { + let tempo: u16 = 0; + let netuid: u16 = 1; + let num_commits: usize = 10; + + let hotkey: T::AccountId = account("hot", 0, 1); + let coldkey: T::AccountId = account("cold", 0, 2); + + Subtensor::::init_new_network(netuid, tempo); + Subtensor::::set_network_registration_allowed(netuid, true); + Subtensor::::set_network_pow_registration_allowed(netuid, true); + Subtensor::::set_commit_reveal_weights_enabled(netuid, true); + Subtensor::::set_weights_set_rate_limit(netuid, 0); // Disable rate limiting for benchmarking + + let block_number: u64 = Subtensor::::get_current_block_as_u64(); + let (nonce, work): (u64, Vec) = Subtensor::::create_work_for_block_number( + netuid, + block_number, + 3, + &hotkey, + ); + + let origin = T::RuntimeOrigin::from(RawOrigin::Signed(hotkey.clone())); + assert_ok!(Subtensor::::register( + origin.clone(), + netuid, + block_number, + nonce, + work.clone(), + hotkey.clone(), + coldkey.clone(), + )); + + let uid: u16 = 0; + + Subtensor::::set_validator_permit_for_uid(netuid, uid, true); + + let mut uids_list = Vec::new(); + let mut values_list = Vec::new(); + let mut salts_list = Vec::new(); + let mut version_keys = Vec::new(); + + for i in 0..num_commits { + let uids: Vec = vec![uid]; + let values: Vec = vec![i as u16]; + let salt: Vec = vec![i as u16]; + let version_key_i: u64 = i as u64; + + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey.clone(), + netuid, + uids.clone(), + values.clone(), + salt.clone(), + version_key_i, + )); + + assert_ok!(Subtensor::::commit_weights( + T::RuntimeOrigin::from(RawOrigin::Signed(hotkey.clone())), + netuid, + commit_hash, + )); + + uids_list.push(uids); + values_list.push(values); + salts_list.push(salt); + version_keys.push(version_key_i); + } +}: batch_reveal_weights( + RawOrigin::Signed(hotkey.clone()), + netuid, + uids_list, + values_list, + salts_list, + version_keys +) + + } diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 723edc423..badb811fa 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -265,69 +265,65 @@ impl Pallet { // --- 1.0 Drain the hotkey emission. PendingdHotkeyEmission::::insert(hotkey, 0); - // --- 2 Retrieve the last time this hotkey's emissions were drained. - let last_emission_drain: u64 = LastHotkeyEmissionDrain::::get(hotkey); - - // --- 3 Update the block value to the current block number. + // --- 2 Update the block value to the current block number. LastHotkeyEmissionDrain::::insert(hotkey, block_number); - // --- 4 Retrieve the total stake for the hotkey from all nominations. + // --- 3 Retrieve the total stake for the hotkey from all nominations. let total_hotkey_stake: u64 = Self::get_total_stake_for_hotkey(hotkey); - // --- 5 Calculate the emission take for the hotkey. + // --- 4 Calculate the emission take for the hotkey. let take_proportion: I64F64 = I64F64::from_num(Delegates::::get(hotkey)) .saturating_div(I64F64::from_num(u16::MAX)); let hotkey_take: u64 = (take_proportion.saturating_mul(I64F64::from_num(emission))).to_num::(); - // --- 6 Compute the remaining emission after deducting the hotkey's take. + // --- 5 Compute the remaining emission after deducting the hotkey's take. let emission_minus_take: u64 = emission.saturating_sub(hotkey_take); - // --- 7 Calculate the remaining emission after the hotkey's take. + // --- 6 Calculate the remaining emission after the hotkey's take. let mut remainder: u64 = emission_minus_take; - // --- 8 Iterate over each nominator and get all viable stake. + // --- 7 Iterate over each nominator and get all viable stake. let mut total_viable_nominator_stake: u64 = total_hotkey_stake; - for (nominator, nominator_stake) in Stake::::iter_prefix(hotkey) { - if LastAddStakeIncrease::::get(hotkey, nominator) > last_emission_drain { - total_viable_nominator_stake = - total_viable_nominator_stake.saturating_sub(nominator_stake); - } + for (nominator, _) in Stake::::iter_prefix(hotkey) { + let nonviable_nomintaor_stake = Self::get_nonviable_stake(hotkey, &nominator); + + total_viable_nominator_stake = + total_viable_nominator_stake.saturating_sub(nonviable_nomintaor_stake); } - // --- 9 Iterate over each nominator. + // --- 8 Iterate over each nominator. if total_viable_nominator_stake != 0 { for (nominator, nominator_stake) in Stake::::iter_prefix(hotkey) { - // --- 10 Check if the stake was manually increased by the user since the last emission drain for this hotkey. + // --- 9 Check if the stake was manually increased by the user since the last emission drain for this hotkey. // If it was, skip this nominator as they will not receive their proportion of the emission. - if LastAddStakeIncrease::::get(hotkey, nominator.clone()) > last_emission_drain { - continue; - } + let viable_nominator_stake = + nominator_stake.saturating_sub(Self::get_nonviable_stake(hotkey, &nominator)); - // --- 11 Calculate this nominator's share of the emission. - let nominator_emission: I64F64 = I64F64::from_num(emission_minus_take) - .saturating_mul(I64F64::from_num(nominator_stake)) + // --- 10 Calculate this nominator's share of the emission. + let nominator_emission: I64F64 = I64F64::from_num(viable_nominator_stake) .checked_div(I64F64::from_num(total_viable_nominator_stake)) - .unwrap_or(I64F64::from_num(0)); + .unwrap_or(I64F64::from_num(0)) + .saturating_mul(I64F64::from_num(emission_minus_take)); - // --- 12 Increase the stake for the nominator. + // --- 11 Increase the stake for the nominator. Self::increase_stake_on_coldkey_hotkey_account( &nominator, hotkey, nominator_emission.to_num::(), ); - // --- 13* Record event and Subtract the nominator's emission from the remainder. + // --- 12* Record event and Subtract the nominator's emission from the remainder. total_new_tao = total_new_tao.saturating_add(nominator_emission.to_num::()); remainder = remainder.saturating_sub(nominator_emission.to_num::()); } } - // --- 14 Finally, add the stake to the hotkey itself, including its take and the remaining emission. + // --- 13 Finally, add the stake to the hotkey itself, including its take and the remaining emission. let hotkey_new_tao: u64 = hotkey_take.saturating_add(remainder); Self::increase_stake_on_hotkey_account(hotkey, hotkey_new_tao); - // --- 15 Record new tao creation event and return the amount created. + // --- 14 Record new tao creation event and return the amount created. total_new_tao = total_new_tao.saturating_add(hotkey_new_tao); total_new_tao } @@ -382,4 +378,18 @@ impl Pallet { let remainder = block_plus_netuid.rem_euclid(tempo_plus_one); (tempo as u64).saturating_sub(remainder) } + + /// Calculates the nonviable stake for a nominator. + /// The nonviable stake is the stake that was added by the nominator since the last emission drain. + /// This stake will not receive emission until the next emission drain. + /// Note: if the stake delta is below zero, we return zero. We don't allow more stake than the nominator has. + pub fn get_nonviable_stake(hotkey: &T::AccountId, nominator: &T::AccountId) -> u64 { + let stake_delta = StakeDeltaSinceLastEmissionDrain::::get(hotkey, nominator); + if stake_delta.is_negative() { + 0 + } else { + // Should never fail the into, but we handle it anyway. + stake_delta.try_into().unwrap_or(u64::MAX) + } + } } diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index cc3d7d025..d93253cfa 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -72,6 +72,7 @@ pub mod pallet { use frame_system::pallet_prelude::*; use sp_core::H256; use sp_runtime::traits::{Dispatchable, TrailingZeroInput}; + use sp_std::collections::vec_deque::VecDeque; use sp_std::vec; use sp_std::vec::Vec; use subtensor_macros::freeze_struct; @@ -258,6 +259,11 @@ pub mod pallet { 0 } #[pallet::type_value] + /// Default stake delta. + pub fn DefaultStakeDelta() -> i128 { + 0 + } + #[pallet::type_value] /// Default stakes per interval. pub fn DefaultStakesPerInterval() -> (u64, u64) { (0, 0) @@ -568,6 +574,11 @@ pub mod pallet { 0 } #[pallet::type_value] + /// Default Reveal Period Epochs + pub fn DefaultRevealPeriodEpochs() -> u64 { + 1 + } + #[pallet::type_value] /// Value definition for vector of u16. pub fn EmptyU16Vec() -> Vec { vec![] @@ -629,11 +640,6 @@ pub mod pallet { T::InitialServingRateLimit::get() } #[pallet::type_value] - /// Default value for weight commit reveal interval. - pub fn DefaultWeightCommitRevealInterval() -> u64 { - 1000 - } - #[pallet::type_value] /// Default value for weight commit/reveal enabled. pub fn DefaultCommitRevealWeightsEnabled() -> bool { false @@ -790,16 +796,16 @@ pub mod pallet { DefaultAccumulatedEmission, >; #[pallet::storage] - /// Map ( hot, cold ) --> block_number | Last add stake increase. - pub type LastAddStakeIncrease = StorageDoubleMap< + /// Map ( hot, cold ) --> stake: i128 | Stake added/removed since last emission drain. + pub type StakeDeltaSinceLastEmissionDrain = StorageDoubleMap< _, Blake2_128Concat, T::AccountId, Identity, T::AccountId, - u64, + i128, ValueQuery, - DefaultAccountTake, + DefaultStakeDelta, >; #[pallet::storage] /// DMAP ( parent, netuid ) --> Vec<(proportion,child)> @@ -1032,10 +1038,6 @@ pub mod pallet { StorageMap<_, Identity, u16, u64, ValueQuery, DefaultAdjustmentAlpha>; #[pallet::storage] /// --- MAP ( netuid ) --> interval - pub type WeightCommitRevealInterval = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultWeightCommitRevealInterval>; - #[pallet::storage] - /// --- MAP ( netuid ) --> interval pub type CommitRevealWeightsEnabled = StorageMap<_, Identity, u16, bool, ValueQuery, DefaultCommitRevealWeightsEnabled>; #[pallet::storage] @@ -1254,16 +1256,20 @@ pub mod pallet { /// ITEM( weights_min_stake ) pub type WeightsMinStake = StorageValue<_, u64, ValueQuery, DefaultWeightsMinStake>; #[pallet::storage] - /// --- MAP (netuid, who) --> (hash, weight) | Returns the hash and weight committed by an account for a given netuid. + /// --- MAP (netuid, who) --> VecDeque<(hash, commit_block, first_reveal_block, last_reveal_block)> | Stores a queue of commits for an account on a given netuid. pub type WeightCommits = StorageDoubleMap< _, Twox64Concat, u16, Twox64Concat, T::AccountId, - (H256, u64), + VecDeque<(H256, u64, u64, u64)>, OptionQuery, >; + #[pallet::storage] + /// --- Map (netuid) --> Number of epochs allowed for commit reveal periods + pub type RevealPeriodEpochs = + StorageMap<_, Twox64Concat, u16, u64, ValueQuery, DefaultRevealPeriodEpochs>; /// ================== /// ==== Genesis ===== @@ -1460,6 +1466,18 @@ where Err(InvalidTransaction::Custom(2).into()) } } + Some(Call::batch_reveal_weights { netuid, .. }) => { + if Self::check_weights_min_stake(who) { + let priority: u64 = Self::get_priority_set_weights(who, *netuid); + Ok(ValidTransaction { + priority, + longevity: 1, + ..Default::default() + }) + } else { + Err(InvalidTransaction::Custom(6).into()) + } + } Some(Call::set_weights { netuid, .. }) => { if Self::check_weights_min_stake(who) { let priority: u64 = Self::get_priority_set_weights(who, *netuid); diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index c4b985a49..e98ecbd6a 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -102,8 +102,11 @@ mod dispatches { /// - The hash representing the committed weights. /// /// # Raises: - /// * `WeightsCommitNotAllowed`: - /// - Attempting to commit when it is not allowed. + /// * `CommitRevealDisabled`: + /// - Attempting to commit when the commit-reveal mechanism is disabled. + /// + /// * `TooManyUnrevealedCommits`: + /// - Attempting to commit when the user has more than the allowed limit of unrevealed commits. /// #[pallet::call_index(96)] #[pallet::weight((Weight::from_parts(46_000_000, 0) @@ -132,21 +135,27 @@ mod dispatches { /// * `values` (`Vec`): /// - The values of the weights being revealed. /// - /// * `salt` (`Vec`): - /// - The random salt to protect from brute-force guessing attack in case of small weight changes bit-wise. + /// * `salt` (`Vec`): + /// - The salt used to generate the commit hash. /// /// * `version_key` (`u64`): /// - The network version key. /// /// # Raises: + /// * `CommitRevealDisabled`: + /// - Attempting to reveal weights when the commit-reveal mechanism is disabled. + /// /// * `NoWeightsCommitFound`: /// - Attempting to reveal weights without an existing commit. /// - /// * `InvalidRevealCommitHashNotMatchTempo`: - /// - Attempting to reveal weights outside the valid tempo. + /// * `ExpiredWeightCommit`: + /// - Attempting to reveal a weight commit that has expired. + /// + /// * `RevealTooEarly`: + /// - Attempting to reveal weights outside the valid reveal period. /// /// * `InvalidRevealCommitHashNotMatch`: - /// - The revealed hash does not match the committed hash. + /// - The revealed hash does not match any committed hash. /// #[pallet::call_index(97)] #[pallet::weight((Weight::from_parts(103_000_000, 0) @@ -163,6 +172,67 @@ mod dispatches { Self::do_reveal_weights(origin, netuid, uids, values, salt, version_key) } + /// ---- The implementation for batch revealing committed weights. + /// + /// # Args: + /// * `origin`: (`::RuntimeOrigin`): + /// - The signature of the revealing hotkey. + /// + /// * `netuid` (`u16`): + /// - The u16 network identifier. + /// + /// * `uids_list` (`Vec>`): + /// - A list of uids for each set of weights being revealed. + /// + /// * `values_list` (`Vec>`): + /// - A list of values for each set of weights being revealed. + /// + /// * `salts_list` (`Vec>`): + /// - A list of salts used to generate the commit hashes. + /// + /// * `version_keys` (`Vec`): + /// - A list of network version keys. + /// + /// # Raises: + /// * `CommitRevealDisabled`: + /// - Attempting to reveal weights when the commit-reveal mechanism is disabled. + /// + /// * `NoWeightsCommitFound`: + /// - Attempting to reveal weights without an existing commit. + /// + /// * `ExpiredWeightCommit`: + /// - Attempting to reveal a weight commit that has expired. + /// + /// * `RevealTooEarly`: + /// - Attempting to reveal weights outside the valid reveal period. + /// + /// * `InvalidRevealCommitHashNotMatch`: + /// - The revealed hash does not match any committed hash. + /// + /// * `InvalidInputLengths`: + /// - The input vectors are of mismatched lengths. + #[pallet::call_index(98)] + #[pallet::weight((Weight::from_parts(367_612_000, 0) + .saturating_add(T::DbWeight::get().reads(14)) + .saturating_add(T::DbWeight::get().writes(3)), DispatchClass::Normal, Pays::No))] + pub fn batch_reveal_weights( + origin: T::RuntimeOrigin, + netuid: u16, + uids_list: Vec>, + values_list: Vec>, + salts_list: Vec>, + version_keys: Vec, + ) -> DispatchResult { + Self::do_batch_reveal_weights( + origin, + netuid, + uids_list, + values_list, + salts_list, + version_keys, + ) + } + /// # Args: /// * `origin`: (Origin): /// - The caller, a hotkey who wishes to set their weights. diff --git a/pallets/subtensor/src/macros/errors.rs b/pallets/subtensor/src/macros/errors.rs index 22a0a6f89..aab849994 100644 --- a/pallets/subtensor/src/macros/errors.rs +++ b/pallets/subtensor/src/macros/errors.rs @@ -114,12 +114,8 @@ mod errors { DelegateTakeTooLow, /// Delegate take is too high. DelegateTakeTooHigh, - /// Not allowed to commit weights. - WeightsCommitNotAllowed, /// No commit found for the provided hotkey+netuid combination when attempting to reveal the weights. NoWeightsCommitFound, - /// Not the correct block/range to reveal weights. - InvalidRevealCommitTempo, /// Committed hash does not equal the hashed reveal data. InvalidRevealCommitHashNotMatch, /// Attempting to call set_weights when commit/reveal is enabled @@ -184,5 +180,15 @@ mod errors { TxChildkeyTakeRateLimitExceeded, /// Invalid identity. InvalidIdentity, + /// Maximum commit limit reached + TooManyUnrevealedCommits, + /// Attempted to reveal weights that are expired. + ExpiredWeightCommit, + /// Attempted to reveal weights too early. + RevealTooEarly, + /// Attempted to batch reveal weights with mismatched vector input lenghts. + InputLengthsUnequal, + /// A transactor exceeded the rate limit for setting weights. + CommittingWeightsTooFast, } } diff --git a/pallets/subtensor/src/macros/events.rs b/pallets/subtensor/src/macros/events.rs index ac6b69012..f3b03684d 100644 --- a/pallets/subtensor/src/macros/events.rs +++ b/pallets/subtensor/src/macros/events.rs @@ -204,5 +204,25 @@ mod events { ColdkeySwapScheduleDurationSet(BlockNumberFor), /// The duration of dissolve network has been set DissolveNetworkScheduleDurationSet(BlockNumberFor), + /// Weights have been successfully committed. + /// + /// - **who**: The account ID of the user committing the weights. + /// - **netuid**: The network identifier. + /// - **commit_hash**: The hash representing the committed weights. + WeightsCommitted(T::AccountId, u16, H256), + + /// Weights have been successfully revealed. + /// + /// - **who**: The account ID of the user revealing the weights. + /// - **netuid**: The network identifier. + /// - **commit_hash**: The hash of the revealed weights. + WeightsRevealed(T::AccountId, u16, H256), + + /// Weights have been successfully batch revealed. + /// + /// - **who**: The account ID of the user revealing the weights. + /// - **netuid**: The network identifier. + /// - **revealed_hashes**: A vector of hashes representing each revealed weight set. + WeightsBatchRevealed(T::AccountId, u16, Vec), } } diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index 76f140002..1077acb76 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -70,7 +70,9 @@ mod hooks { // Storage version v8 -> v9 .saturating_add(migrations::migrate_fix_total_coldkey_stake::migrate_fix_total_coldkey_stake::()) // Migrate Delegate Ids on chain - .saturating_add(migrations::migrate_chain_identity::migrate_set_hotkey_identities::()); + .saturating_add(migrations::migrate_chain_identity::migrate_set_hotkey_identities::()) + // Migrate Commit-Reval 2.0 + .saturating_add(migrations::migrate_commit_reveal_v2::migrate_commit_reveal_2::()); weight } diff --git a/pallets/subtensor/src/migrations/migrate_commit_reveal_v2.rs b/pallets/subtensor/src/migrations/migrate_commit_reveal_v2.rs new file mode 100644 index 000000000..b8b831b61 --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_commit_reveal_v2.rs @@ -0,0 +1,88 @@ +use super::*; +use crate::HasMigrationRun; +use frame_support::{traits::Get, weights::Weight}; +use scale_info::prelude::string::String; +use sp_io::{hashing::twox_128, storage::clear_prefix, KillStorageResult}; + +pub fn migrate_commit_reveal_2() -> Weight { + let migration_name = b"migrate_commit_reveal_2_v2".to_vec(); + let mut weight = T::DbWeight::get().reads(1); + + if HasMigrationRun::::get(&migration_name) { + log::info!( + "Migration '{:?}' has already run. Skipping.", + migration_name + ); + return weight; + } + + log::info!( + "Running migration '{}'", + String::from_utf8_lossy(&migration_name) + ); + + // ------------------------------ + // Step 1: Remove WeightCommitRevealInterval entries + // ------------------------------ + + let mut weight_commit_reveal_interval_prefix = Vec::new(); + weight_commit_reveal_interval_prefix.extend_from_slice(&twox_128("SubtensorModule".as_bytes())); + weight_commit_reveal_interval_prefix + .extend_from_slice(&twox_128("WeightCommitRevealInterval".as_bytes())); + + let removal_results = clear_prefix(&weight_commit_reveal_interval_prefix, Some(u32::MAX)); + + let removed_entries_count = match removal_results { + KillStorageResult::AllRemoved(removed) => removed as u64, + KillStorageResult::SomeRemaining(removed) => { + log::info!("Failed To Remove Some Items During migrate_commit_reveal_v2"); + removed as u64 + } + }; + + weight = weight.saturating_add(T::DbWeight::get().writes(removed_entries_count)); + + log::info!( + "Removed {:?} entries from WeightCommitRevealInterval.", + removed_entries_count + ); + + // ------------------------------ + // Step 2: Remove WeightCommits entries + // ------------------------------ + + let mut weight_commits_prefix = Vec::new(); + weight_commits_prefix.extend_from_slice(&twox_128("SubtensorModule".as_bytes())); + weight_commits_prefix.extend_from_slice(&twox_128("WeightCommits".as_bytes())); + + let removal_results_commits = clear_prefix(&weight_commits_prefix, Some(u32::MAX)); + + let removed_commits_entries = match removal_results_commits { + KillStorageResult::AllRemoved(removed) => removed as u64, + KillStorageResult::SomeRemaining(removed) => { + log::info!("Failed To Remove Some Items During migrate_commit_reveal_v2"); + removed as u64 + } + }; + + weight = weight.saturating_add(T::DbWeight::get().writes(removed_commits_entries)); + + log::info!( + "Removed {} entries from WeightCommits.", + removed_commits_entries + ); + + // ------------------------------ + // Step 3: Mark Migration as Completed + // ------------------------------ + + HasMigrationRun::::insert(&migration_name, true); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!( + "Migration '{:?}' completed successfully.", + String::from_utf8_lossy(&migration_name) + ); + + weight +} diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index 6036b23e0..a0ee65998 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -1,5 +1,6 @@ use super::*; pub mod migrate_chain_identity; +pub mod migrate_commit_reveal_v2; pub mod migrate_create_root_network; pub mod migrate_delete_subnet_21; pub mod migrate_delete_subnet_3; diff --git a/pallets/subtensor/src/rpc_info/subnet_info.rs b/pallets/subtensor/src/rpc_info/subnet_info.rs index af12d8139..2cc4440bf 100644 --- a/pallets/subtensor/src/rpc_info/subnet_info.rs +++ b/pallets/subtensor/src/rpc_info/subnet_info.rs @@ -161,7 +161,7 @@ impl Pallet { let max_validators = Self::get_max_allowed_validators(netuid); let adjustment_alpha = Self::get_adjustment_alpha(netuid); let difficulty = Self::get_difficulty_as_u64(netuid); - let commit_reveal_weights_interval = Self::get_commit_reveal_weights_interval(netuid); + let commit_reveal_periods = Self::get_reveal_period(netuid); let commit_reveal_weights_enabled = Self::get_commit_reveal_weights_enabled(netuid); let liquid_alpha_enabled = Self::get_liquid_alpha_enabled(netuid); let (alpha_low, alpha_high): (u16, u16) = Self::get_alpha_values(netuid); @@ -189,7 +189,7 @@ impl Pallet { max_validators: max_validators.into(), adjustment_alpha: adjustment_alpha.into(), difficulty: difficulty.into(), - commit_reveal_weights_interval: commit_reveal_weights_interval.into(), + commit_reveal_weights_interval: commit_reveal_periods.into(), commit_reveal_weights_enabled, alpha_high: alpha_high.into(), alpha_low: alpha_low.into(), diff --git a/pallets/subtensor/src/staking/add_stake.rs b/pallets/subtensor/src/staking/add_stake.rs index c9cbd7e04..72d8374bc 100644 --- a/pallets/subtensor/src/staking/add_stake.rs +++ b/pallets/subtensor/src/staking/add_stake.rs @@ -70,8 +70,10 @@ impl Pallet { Error::::StakeRateLimitExceeded ); - // Set the last time the stake increased for nominator drain protection. - LastAddStakeIncrease::::insert(&hotkey, &coldkey, Self::get_current_block_as_u64()); + // Track this addition in the stake delta. + StakeDeltaSinceLastEmissionDrain::::mutate(&hotkey, &coldkey, |stake_delta| { + *stake_delta = stake_delta.saturating_add_unsigned(stake_to_be_added as u128); + }); // If coldkey is not owner of the hotkey, it's a nomination stake. if !Self::coldkey_owns_hotkey(&coldkey, &hotkey) { diff --git a/pallets/subtensor/src/subnets/weights.rs b/pallets/subtensor/src/subnets/weights.rs index 1a53e44cc..87042f456 100644 --- a/pallets/subtensor/src/subnets/weights.rs +++ b/pallets/subtensor/src/subnets/weights.rs @@ -2,7 +2,7 @@ use super::*; use crate::epoch::math::*; use sp_core::H256; use sp_runtime::traits::{BlakeTwo256, Hash}; -use sp_std::vec; +use sp_std::{collections::vec_deque::VecDeque, vec}; impl Pallet { /// ---- The implementation for committing weight hashes. @@ -18,34 +18,91 @@ impl Pallet { /// - The hash representing the committed weights. /// /// # Raises: - /// * `WeightsCommitNotAllowed`: - /// - Attempting to commit when it is not allowed. + /// * `CommitRevealDisabled`: + /// - Raised if commit-reveal is disabled for the specified network. /// + /// * `HotKeyNotRegisteredInSubNet`: + /// - Raised if the hotkey is not registered on the specified network. + /// + /// * `CommittingWeightsTooFast`: + /// - Raised if the hotkey's commit rate exceeds the permitted limit. + /// + /// * `TooManyUnrevealedCommits`: + /// - Raised if the hotkey has reached the maximum number of unrevealed commits. + /// + /// # Events: + /// * `WeightsCommitted`: + /// - Emitted upon successfully storing the weight hash. pub fn do_commit_weights( origin: T::RuntimeOrigin, netuid: u16, commit_hash: H256, ) -> DispatchResult { + // 1. Verify the caller's signature (hotkey). let who = ensure_signed(origin)?; - log::debug!("do_commit_weights( hotkey:{:?} netuid:{:?})", who, netuid); + log::debug!("do_commit_weights(hotkey: {:?}, netuid: {:?})", who, netuid); + // 2. Ensure commit-reveal is enabled. ensure!( Self::get_commit_reveal_weights_enabled(netuid), Error::::CommitRevealDisabled ); + // 3. Ensure the hotkey is registered on the network. ensure!( - Self::can_commit(netuid, &who), - Error::::WeightsCommitNotAllowed + Self::is_hotkey_registered_on_network(netuid, &who), + Error::::HotKeyNotRegisteredInSubNet ); - WeightCommits::::insert( - netuid, - &who, - (commit_hash, Self::get_current_block_as_u64()), + // 4. Check that the commit rate does not exceed the allowed frequency. + let commit_block = Self::get_current_block_as_u64(); + let neuron_uid = Self::get_uid_for_net_and_hotkey(netuid, &who)?; + ensure!( + Self::check_rate_limit(netuid, neuron_uid, commit_block), + Error::::CommittingWeightsTooFast ); - Ok(()) + + // 5. Calculate the reveal blocks based on network tempo and reveal period. + let (first_reveal_block, last_reveal_block) = Self::get_reveal_blocks(netuid, commit_block); + + // 6. Retrieve or initialize the VecDeque of commits for the hotkey. + WeightCommits::::try_mutate(netuid, &who, |maybe_commits| -> DispatchResult { + let mut commits: VecDeque<(H256, u64, u64, u64)> = + maybe_commits.take().unwrap_or_default(); + + // 7. Remove any expired commits from the front of the queue. + while let Some((_, commit_block_existing, _, _)) = commits.front() { + if Self::is_commit_expired(netuid, *commit_block_existing) { + commits.pop_front(); + } else { + break; + } + } + + // 8. Verify that the number of unrevealed commits is within the allowed limit. + ensure!(commits.len() < 10, Error::::TooManyUnrevealedCommits); + + // 9. Append the new commit with calculated reveal blocks. + commits.push_back(( + commit_hash, + commit_block, + first_reveal_block, + last_reveal_block, + )); + + // 10. Store the updated commits queue back to storage. + *maybe_commits = Some(commits); + + // 11. Emit the WeightsCommitted event + Self::deposit_event(Event::WeightsCommitted(who.clone(), netuid, commit_hash)); + + // 12. Update the last commit block for the hotkey's UID. + Self::set_last_update_for_uid(netuid, neuron_uid, commit_block); + + // 13. Return success. + Ok(()) + }) } /// ---- The implementation for revealing committed weights. @@ -63,22 +120,27 @@ impl Pallet { /// * `values` (`Vec`): /// - The values of the weights being revealed. /// - /// * `salt` (`Vec`): - /// - The values of the weights being revealed. + /// * `salt` (`Vec`): + /// - The salt used to generate the commit hash. /// /// * `version_key` (`u64`): /// - The network version key. /// /// # Raises: + /// * `CommitRevealDisabled`: + /// - Attempting to reveal weights when the commit-reveal mechanism is disabled. + /// /// * `NoWeightsCommitFound`: /// - Attempting to reveal weights without an existing commit. /// - /// * `InvalidRevealCommitHashNotMatchTempo`: - /// - Attempting to reveal weights outside the valid tempo. + /// * `ExpiredWeightCommit`: + /// - Attempting to reveal a weight commit that has expired. /// - /// * `InvalidRevealCommitHashNotMatch`: - /// - The revealed hash does not match the committed hash. + /// * `RevealTooEarly`: + /// - Attempting to reveal weights outside the valid reveal period. /// + /// * `InvalidRevealCommitHashNotMatch`: + /// - The revealed hash does not match any committed hash. pub fn do_reveal_weights( origin: T::RuntimeOrigin, netuid: u16, @@ -87,25 +149,36 @@ impl Pallet { salt: Vec, version_key: u64, ) -> DispatchResult { + // --- 1. Check the caller's signature (hotkey). let who = ensure_signed(origin.clone())?; log::debug!("do_reveal_weights( hotkey:{:?} netuid:{:?})", who, netuid); + // --- 2. Ensure commit-reveal is enabled for the network. ensure!( Self::get_commit_reveal_weights_enabled(netuid), Error::::CommitRevealDisabled ); - WeightCommits::::try_mutate_exists(netuid, &who, |maybe_commit| -> DispatchResult { - let (commit_hash, commit_block) = maybe_commit - .as_ref() + // --- 3. Mutate the WeightCommits to retrieve existing commits for the user. + WeightCommits::::try_mutate_exists(netuid, &who, |maybe_commits| -> DispatchResult { + let commits = maybe_commits + .as_mut() .ok_or(Error::::NoWeightsCommitFound)?; - ensure!( - Self::is_reveal_block_range(netuid, *commit_block), - Error::::InvalidRevealCommitTempo - ); + // --- 4. Remove any expired commits from the front of the queue, collecting their hashes. + let mut expired_hashes = Vec::new(); + while let Some((hash, commit_block, _, _)) = commits.front() { + if Self::is_commit_expired(netuid, *commit_block) { + // Collect the expired commit hash + expired_hashes.push(*hash); + commits.pop_front(); + } else { + break; + } + } + // --- 5. Hash the provided data. let provided_hash: H256 = BlakeTwo256::hash_of(&( who.clone(), netuid, @@ -114,12 +187,238 @@ impl Pallet { salt.clone(), version_key, )); - ensure!( - provided_hash == *commit_hash, - Error::::InvalidRevealCommitHashNotMatch - ); - Self::do_set_weights(origin, netuid, uids, values, version_key) + // --- 6. After removing expired commits, check if any commits are left. + if commits.is_empty() { + // Check if provided_hash matches any expired commits + if expired_hashes.contains(&provided_hash) { + return Err(Error::::ExpiredWeightCommit.into()); + } else { + return Err(Error::::NoWeightsCommitFound.into()); + } + } + + // --- 7. Search for the provided_hash in the non-expired commits. + if let Some(position) = commits + .iter() + .position(|(hash, _, _, _)| *hash == provided_hash) + { + // --- 8. Get the commit block for the commit being revealed. + let (_, commit_block, _, _) = commits + .get(position) + .ok_or(Error::::NoWeightsCommitFound)?; + + // --- 9. Ensure the commit is ready to be revealed in the current block range. + ensure!( + Self::is_reveal_block_range(netuid, *commit_block), + Error::::RevealTooEarly + ); + + // --- 10. Remove all commits up to and including the one being revealed. + for _ in 0..=position { + commits.pop_front(); + } + + // --- 11. If the queue is now empty, remove the storage entry for the user. + if commits.is_empty() { + *maybe_commits = None; + } + + // --- 12. Proceed to set the revealed weights. + Self::do_set_weights(origin, netuid, uids.clone(), values.clone(), version_key)?; + + // --- 13. Emit the WeightsRevealed event. + Self::deposit_event(Event::WeightsRevealed(who.clone(), netuid, provided_hash)); + + // --- 14. Return ok. + Ok(()) + } else { + // --- 15. The provided_hash does not match any non-expired commits. + if expired_hashes.contains(&provided_hash) { + Err(Error::::ExpiredWeightCommit.into()) + } else { + Err(Error::::InvalidRevealCommitHashNotMatch.into()) + } + } + }) + } + + /// ---- The implementation for batch revealing committed weights. + /// + /// # Args: + /// * `origin`: (`::RuntimeOrigin`): + /// - The signature of the revealing hotkey. + /// + /// * `netuid` (`u16`): + /// - The u16 network identifier. + /// + /// * `uids_list` (`Vec>`): + /// - A list of uids for each set of weights being revealed. + /// + /// * `values_list` (`Vec>`): + /// - A list of values for each set of weights being revealed. + /// + /// * `salts_list` (`Vec>`): + /// - A list of salts used to generate the commit hashes. + /// + /// * `version_keys` (`Vec`): + /// - A list of network version keys. + /// + /// # Raises: + /// * `CommitRevealDisabled`: + /// - Attempting to reveal weights when the commit-reveal mechanism is disabled. + /// + /// * `NoWeightsCommitFound`: + /// - Attempting to reveal weights without an existing commit. + /// + /// * `ExpiredWeightCommit`: + /// - Attempting to reveal a weight commit that has expired. + /// + /// * `RevealTooEarly`: + /// - Attempting to reveal weights outside the valid reveal period. + /// + /// * `InvalidRevealCommitHashNotMatch`: + /// - The revealed hash does not match any committed hash. + /// + /// * `InputLengthsUnequal`: + /// - The input vectors are of mismatched lengths. + pub fn do_batch_reveal_weights( + origin: T::RuntimeOrigin, + netuid: u16, + uids_list: Vec>, + values_list: Vec>, + salts_list: Vec>, + version_keys: Vec, + ) -> DispatchResult { + // --- 1. Check that the input lists are of the same length. + let num_reveals = uids_list.len(); + ensure!( + num_reveals == values_list.len() + && num_reveals == salts_list.len() + && num_reveals == version_keys.len(), + Error::::InputLengthsUnequal + ); + + // --- 2. Check the caller's signature (hotkey). + let who = ensure_signed(origin.clone())?; + + log::debug!( + "do_batch_reveal_weights( hotkey:{:?} netuid:{:?})", + who, + netuid + ); + + // --- 3. Ensure commit-reveal is enabled for the network. + ensure!( + Self::get_commit_reveal_weights_enabled(netuid), + Error::::CommitRevealDisabled + ); + + // --- 4. Mutate the WeightCommits to retrieve existing commits for the user. + WeightCommits::::try_mutate_exists(netuid, &who, |maybe_commits| -> DispatchResult { + let commits = maybe_commits + .as_mut() + .ok_or(Error::::NoWeightsCommitFound)?; + + // --- 5. Remove any expired commits from the front of the queue, collecting their hashes. + let mut expired_hashes = Vec::new(); + while let Some((hash, commit_block, _, _)) = commits.front() { + if Self::is_commit_expired(netuid, *commit_block) { + // Collect the expired commit hash + expired_hashes.push(*hash); + commits.pop_front(); + } else { + break; + } + } + + // --- 6. Prepare to collect all provided hashes and their corresponding reveals. + let mut provided_hashes = Vec::new(); + let mut reveals = Vec::new(); + let mut revealed_hashes: Vec = Vec::with_capacity(num_reveals); + + for ((uids, values), (salt, version_key)) in uids_list + .into_iter() + .zip(values_list) + .zip(salts_list.into_iter().zip(version_keys)) + { + // --- 6a. Hash the provided data. + let provided_hash: H256 = BlakeTwo256::hash_of(&( + who.clone(), + netuid, + uids.clone(), + values.clone(), + salt.clone(), + version_key, + )); + provided_hashes.push(provided_hash); + reveals.push((uids, values, version_key, provided_hash)); + } + + // --- 7. Validate all reveals first to ensure atomicity. + for (_uids, _values, _version_key, provided_hash) in &reveals { + // --- 7a. Check if the provided_hash is in the non-expired commits. + if !commits + .iter() + .any(|(hash, _, _, _)| *hash == *provided_hash) + { + // --- 7b. If not found, check if it matches any expired commits. + if expired_hashes.contains(provided_hash) { + return Err(Error::::ExpiredWeightCommit.into()); + } else { + return Err(Error::::InvalidRevealCommitHashNotMatch.into()); + } + } + + // --- 7c. Find the commit corresponding to the provided_hash. + let commit = commits + .iter() + .find(|(hash, _, _, _)| *hash == *provided_hash) + .ok_or(Error::::NoWeightsCommitFound)?; + + // --- 7d. Check if the commit is within the reveal window. + ensure!( + Self::is_reveal_block_range(netuid, commit.1), + Error::::RevealTooEarly + ); + } + + // --- 8. All reveals are valid. Proceed to remove and process each reveal. + for (uids, values, version_key, provided_hash) in reveals { + // --- 8a. Find the position of the provided_hash. + if let Some(position) = commits + .iter() + .position(|(hash, _, _, _)| *hash == provided_hash) + { + // --- 8b. Remove the commit from the queue. + commits.remove(position); + + // --- 8c. Proceed to set the revealed weights. + Self::do_set_weights(origin.clone(), netuid, uids, values, version_key)?; + + // --- 8d. Collect the revealed hash. + revealed_hashes.push(provided_hash); + } else if expired_hashes.contains(&provided_hash) { + return Err(Error::::ExpiredWeightCommit.into()); + } else { + return Err(Error::::InvalidRevealCommitHashNotMatch.into()); + } + } + + // --- 9. If the queue is now empty, remove the storage entry for the user. + if commits.is_empty() { + *maybe_commits = None; + } + + // --- 10. Emit the WeightsBatchRevealed event with all revealed hashes. + Self::deposit_event(Event::WeightsBatchRevealed( + who.clone(), + netuid, + revealed_hashes, + )); + + // --- 11. Return ok. + Ok(()) }) } @@ -241,10 +540,12 @@ impl Pallet { // --- 9. Ensure the uid is not setting weights faster than the weights_set_rate_limit. let neuron_uid = Self::get_uid_for_net_and_hotkey(netuid, &hotkey)?; let current_block: u64 = Self::get_current_block_as_u64(); - ensure!( - Self::check_rate_limit(netuid, neuron_uid, current_block), - Error::::SettingWeightsTooFast - ); + if !Self::get_commit_reveal_weights_enabled(netuid) { + ensure!( + Self::check_rate_limit(netuid, neuron_uid, current_block), + Error::::SettingWeightsTooFast + ); + } // --- 10. Check that the neuron uid is an allowed validator permitted to set non-self weights. ensure!( @@ -286,7 +587,9 @@ impl Pallet { Weights::::insert(netuid, neuron_uid, zipped_weights); // --- 18. Set the activity for the weights on this network. - Self::set_last_update_for_uid(netuid, neuron_uid, current_block); + if !Self::get_commit_reveal_weights_enabled(netuid) { + Self::set_last_update_for_uid(netuid, neuron_uid, current_block); + } // --- 19. Emit the tracking event. log::debug!( @@ -452,50 +755,55 @@ impl Pallet { uids.len() <= subnetwork_n as usize } - #[allow(clippy::arithmetic_side_effects)] - pub fn can_commit(netuid: u16, who: &T::AccountId) -> bool { - if let Some((_hash, commit_block)) = WeightCommits::::get(netuid, who) { - let interval: u64 = Self::get_commit_reveal_weights_interval(netuid); - if interval == 0 { - return true; //prevent division by 0 - } + pub fn is_reveal_block_range(netuid: u16, commit_block: u64) -> bool { + let current_block: u64 = Self::get_current_block_as_u64(); + let commit_epoch: u64 = Self::get_epoch_index(netuid, commit_block); + let current_epoch: u64 = Self::get_epoch_index(netuid, current_block); + let reveal_period: u64 = Self::get_reveal_period(netuid); - let current_block: u64 = Self::get_current_block_as_u64(); - let interval_start: u64 = current_block.saturating_sub(current_block % interval); - let last_commit_interval_start: u64 = - commit_block.saturating_sub(commit_block % interval); + // Reveal is allowed only in the exact epoch `commit_epoch + reveal_period` + current_epoch == commit_epoch.saturating_add(reveal_period) + } - // Allow commit if we're within the interval bounds - if current_block <= interval_start.saturating_add(interval) - && interval_start > last_commit_interval_start - { - return true; - } + pub fn get_epoch_index(netuid: u16, block_number: u64) -> u64 { + let tempo: u64 = Self::get_tempo(netuid) as u64; + let tempo_plus_one: u64 = tempo.saturating_add(1); + let netuid_plus_one: u64 = (netuid as u64).saturating_add(1); + let block_with_offset: u64 = block_number.saturating_add(netuid_plus_one); - false - } else { - true - } + block_with_offset.checked_div(tempo_plus_one).unwrap_or(0) } - #[allow(clippy::arithmetic_side_effects)] - pub fn is_reveal_block_range(netuid: u16, commit_block: u64) -> bool { - let interval: u64 = Self::get_commit_reveal_weights_interval(netuid); - if interval == 0 { - return true; //prevent division by 0 - } - - let commit_interval_start: u64 = commit_block.saturating_sub(commit_block % interval); // Find the start of the interval in which the commit occurred - let reveal_interval_start: u64 = commit_interval_start.saturating_add(interval); // Start of the next interval after the commit interval + pub fn is_commit_expired(netuid: u16, commit_block: u64) -> bool { let current_block: u64 = Self::get_current_block_as_u64(); + let current_epoch: u64 = Self::get_epoch_index(netuid, current_block); + let commit_epoch: u64 = Self::get_epoch_index(netuid, commit_block); + let reveal_period: u64 = Self::get_reveal_period(netuid); - // Allow reveal if the current block is within the interval following the commit's interval - if current_block >= reveal_interval_start - && current_block < reveal_interval_start.saturating_add(interval) - { - return true; - } + current_epoch > commit_epoch.saturating_add(reveal_period) + } - false + pub fn get_reveal_blocks(netuid: u16, commit_block: u64) -> (u64, u64) { + let reveal_period: u64 = Self::get_reveal_period(netuid); + let tempo: u64 = Self::get_tempo(netuid) as u64; + let tempo_plus_one: u64 = tempo.saturating_add(1); + let netuid_plus_one: u64 = (netuid as u64).saturating_add(1); + + let commit_epoch: u64 = Self::get_epoch_index(netuid, commit_block); + let reveal_epoch: u64 = commit_epoch.saturating_add(reveal_period); + + let first_reveal_block = reveal_epoch + .saturating_mul(tempo_plus_one) + .saturating_sub(netuid_plus_one); + let last_reveal_block = first_reveal_block.saturating_add(tempo); + + (first_reveal_block, last_reveal_block) + } + + pub fn set_reveal_period(netuid: u16, reveal_period: u64) { + RevealPeriodEpochs::::insert(netuid, reveal_period); + } + pub fn get_reveal_period(netuid: u16) -> u64 { + RevealPeriodEpochs::::get(netuid) } } diff --git a/pallets/subtensor/src/swap/swap_hotkey.rs b/pallets/subtensor/src/swap/swap_hotkey.rs index ca3d0b5a7..b16c180c4 100644 --- a/pallets/subtensor/src/swap/swap_hotkey.rs +++ b/pallets/subtensor/src/swap/swap_hotkey.rs @@ -206,33 +206,42 @@ impl Pallet { Delegates::::insert(new_hotkey, old_delegate_take); weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); } - // 9. Swap all subnet specific info. + + // 9. swap PendingdHotkeyEmission + if PendingdHotkeyEmission::::contains_key(old_hotkey) { + let old_pending_hotkey_emission = PendingdHotkeyEmission::::get(old_hotkey); + PendingdHotkeyEmission::::remove(old_hotkey); + PendingdHotkeyEmission::::insert(new_hotkey, old_pending_hotkey_emission); + weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); + } + + // 10. Swap all subnet specific info. let all_netuids: Vec = Self::get_all_subnet_netuids(); for netuid in all_netuids { - // 9.1 Remove the previous hotkey and insert the new hotkey from membership. + // 10.1 Remove the previous hotkey and insert the new hotkey from membership. // IsNetworkMember( hotkey, netuid ) -> bool -- is the hotkey a subnet member. let is_network_member: bool = IsNetworkMember::::get(old_hotkey, netuid); IsNetworkMember::::remove(old_hotkey, netuid); IsNetworkMember::::insert(new_hotkey, netuid, is_network_member); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - // 9.2 Swap Uids + Keys. + // 10.2 Swap Uids + Keys. // Keys( netuid, hotkey ) -> uid -- the uid the hotkey has in the network if it is a member. // Uids( netuid, hotkey ) -> uid -- the uids that the hotkey has. if is_network_member { - // 9.2.1 Swap the UIDS + // 10.2.1 Swap the UIDS if let Ok(old_uid) = Uids::::try_get(netuid, old_hotkey) { Uids::::remove(netuid, old_hotkey); Uids::::insert(netuid, new_hotkey, old_uid); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - // 9.2.2 Swap the keys. + // 10.2.2 Swap the keys. Keys::::insert(netuid, old_uid, new_hotkey.clone()); weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 1)); } } - // 9.3 Swap Prometheus. + // 10.3 Swap Prometheus. // Prometheus( netuid, hotkey ) -> prometheus -- the prometheus data that a hotkey has in the network. if is_network_member { if let Ok(old_prometheus_info) = Prometheus::::try_get(netuid, old_hotkey) { @@ -242,7 +251,7 @@ impl Pallet { } } - // 9.4. Swap axons. + // 10.4. Swap axons. // Axons( netuid, hotkey ) -> axon -- the axon that the hotkey has. if is_network_member { if let Ok(old_axon_info) = Axons::::try_get(netuid, old_hotkey) { @@ -252,7 +261,7 @@ impl Pallet { } } - // 9.5 Swap WeightCommits + // 10.5 Swap WeightCommits // WeightCommits( hotkey ) --> Vec -- the weight commits for the hotkey. if is_network_member { if let Ok(old_weight_commits) = WeightCommits::::try_get(netuid, old_hotkey) { @@ -262,7 +271,7 @@ impl Pallet { } } - // 9.6. Swap the subnet loaded emission. + // 10.6. Swap the subnet loaded emission. // LoadedEmission( netuid ) --> Vec<(hotkey, u64)> -- the loaded emission for the subnet. if is_network_member { if let Some(mut old_loaded_emission) = LoadedEmission::::get(netuid) { @@ -277,7 +286,7 @@ impl Pallet { } } - // 9.7. Swap neuron TLS certificates. + // 10.7. Swap neuron TLS certificates. // NeuronCertificates( netuid, hotkey ) -> Vec -- the neuron certificate for the hotkey. if is_network_member { if let Ok(old_neuron_certificates) = @@ -290,7 +299,7 @@ impl Pallet { } } - // 10. Swap Stake. + // 11. Swap Stake. // Stake( hotkey, coldkey ) -> stake -- the stake that the hotkey controls on behalf of the coldkey. let stakes: Vec<(T::AccountId, u64)> = Stake::::iter_prefix(old_hotkey).collect(); // Clear the entire old prefix here. @@ -320,7 +329,7 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); } - // 11. Swap ChildKeys. + // 12. Swap ChildKeys. // ChildKeys( parent, netuid ) --> Vec<(proportion,child)> -- the child keys of the parent. for netuid in Self::get_all_subnet_netuids() { // Get the children of the old hotkey for this subnet @@ -328,10 +337,23 @@ impl Pallet { // Remove the old hotkey's child entries ChildKeys::::remove(old_hotkey, netuid); // Insert the same child entries for the new hotkey - ChildKeys::::insert(new_hotkey, netuid, my_children); + ChildKeys::::insert(new_hotkey, netuid, my_children.clone()); + for (_, child_key_i) in my_children { + // For each child, update their parent list + let mut child_parents: Vec<(u64, T::AccountId)> = + ParentKeys::::get(child_key_i.clone(), netuid); + for parent in child_parents.iter_mut() { + // If the parent is the old hotkey, replace it with the new hotkey + if parent.1 == *old_hotkey { + parent.1 = new_hotkey.clone(); + } + } + // Update the child's parent list + ParentKeys::::insert(child_key_i, netuid, child_parents); + } } - // 12. Swap ParentKeys. + // 13. Swap ParentKeys. // ParentKeys( child, netuid ) --> Vec<(proportion,parent)> -- the parent keys of the child. for netuid in Self::get_all_subnet_netuids() { // Get the parents of the old hotkey for this subnet @@ -355,6 +377,19 @@ impl Pallet { } } + // 14. Swap Stake Delta for all coldkeys. + for (coldkey, stake_delta) in StakeDeltaSinceLastEmissionDrain::::iter_prefix(old_hotkey) + { + let new_stake_delta = StakeDeltaSinceLastEmissionDrain::::get(new_hotkey, &coldkey); + StakeDeltaSinceLastEmissionDrain::::insert( + new_hotkey, + &coldkey, + new_stake_delta.saturating_add(stake_delta), + ); + StakeDeltaSinceLastEmissionDrain::::remove(old_hotkey, &coldkey); + weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); + } + // Return successful after swapping all the relevant terms. Ok(()) } diff --git a/pallets/subtensor/src/utils/misc.rs b/pallets/subtensor/src/utils/misc.rs index 76546a1a2..57cc38786 100644 --- a/pallets/subtensor/src/utils/misc.rs +++ b/pallets/subtensor/src/utils/misc.rs @@ -486,13 +486,6 @@ impl Pallet { Kappa::::insert(netuid, kappa); Self::deposit_event(Event::KappaSet(netuid, kappa)); } - - pub fn get_commit_reveal_weights_interval(netuid: u16) -> u64 { - WeightCommitRevealInterval::::get(netuid) - } - pub fn set_commit_reveal_weights_interval(netuid: u16, interval: u64) { - WeightCommitRevealInterval::::set(netuid, interval); - } pub fn get_commit_reveal_weights_enabled(netuid: u16) -> bool { CommitRevealWeightsEnabled::::get(netuid) } diff --git a/pallets/subtensor/tests/migration.rs b/pallets/subtensor/tests/migration.rs index 6c40d7d78..4ddef882c 100644 --- a/pallets/subtensor/tests/migration.rs +++ b/pallets/subtensor/tests/migration.rs @@ -1,10 +1,19 @@ #![allow(unused, clippy::indexing_slicing, clippy::panic, clippy::unwrap_used)] mod mock; -use frame_support::{assert_ok, weights::Weight}; +use codec::{Decode, Encode}; +use frame_support::{ + assert_ok, + storage::unhashed::{get_raw, put_raw}, + traits::{StorageInstance, StoredMap}, + weights::Weight, + StorageHasher, Twox64Concat, +}; use frame_system::Config; use mock::*; use pallet_subtensor::*; -use sp_core::U256; +use sp_core::{H256, U256}; +use sp_io::hashing::twox_128; +use sp_runtime::traits::Zero; #[test] fn test_initialise_ti() { @@ -430,3 +439,92 @@ fn run_migration_and_check(migration_name: &'static str) -> frame_support::weigh // Return the weight of the executed migration weight } + +#[test] +fn test_migrate_commit_reveal_2() { + new_test_ext(1).execute_with(|| { + // ------------------------------ + // Step 1: Simulate Old Storage Entries + // ------------------------------ + const MIGRATION_NAME: &str = "migrate_commit_reveal_2_v2"; + + let pallet_prefix = twox_128("SubtensorModule".as_bytes()); + let storage_prefix_interval = twox_128("WeightCommitRevealInterval".as_bytes()); + let storage_prefix_commits = twox_128("WeightCommits".as_bytes()); + + let netuid: u16 = 1; + let interval_value: u64 = 50u64; + + // Construct the full key for WeightCommitRevealInterval + let mut interval_key = Vec::new(); + interval_key.extend_from_slice(&pallet_prefix); + interval_key.extend_from_slice(&storage_prefix_interval); + interval_key.extend_from_slice(&netuid.encode()); + + put_raw(&interval_key, &interval_value.encode()); + + let test_account: U256 = U256::from(1); + + // Construct the full key for WeightCommits (DoubleMap) + let mut commit_key = Vec::new(); + commit_key.extend_from_slice(&pallet_prefix); + commit_key.extend_from_slice(&storage_prefix_commits); + + // First key (netuid) hashed with Twox64Concat + let netuid_hashed = Twox64Concat::hash(&netuid.encode()); + commit_key.extend_from_slice(&netuid_hashed); + + // Second key (account) hashed with Twox64Concat + let account_hashed = Twox64Concat::hash(&test_account.encode()); + commit_key.extend_from_slice(&account_hashed); + + let commit_value: (H256, u64) = (H256::from_low_u64_be(42), 100); + put_raw(&commit_key, &commit_value.encode()); + + let stored_interval = get_raw(&interval_key).expect("Expected to get a value"); + assert_eq!( + u64::decode(&mut &stored_interval[..]).expect("Failed to decode interval value"), + interval_value + ); + + let stored_commit = get_raw(&commit_key).expect("Expected to get a value"); + assert_eq!( + <(H256, u64)>::decode(&mut &stored_commit[..]).expect("Failed to decode commit value"), + commit_value + ); + + assert!( + !HasMigrationRun::::get(MIGRATION_NAME.as_bytes().to_vec()), + "Migration should not have run yet" + ); + + // ------------------------------ + // Step 2: Run the Migration + // ------------------------------ + let weight = + pallet_subtensor::migrations::migrate_commit_reveal_v2::migrate_commit_reveal_2::( + ); + + assert!( + HasMigrationRun::::get(MIGRATION_NAME.as_bytes().to_vec()), + "Migration should be marked as run" + ); + + // ------------------------------ + // Step 3: Verify Migration Effects + // ------------------------------ + let stored_interval_after = get_raw(&interval_key); + assert!( + stored_interval_after.is_none(), + "WeightCommitRevealInterval should be cleared" + ); + + let stored_commit_after = get_raw(&commit_key); + assert!( + stored_commit_after.is_none(), + "WeightCommits entry should be cleared" + ); + + assert!(!weight.is_zero(), "Migration weight should be non-zero"); + }); +} diff --git a/pallets/subtensor/tests/mock.rs b/pallets/subtensor/tests/mock.rs index 6f3b44383..7a2967e8c 100644 --- a/pallets/subtensor/tests/mock.rs +++ b/pallets/subtensor/tests/mock.rs @@ -513,6 +513,24 @@ pub(crate) fn run_to_block(n: u64) { } } +#[allow(dead_code)] +pub(crate) fn step_epochs(count: u16, netuid: u16) { + for _ in 0..count { + let blocks_to_next_epoch = SubtensorModule::blocks_until_next_epoch( + netuid, + SubtensorModule::get_tempo(netuid), + SubtensorModule::get_current_block_as_u64(), + ); + step_block(blocks_to_next_epoch as u16); + + assert!(SubtensorModule::should_run_epoch( + netuid, + SubtensorModule::get_current_block_as_u64() + )); + step_block(1); + } +} + /// Increments current block by `1`, running all hooks associated with doing so, and asserts /// that the block number was in fact incremented. /// diff --git a/pallets/subtensor/tests/swap_hotkey.rs b/pallets/subtensor/tests/swap_hotkey.rs index 89938e3eb..206cc324f 100644 --- a/pallets/subtensor/tests/swap_hotkey.rs +++ b/pallets/subtensor/tests/swap_hotkey.rs @@ -342,7 +342,7 @@ fn test_swap_certificates() { ); }); } - +use sp_std::collections::vec_deque::VecDeque; // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_weight_commits --exact --nocapture #[test] fn test_swap_weight_commits() { @@ -351,12 +351,13 @@ fn test_swap_weight_commits() { let new_hotkey = U256::from(2); let coldkey = U256::from(3); let netuid = 0u16; - let weight_commits = (H256::from_low_u64_be(100), 200); + let mut weight_commits: VecDeque<(H256, u64, u64, u64)> = VecDeque::new(); + weight_commits.push_back((H256::from_low_u64_be(100), 200, 1, 1)); let mut weight = Weight::zero(); add_network(netuid, 0, 1); IsNetworkMember::::insert(old_hotkey, netuid, true); - WeightCommits::::insert(netuid, old_hotkey, weight_commits); + WeightCommits::::insert(netuid, old_hotkey, weight_commits.clone()); assert_ok!(SubtensorModule::perform_hotkey_swap( &old_hotkey, @@ -1147,3 +1148,100 @@ fn test_swap_complex_parent_child_structure() { ); }); } + +#[test] +fn test_swap_parent_hotkey_childkey_maps() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let parent_old = U256::from(1); + let coldkey = U256::from(2); + let child = U256::from(3); + let parent_new = U256::from(4); + add_network(netuid, 0, 0); + SubtensorModule::create_account_if_non_existent(&coldkey, &parent_old); + + // Set child and verify state maps + assert_ok!(SubtensorModule::do_set_children( + RuntimeOrigin::signed(coldkey), + parent_old, + netuid, + vec![(u64::MAX, child)] + )); + assert_eq!( + ParentKeys::::get(child, netuid), + vec![(u64::MAX, parent_old)] + ); + assert_eq!( + ChildKeys::::get(parent_old, netuid), + vec![(u64::MAX, child)] + ); + + // Swap + let mut weight = Weight::zero(); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &parent_old, + &parent_new, + &coldkey, + &mut weight + )); + + // Verify parent and child keys updates + assert_eq!( + ParentKeys::::get(child, netuid), + vec![(u64::MAX, parent_new)] + ); + assert_eq!( + ChildKeys::::get(parent_new, netuid), + vec![(u64::MAX, child)] + ); + }) +} + +#[test] +fn test_swap_child_hotkey_childkey_maps() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let parent = U256::from(1); + let coldkey = U256::from(2); + let child_old = U256::from(3); + let child_new = U256::from(4); + add_network(netuid, 0, 0); + SubtensorModule::create_account_if_non_existent(&coldkey, &child_old); + SubtensorModule::create_account_if_non_existent(&coldkey, &parent); + + // Set child and verify state maps + assert_ok!(SubtensorModule::do_set_children( + RuntimeOrigin::signed(coldkey), + parent, + netuid, + vec![(u64::MAX, child_old)] + )); + assert_eq!( + ParentKeys::::get(child_old, netuid), + vec![(u64::MAX, parent)] + ); + assert_eq!( + ChildKeys::::get(parent, netuid), + vec![(u64::MAX, child_old)] + ); + + // Swap + let mut weight = Weight::zero(); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &child_old, + &child_new, + &coldkey, + &mut weight + )); + + // Verify parent and child keys updates + assert_eq!( + ParentKeys::::get(child_new, netuid), + vec![(u64::MAX, parent)] + ); + assert_eq!( + ChildKeys::::get(parent, netuid), + vec![(u64::MAX, child_new)] + ); + }) +} diff --git a/pallets/subtensor/tests/weights.rs b/pallets/subtensor/tests/weights.rs index 214e3add0..7dbeba288 100644 --- a/pallets/subtensor/tests/weights.rs +++ b/pallets/subtensor/tests/weights.rs @@ -8,11 +8,13 @@ use frame_support::{ }; use mock::*; use pallet_subtensor::{Error, Owner}; +use scale_info::prelude::collections::HashMap; use sp_core::{H256, U256}; use sp_runtime::{ traits::{BlakeTwo256, DispatchInfoOf, Hash, SignedExtension}, DispatchError, }; +use sp_std::collections::vec_deque::VecDeque; use substrate_fixed::types::I32F32; /*************************** @@ -402,12 +404,17 @@ fn test_set_weights_is_root_error() { let uids = vec![0]; let weights = vec![1]; - let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; let version_key: u64 = 0; let hotkey = U256::from(1); assert_err!( - commit_reveal_set_weights(hotkey, root_netuid, uids, weights, salt, version_key), + SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey), + root_netuid, + uids.clone(), + weights.clone(), + version_key, + ), Error::::CanNotSetRootNetworkWeights ); }); @@ -430,14 +437,12 @@ fn test_weights_err_no_validator_permit() { let weights_keys: Vec = vec![1, 2]; let weight_values: Vec = vec![1, 2]; - let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; - let result = commit_reveal_set_weights( - hotkey_account_id, + let result = SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey_account_id), netuid, weights_keys, weight_values, - salt.clone(), 0, ); assert_eq!(result, Err(Error::::NeuronNoValidatorPermit.into())); @@ -448,12 +453,11 @@ fn test_weights_err_no_validator_permit() { SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkey_account_id) .expect("Not registered."); SubtensorModule::set_validator_permit_for_uid(netuid, neuron_uid, true); - let result = commit_reveal_set_weights( - hotkey_account_id, + let result = SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey_account_id), netuid, weights_keys, weight_values, - salt, 0, ); assert_ok!(result); @@ -470,7 +474,7 @@ fn test_set_weights_min_stake_failed() { let version_key: u64 = 0; let hotkey = U256::from(0); let coldkey = U256::from(0); - let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; + add_network(netuid, 0, 0); register_ok_neuron(netuid, hotkey, coldkey, 2143124); SubtensorModule::set_weights_min_stake(20_000_000_000_000); @@ -486,24 +490,22 @@ fn test_set_weights_min_stake_failed() { // Check that it fails at the pallet level. SubtensorModule::set_weights_min_stake(100_000_000_000_000); assert_eq!( - commit_reveal_set_weights( - hotkey, + SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey), netuid, dests.clone(), weights.clone(), - salt.clone(), - version_key + version_key, ), Err(Error::::NotEnoughStakeToSetWeights.into()) ); // Now passes SubtensorModule::increase_stake_on_hotkey_account(&hotkey, 100_000_000_000_000); - assert_ok!(commit_reveal_set_weights( - hotkey, + assert_ok!(SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey), netuid, dests.clone(), weights.clone(), - salt.clone(), version_key )); }); @@ -517,7 +519,7 @@ fn test_weights_version_key() { let coldkey = U256::from(66); let netuid0: u16 = 1; let netuid1: u16 = 2; - let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; + add_network(netuid0, 0, 0); add_network(netuid1, 0, 0); register_ok_neuron(netuid0, hotkey, coldkey, 2143124); @@ -525,20 +527,18 @@ fn test_weights_version_key() { let weights_keys: Vec = vec![0]; let weight_values: Vec = vec![1]; - assert_ok!(commit_reveal_set_weights( - hotkey, + assert_ok!(SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey), netuid0, weights_keys.clone(), weight_values.clone(), - salt.clone(), 0 )); - assert_ok!(commit_reveal_set_weights( - hotkey, + assert_ok!(SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey), netuid1, weights_keys.clone(), weight_values.clone(), - salt.clone(), 0 )); @@ -549,42 +549,38 @@ fn test_weights_version_key() { SubtensorModule::set_weights_version_key(netuid1, key1); // Setting works with version key. - assert_ok!(commit_reveal_set_weights( - hotkey, + assert_ok!(SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey), netuid0, weights_keys.clone(), weight_values.clone(), - salt.clone(), key0 )); - assert_ok!(commit_reveal_set_weights( - hotkey, + assert_ok!(SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey), netuid1, weights_keys.clone(), weight_values.clone(), - salt.clone(), key1 )); // validator:20313 >= network:12312 (accepted: validator newer) - assert_ok!(commit_reveal_set_weights( - hotkey, + assert_ok!(SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey), netuid0, weights_keys.clone(), weight_values.clone(), - salt.clone(), key1 )); // Setting fails with incorrect keys. // validator:12312 < network:20313 (rejected: validator not updated) assert_eq!( - commit_reveal_set_weights( - hotkey, + SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey), netuid1, weights_keys.clone(), weight_values.clone(), - salt.clone(), key0 ), Err(Error::::IncorrectWeightVersionKey.into()) @@ -734,7 +730,6 @@ fn test_weights_err_max_weight_limit() { // Add network. let netuid: u16 = 1; let tempo: u16 = 100; - let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; add_network(netuid, tempo, 0); // Set params. @@ -795,18 +790,18 @@ fn test_weights_err_max_weight_limit() { // Non self-weight fails. let uids: Vec = vec![1, 2, 3, 4]; let values: Vec = vec![u16::MAX / 4, u16::MAX / 4, u16::MAX / 54, u16::MAX / 4]; - let result = commit_reveal_set_weights(U256::from(0), 1, uids, values, salt.clone(), 0); + let result = + SubtensorModule::set_weights(RuntimeOrigin::signed(U256::from(0)), 1, uids, values, 0); assert_eq!(result, Err(Error::::MaxWeightExceeded.into())); // Self-weight is a success. let uids: Vec = vec![0]; // Self. let values: Vec = vec![u16::MAX]; // normalizes to u32::MAX - assert_ok!(commit_reveal_set_weights( - U256::from(0), + assert_ok!(SubtensorModule::set_weights( + RuntimeOrigin::signed(U256::from(0)), 1, uids, values, - salt.clone(), 0 )); }); @@ -893,19 +888,23 @@ fn test_set_weight_not_enough_values() { // Should fail because we are only setting a single value and its not the self weight. let weight_keys: Vec = vec![1]; // not weight. let weight_values: Vec = vec![88]; // random value. - let result = - commit_reveal_set_weights(account_id, 1, weight_keys, weight_values, salt.clone(), 0); + let result = SubtensorModule::set_weights( + RuntimeOrigin::signed(account_id), + 1, + weight_keys, + weight_values, + 0, + ); assert_eq!(result, Err(Error::::WeightVecLengthIsLow.into())); // Shouldnt fail because we setting a single value but it is the self weight. let weight_keys: Vec = vec![0]; // self weight. let weight_values: Vec = vec![88]; // random value. - assert_ok!(commit_reveal_set_weights( - account_id, + assert_ok!(SubtensorModule::set_weights( + RuntimeOrigin::signed(account_id), 1, weight_keys, weight_values, - salt.clone(), 0 )); @@ -930,7 +929,6 @@ fn test_set_weight_too_many_uids() { new_test_ext(0).execute_with(|| { let netuid: u16 = 1; let tempo: u16 = 13; - let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; add_network(netuid, tempo, 0); register_ok_neuron(1, U256::from(1), U256::from(2), 100_000); @@ -945,12 +943,11 @@ fn test_set_weight_too_many_uids() { // Should fail because we are setting more weights than there are neurons. let weight_keys: Vec = vec![0, 1, 2, 3, 4]; // more uids than neurons in subnet. let weight_values: Vec = vec![88, 102, 303, 1212, 11]; // random value. - let result = commit_reveal_set_weights( - U256::from(1), + let result = SubtensorModule::set_weights( + RuntimeOrigin::signed(U256::from(1)), 1, weight_keys, weight_values, - salt.clone(), 0, ); assert_eq!( @@ -961,12 +958,11 @@ fn test_set_weight_too_many_uids() { // Shouldnt fail because we are setting less weights than there are neurons. let weight_keys: Vec = vec![0, 1]; // Only on neurons that exist. let weight_values: Vec = vec![10, 10]; // random value. - assert_ok!(commit_reveal_set_weights( - U256::from(1), + assert_ok!(SubtensorModule::set_weights( + RuntimeOrigin::signed(U256::from(1)), 1, weight_keys, weight_values, - salt, 0 )); }); @@ -1372,7 +1368,7 @@ fn test_set_weights_commit_reveal_enabled_error() { } #[test] -fn test_commit_reveal_weights_ok() { +fn test_reveal_weights_when_commit_reveal_disabled() { new_test_ext(1).execute_with(|| { let netuid: u16 = 1; let uids: Vec = vec![0, 1]; @@ -1390,24 +1386,88 @@ fn test_commit_reveal_weights_ok() { version_key, )); - add_network(netuid, 0, 0); - register_ok_neuron(netuid, U256::from(3), U256::from(4), 300000); - register_ok_neuron(netuid, U256::from(1), U256::from(2), 100000); + System::set_block_number(0); + + let tempo: u16 = 5; + add_network(netuid, tempo, 0); + + // Register neurons and set up configurations + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); SubtensorModule::set_weights_set_rate_limit(netuid, 5); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); - SubtensorModule::set_commit_reveal_weights_interval(netuid, 5); + // Enable commit-reveal and commit + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + + step_epochs(1, netuid); + + // Disable commit-reveal before reveal + SubtensorModule::set_commit_reveal_weights_enabled(netuid, false); + + // Attempt to reveal, should fail with CommitRevealDisabled + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids, + weight_values, + salt, + version_key, + ), + Error::::CommitRevealDisabled + ); + }); +} + +#[test] +fn test_commit_reveal_weights_ok() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let uids: Vec = vec![0, 1]; + let weight_values: Vec = vec![10, 10]; + let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; + let version_key: u64 = 0; + let hotkey: U256 = U256::from(1); + + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + )); + + System::set_block_number(0); + + let tempo: u16 = 5; + add_network(netuid, tempo, 0); + + // Register neurons and set up configurations + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); + SubtensorModule::set_weights_set_rate_limit(netuid, 5); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + // Commit at block 0 assert_ok!(SubtensorModule::commit_weights( RuntimeOrigin::signed(hotkey), netuid, commit_hash )); - step_block(5); + step_epochs(1, netuid); + // Reveal in the next epoch assert_ok!(SubtensorModule::reveal_weights( RuntimeOrigin::signed(hotkey), netuid, @@ -1420,7 +1480,7 @@ fn test_commit_reveal_weights_ok() { } #[test] -fn test_commit_reveal_interval() { +fn test_commit_reveal_tempo_interval() { new_test_ext(1).execute_with(|| { let netuid: u16 = 1; let uids: Vec = vec![0, 1]; @@ -1438,42 +1498,26 @@ fn test_commit_reveal_interval() { version_key, )); - add_network(netuid, 0, 0); - register_ok_neuron(netuid, U256::from(3), U256::from(4), 300000); - register_ok_neuron(netuid, U256::from(1), U256::from(2), 100000); + System::set_block_number(0); + + let tempo: u16 = 100; + add_network(netuid, tempo, 0); + + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); SubtensorModule::set_weights_set_rate_limit(netuid, 5); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); - - SubtensorModule::set_commit_reveal_weights_interval(netuid, 100); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - System::set_block_number(0); + // Commit at block 0 assert_ok!(SubtensorModule::commit_weights( RuntimeOrigin::signed(hotkey), netuid, commit_hash )); - assert_err!( - SubtensorModule::commit_weights(RuntimeOrigin::signed(hotkey), netuid, commit_hash), - Error::::WeightsCommitNotAllowed - ); - assert_err!( - SubtensorModule::reveal_weights( - RuntimeOrigin::signed(hotkey), - netuid, - uids.clone(), - weight_values.clone(), - salt.clone(), - version_key, - ), - Error::::InvalidRevealCommitTempo - ); - step_block(99); - assert_err!( - SubtensorModule::commit_weights(RuntimeOrigin::signed(hotkey), netuid, commit_hash), - Error::::WeightsCommitNotAllowed - ); + + // Attempt to reveal in the same epoch, should fail assert_err!( SubtensorModule::reveal_weights( RuntimeOrigin::signed(hotkey), @@ -1483,9 +1527,11 @@ fn test_commit_reveal_interval() { salt.clone(), version_key, ), - Error::::InvalidRevealCommitTempo + Error::::RevealTooEarly ); - step_block(1); + + step_epochs(1, netuid); + assert_ok!(SubtensorModule::reveal_weights( RuntimeOrigin::signed(hotkey), netuid, @@ -1494,11 +1540,9 @@ fn test_commit_reveal_interval() { salt.clone(), version_key, )); - assert_ok!(SubtensorModule::commit_weights( - RuntimeOrigin::signed(hotkey), - netuid, - commit_hash - )); + + step_block(6); + assert_err!( SubtensorModule::reveal_weights( RuntimeOrigin::signed(hotkey), @@ -1508,25 +1552,18 @@ fn test_commit_reveal_interval() { salt.clone(), version_key, ), - Error::::InvalidRevealCommitTempo + Error::::NoWeightsCommitFound ); - step_block(100); - assert_ok!(SubtensorModule::reveal_weights( - RuntimeOrigin::signed(hotkey), - netuid, - uids.clone(), - weight_values.clone(), - salt.clone(), - version_key, - )); - // Testing that if you miss the next tempo you cannot reveal it. assert_ok!(SubtensorModule::commit_weights( RuntimeOrigin::signed(hotkey), netuid, commit_hash )); - step_block(205); + + // step two epochs + step_epochs(2, netuid); + assert_err!( SubtensorModule::reveal_weights( RuntimeOrigin::signed(hotkey), @@ -1536,30 +1573,17 @@ fn test_commit_reveal_interval() { salt.clone(), version_key, ), - Error::::InvalidRevealCommitTempo + Error::::ExpiredWeightCommit ); - // Testing when you commit but do not reveal until later intervals assert_ok!(SubtensorModule::commit_weights( RuntimeOrigin::signed(hotkey), netuid, commit_hash )); - step_block(425); - let commit_hash_2: H256 = BlakeTwo256::hash_of(&( - hotkey, - netuid, - uids.clone(), - weight_values.clone(), - salt.clone(), - version_key + 1, - )); - assert_ok!(SubtensorModule::commit_weights( - RuntimeOrigin::signed(hotkey), - netuid, - commit_hash_2 - )); - step_block(100); + + step_block(50); + assert_err!( SubtensorModule::reveal_weights( RuntimeOrigin::signed(hotkey), @@ -1569,15 +1593,18 @@ fn test_commit_reveal_interval() { salt.clone(), version_key, ), - Error::::InvalidRevealCommitHashNotMatch + Error::::RevealTooEarly ); + + step_epochs(1, netuid); + assert_ok!(SubtensorModule::reveal_weights( RuntimeOrigin::signed(hotkey), netuid, - uids.clone(), - weight_values.clone(), - salt.clone(), - version_key + 1, + uids, + weight_values, + salt, + version_key, )); }); } @@ -1589,17 +1616,19 @@ fn test_commit_reveal_hash() { let uids: Vec = vec![0, 1]; let weight_values: Vec = vec![10, 10]; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; + let bad_salt: Vec = vec![0, 2, 3, 4, 5, 6, 7, 8]; let version_key: u64 = 0; let hotkey: U256 = U256::from(1); - add_network(netuid, 0, 0); - register_ok_neuron(netuid, U256::from(3), U256::from(4), 300000); - register_ok_neuron(netuid, U256::from(1), U256::from(2), 100000); + add_network(netuid, 5, 0); + System::set_block_number(0); + + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); SubtensorModule::set_weights_set_rate_limit(netuid, 5); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); - SubtensorModule::set_commit_reveal_weights_interval(netuid, 5); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); let commit_hash: H256 = BlakeTwo256::hash_of(&( @@ -1617,8 +1646,9 @@ fn test_commit_reveal_hash() { commit_hash )); - step_block(5); + step_epochs(1, netuid); + // Attempt to reveal with incorrect data, should fail assert_err!( SubtensorModule::reveal_weights( RuntimeOrigin::signed(hotkey), @@ -1630,46 +1660,26 @@ fn test_commit_reveal_hash() { ), Error::::InvalidRevealCommitHashNotMatch ); + assert_err!( SubtensorModule::reveal_weights( RuntimeOrigin::signed(hotkey), netuid, uids.clone(), weight_values.clone(), - salt.clone(), - 7, - ), - Error::::InvalidRevealCommitHashNotMatch - ); - assert_err!( - SubtensorModule::reveal_weights( - RuntimeOrigin::signed(hotkey), - netuid, - uids.clone(), - vec![10, 9], - salt.clone(), + bad_salt.clone(), version_key, ), Error::::InvalidRevealCommitHashNotMatch ); - assert_err!( - SubtensorModule::reveal_weights( - RuntimeOrigin::signed(hotkey), - netuid, - vec![0, 1, 2], - vec![10, 10, 33], - salt.clone(), - 9, - ), - Error::::InvalidRevealCommitHashNotMatch - ); + // Correct reveal, should succeed assert_ok!(SubtensorModule::reveal_weights( RuntimeOrigin::signed(hotkey), netuid, uids, weight_values, - salt.clone(), + salt, version_key, )); }); @@ -1694,82 +1704,118 @@ fn test_commit_reveal_disabled_or_enabled() { version_key, )); - add_network(netuid, 0, 0); - register_ok_neuron(netuid, U256::from(3), U256::from(4), 300000); - register_ok_neuron(netuid, U256::from(1), U256::from(2), 100000); + add_network(netuid, 5, 0); + System::set_block_number(0); + + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); SubtensorModule::set_weights_set_rate_limit(netuid, 5); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); - SubtensorModule::set_commit_reveal_weights_interval(netuid, 5); + // Disable commit/reveal SubtensorModule::set_commit_reveal_weights_enabled(netuid, false); + // Attempt to commit, should fail assert_err!( SubtensorModule::commit_weights(RuntimeOrigin::signed(hotkey), netuid, commit_hash), Error::::CommitRevealDisabled ); - step_block(5); + // Enable commit/reveal + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - assert_err!( - SubtensorModule::reveal_weights( - RuntimeOrigin::signed(hotkey), - netuid, - uids.clone(), - weight_values.clone(), - salt.clone(), - version_key, - ), - Error::::CommitRevealDisabled - ); + // Commit should now succeed + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); - SubtensorModule::set_commit_reveal_weights_enabled(netuid + 1, true); + step_epochs(1, netuid); - //Should still fail because bad netuid - assert_err!( - SubtensorModule::commit_weights(RuntimeOrigin::signed(hotkey), netuid, commit_hash), - Error::::CommitRevealDisabled - ); + // Reveal should succeed + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids, + weight_values, + salt, + version_key, + )); + }); +} - step_block(5); +#[test] +fn test_toggle_commit_reveal_weights_and_set_weights() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let uids: Vec = vec![0, 1]; + let weight_values: Vec = vec![10, 10]; + let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; + let version_key: u64 = 0; + let hotkey: U256 = U256::from(1); - assert_err!( - SubtensorModule::reveal_weights( - RuntimeOrigin::signed(hotkey), - netuid, - uids.clone(), - weight_values.clone(), - salt.clone(), - version_key, - ), - Error::::CommitRevealDisabled - ); + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + )); + + add_network(netuid, 5, 0); + System::set_block_number(0); + + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + SubtensorModule::set_weights_set_rate_limit(netuid, 5); - // Enable and should pass + // Enable commit/reveal SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + // Commit at block 0 assert_ok!(SubtensorModule::commit_weights( RuntimeOrigin::signed(hotkey), netuid, commit_hash )); - step_block(5); + step_epochs(1, netuid); + // Reveal in the next epoch assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + )); + + // Disable commit/reveal + SubtensorModule::set_commit_reveal_weights_enabled(netuid, false); + + // Advance to allow setting weights (due to rate limit) + step_block(5); + + // Set weights directly + assert_ok!(SubtensorModule::set_weights( RuntimeOrigin::signed(hotkey), netuid, uids, weight_values, - salt.clone(), version_key, )); }); } #[test] -fn test_toggle_commit_reveal_weights_and_set_weights() { - new_test_ext(1).execute_with(|| { +fn test_tempo_change_during_commit_reveal_process() { + new_test_ext(0).execute_with(|| { let netuid: u16 = 1; let uids: Vec = vec![0, 1]; let weight_values: Vec = vec![10, 10]; @@ -1786,40 +1832,77 @@ fn test_toggle_commit_reveal_weights_and_set_weights() { version_key, )); - add_network(netuid, 0, 0); - register_ok_neuron(netuid, U256::from(3), U256::from(4), 300000); - register_ok_neuron(netuid, U256::from(1), U256::from(2), 100000); + System::set_block_number(0); + + let tempo: u16 = 100; + add_network(netuid, tempo, 0); + + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); + SubtensorModule::set_weights_set_rate_limit(netuid, 5); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::set_weights_set_rate_limit(netuid, 5); - SubtensorModule::set_commit_reveal_weights_interval(netuid, 5); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + log::info!( + "Commit successful at block {}", + SubtensorModule::get_current_block_as_u64() + ); - step_block(5); + step_block(9); + log::info!( + "Advanced to block {}", + SubtensorModule::get_current_block_as_u64() + ); - // Set weights OK - let result = SubtensorModule::set_weights( + let tempo_before_next_reveal: u16 = 200; + log::info!("Changing tempo to {}", tempo_before_next_reveal); + SubtensorModule::set_tempo(netuid, tempo_before_next_reveal); + + step_epochs(1, netuid); + log::info!( + "Advanced to block {}", + SubtensorModule::get_current_block_as_u64() + ); + + assert_ok!(SubtensorModule::reveal_weights( RuntimeOrigin::signed(hotkey), netuid, uids.clone(), weight_values.clone(), - 0, + salt.clone(), + version_key, + )); + log::info!( + "Revealed at block {}", + SubtensorModule::get_current_block_as_u64() ); - assert_ok!(result); - // Enable Commit/Reveal - SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - - // Commit is enabled the same block assert_ok!(SubtensorModule::commit_weights( RuntimeOrigin::signed(hotkey), netuid, commit_hash )); + log::info!( + "Commit successful at block {}", + SubtensorModule::get_current_block_as_u64() + ); + + let tempo: u16 = 150; + log::info!("Changing tempo to {}", tempo); + SubtensorModule::set_tempo(netuid, tempo); - step_block(5); //Step to the next commit/reveal tempo + step_epochs(1, netuid); + log::info!( + "Advanced to block {}", + SubtensorModule::get_current_block_as_u64() + ); - // Reveal OK assert_ok!(SubtensorModule::reveal_weights( RuntimeOrigin::signed(hotkey), netuid, @@ -1828,109 +1911,2280 @@ fn test_toggle_commit_reveal_weights_and_set_weights() { salt.clone(), version_key, )); + log::info!( + "Revealed at block {}", + SubtensorModule::get_current_block_as_u64() + ); - // Disable Commit/Reveal - SubtensorModule::set_commit_reveal_weights_enabled(netuid, false); + let tempo: u16 = 1050; + log::info!("Changing tempo to {}", tempo); + SubtensorModule::set_tempo(netuid, tempo); + + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + log::info!( + "Commit successful at block {}", + SubtensorModule::get_current_block_as_u64() + ); - // Cannot set weights the same block due to WeightsRateLimit - step_block(5); //step to avoid settingweightstofast + let tempo: u16 = 805; + log::info!("Changing tempo to {}", tempo); + SubtensorModule::set_tempo(netuid, tempo); - let result = SubtensorModule::set_weights( + step_epochs(1, netuid); + log::info!( + "Advanced to block {}", + SubtensorModule::get_current_block_as_u64() + ); + + assert_ok!(SubtensorModule::reveal_weights( RuntimeOrigin::signed(hotkey), netuid, uids.clone(), weight_values.clone(), - 0, + salt.clone(), + version_key, + )); + log::info!( + "Revealed at block {}", + SubtensorModule::get_current_block_as_u64() ); - assert_ok!(result); }); } #[test] -fn test_commit_reveal_bad_salt_fail() { +fn test_commit_reveal_multiple_commits() { new_test_ext(1).execute_with(|| { let netuid: u16 = 1; let uids: Vec = vec![0, 1]; let weight_values: Vec = vec![10, 10]; - let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; - let bad_salt: Vec = vec![0, 2, 3, 4, 5, 6, 7, 8]; let version_key: u64 = 0; let hotkey: U256 = U256::from(1); - let commit_hash: H256 = BlakeTwo256::hash_of(&( + System::set_block_number(0); + + let tempo: u16 = 7200; + add_network(netuid, tempo, 0); + + // Setup the network and neurons + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + + // 1. Commit 10 times successfully + let mut commit_info = Vec::new(); + for i in 0..10 { + let salt_i: Vec = vec![i; 8]; // Unique salt for each commit + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt_i.clone(), + version_key, + )); + commit_info.push((commit_hash, salt_i)); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + } + + // 2. Attempt to commit an 11th time, should fail + let salt_11: Vec = vec![11; 8]; + let commit_hash_11: H256 = BlakeTwo256::hash_of(&( hotkey, netuid, uids.clone(), weight_values.clone(), - salt.clone(), + salt_11.clone(), version_key, )); + assert_err!( + SubtensorModule::commit_weights(RuntimeOrigin::signed(hotkey), netuid, commit_hash_11), + Error::::TooManyUnrevealedCommits + ); - add_network(netuid, 0, 0); - register_ok_neuron(netuid, U256::from(3), U256::from(4), 300000); - register_ok_neuron(netuid, U256::from(1), U256::from(2), 100000); - SubtensorModule::set_weights_set_rate_limit(netuid, 5); - SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); - SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + // 3. Attempt to reveal out of order (reveal the second commit first) + // Advance to the next epoch for reveals to be valid + step_epochs(1, netuid); - SubtensorModule::set_commit_reveal_weights_interval(netuid, 5); - SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + // Try to reveal the second commit first + let (_commit_hash_2, salt_2) = &commit_info[1]; + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt_2.clone(), + version_key, + )); + + // Check that commits before the revealed one are removed + let remaining_commits = pallet_subtensor::WeightCommits::::get(netuid, hotkey) + .expect("expected 8 remaining commits"); + assert_eq!(remaining_commits.len(), 8); // 10 commits - 2 removed (index 0 and 1) + + // 4. Reveal the last commit next + let (_commit_hash_10, salt_10) = &commit_info[9]; + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt_10.clone(), + version_key, + )); + + // Remaining commits should have removed up to index 9 + let remaining_commits = pallet_subtensor::WeightCommits::::get(netuid, hotkey); + assert!(remaining_commits.is_none()); // All commits removed + // After revealing all commits, attempt to commit again should now succeed assert_ok!(SubtensorModule::commit_weights( RuntimeOrigin::signed(hotkey), netuid, - commit_hash + commit_hash_11 )); - step_block(5); + // 5. Test expired commits are removed and do not block reveals + // Commit again and let the commit expire + let salt_12: Vec = vec![12; 8]; + let commit_hash_12: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt_12.clone(), + version_key, + )); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash_12 + )); + // Advance two epochs so the commit expires + step_epochs(2, netuid); + + // Attempt to reveal the expired commit, should fail assert_err!( SubtensorModule::reveal_weights( RuntimeOrigin::signed(hotkey), netuid, uids.clone(), weight_values.clone(), - bad_salt.clone(), + salt_12.clone(), version_key, ), - Error::::InvalidRevealCommitHashNotMatch + Error::::ExpiredWeightCommit ); - }); -} -fn commit_reveal_set_weights( - hotkey: U256, - netuid: u16, - uids: Vec, - weights: Vec, - salt: Vec, - version_key: u64, -) -> DispatchResult { - SubtensorModule::set_commit_reveal_weights_interval(netuid, 5); - SubtensorModule::set_weights_set_rate_limit(netuid, 5); - SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + // Commit again and reveal after advancing to next epoch + let salt_13: Vec = vec![13; 8]; + let commit_hash_13: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt_13.clone(), + version_key, + )); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash_13 + )); - let commit_hash: H256 = BlakeTwo256::hash_of(&( - hotkey, - netuid, - uids.clone(), - weights.clone(), - salt.clone(), - version_key, - )); + step_epochs(1, netuid); - SubtensorModule::commit_weights(RuntimeOrigin::signed(hotkey), netuid, commit_hash)?; + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt_13.clone(), + version_key, + )); - step_block(5); + // 6. Ensure that attempting to reveal after the valid reveal period fails + // Commit again + let salt_14: Vec = vec![14; 8]; + let commit_hash_14: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt_14.clone(), + version_key, + )); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash_14 + )); - SubtensorModule::reveal_weights( - RuntimeOrigin::signed(hotkey), - netuid, - uids, - weights, - salt, - version_key, - )?; + // Advance beyond the valid reveal period (more than one epoch) + step_epochs(2, netuid); - Ok(()) + // Attempt to reveal, should fail + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt_14.clone(), + version_key, + ), + Error::::ExpiredWeightCommit + ); + + // 7. Attempt to reveal a commit that is not ready yet (before the reveal period) + // Commit again + let salt_15: Vec = vec![15; 8]; + let commit_hash_15: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt_15.clone(), + version_key, + )); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash_15 + )); + + // Attempt to reveal immediately, should fail + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt_15.clone(), + version_key, + ), + Error::::RevealTooEarly + ); + + step_epochs(1, netuid); + + // Now reveal should succeed + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt_15.clone(), + version_key, + )); + + // 8. Test that revealing with incorrect data (salt) fails + // Commit again + let salt_16: Vec = vec![16; 8]; + let commit_hash_16: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt_16.clone(), + version_key, + )); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash_16 + )); + + step_epochs(1, netuid); + + // Attempt to reveal with incorrect salt + let wrong_salt: Vec = vec![99; 8]; + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + wrong_salt.clone(), + version_key, + ), + Error::::InvalidRevealCommitHashNotMatch + ); + + // Reveal with correct data should succeed + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt_16.clone(), + version_key, + )); + + // 9. Test that attempting to reveal when there are no commits fails + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt_16.clone(), + version_key, + ), + Error::::NoWeightsCommitFound + ); + + // 10. Commit twice and attempt to reveal out of sequence (which is now allowed) + let salt_a: Vec = vec![21; 8]; + let commit_hash_a: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt_a.clone(), + version_key, + )); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash_a + )); + + let salt_b: Vec = vec![22; 8]; + let commit_hash_b: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt_b.clone(), + version_key, + )); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash_b + )); + + step_epochs(1, netuid); + + // Reveal the second commit first, should now succeed + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt_b.clone(), + version_key, + )); + + // Check that the first commit has been removed + let remaining_commits = pallet_subtensor::WeightCommits::::get(netuid, hotkey); + assert!(remaining_commits.is_none()); + + // Attempting to reveal the first commit should fail as it was removed + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids, + weight_values, + salt_a, + version_key, + ), + Error::::NoWeightsCommitFound + ); + }); +} + +fn commit_reveal_set_weights( + hotkey: U256, + netuid: u16, + uids: Vec, + weights: Vec, + salt: Vec, + version_key: u64, +) -> DispatchResult { + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weights.clone(), + salt.clone(), + version_key, + )); + + SubtensorModule::commit_weights(RuntimeOrigin::signed(hotkey), netuid, commit_hash)?; + + step_epochs(1, netuid); + + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids, + weights, + salt, + version_key, + )?; + + Ok(()) +} + +#[test] +fn test_expired_commits_handling_in_commit_and_reveal() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let hotkey: ::AccountId = U256::from(1); + let version_key: u64 = 0; + let uids: Vec = vec![0, 1]; + let weight_values: Vec = vec![10, 10]; + let tempo: u16 = 100; + + System::set_block_number(0); + add_network(netuid, tempo, 0); + + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + + // Register neurons + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + + // 1. Commit 5 times in epoch 0 + let mut commit_info = Vec::new(); + for i in 0..5 { + let salt: Vec = vec![i; 8]; + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + )); + commit_info.push((commit_hash, salt)); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + } + + // Advance to epoch 1 + step_epochs(1, netuid); + + // 2. Commit another 5 times in epoch 1 + for i in 5..10 { + let salt: Vec = vec![i; 8]; + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + )); + commit_info.push((commit_hash, salt)); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + } + + // 3. Attempt to commit an 11th time, should fail with TooManyUnrevealedCommits + let salt_11: Vec = vec![11; 8]; + let commit_hash_11: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt_11.clone(), + version_key, + )); + assert_err!( + SubtensorModule::commit_weights(RuntimeOrigin::signed(hotkey), netuid, commit_hash_11), + Error::::TooManyUnrevealedCommits + ); + + // 4. Advance to epoch 2 to expire the commits from epoch 0 + step_epochs(1, netuid); // Now at epoch 2 + + // 5. Attempt to commit again; should succeed after expired commits are removed + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash_11 + )); + + // 6. Verify that the number of unrevealed, non-expired commits is now 6 + let commits: VecDeque<(H256, u64, u64, u64)> = + pallet_subtensor::WeightCommits::::get(netuid, hotkey) + .expect("Expected a commit"); + assert_eq!(commits.len(), 6); // 5 non-expired commits from epoch 1 + new commit + + // 7. Attempt to reveal an expired commit (from epoch 0) + // Previous commit removed expired commits + let (_, expired_salt) = &commit_info[0]; + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + expired_salt.clone(), + version_key, + ), + Error::::InvalidRevealCommitHashNotMatch + ); + + // 8. Reveal commits from epoch 1 at current_epoch = 2 + for (_, salt) in commit_info.iter().skip(5).take(5) { + let salt = salt.clone(); + + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + )); + } + + // 9. Advance to epoch 3 to reveal the new commit + step_epochs(1, netuid); + + // 10. Reveal the new commit from epoch 2 + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt_11.clone(), + version_key, + )); + + // 10. Verify that all commits have been revealed and the queue is empty + let commits = pallet_subtensor::WeightCommits::::get(netuid, hotkey); + assert!(commits.is_none()); + + // 11. Attempt to reveal again, should fail with NoWeightsCommitFound + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt_11.clone(), + version_key, + ), + Error::::NoWeightsCommitFound + ); + + // 12. Commit again to ensure we can continue after previous commits + let salt_12: Vec = vec![12; 8]; + let commit_hash_12: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt_12.clone(), + version_key, + )); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash_12 + )); + + // Advance to next epoch (epoch 4) and reveal + step_epochs(1, netuid); + + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids, + weight_values, + salt_12, + version_key, + )); + }); +} + +#[test] +fn test_reveal_at_exact_epoch() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let hotkey: ::AccountId = U256::from(1); + let version_key: u64 = 0; + let uids: Vec = vec![0, 1]; + let weight_values: Vec = vec![10, 10]; + let tempo: u16 = 100; + + System::set_block_number(0); + add_network(netuid, tempo, 0); + + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + + let reveal_periods: Vec = vec![0, 1, 2, 7, 40, 86, 100]; + + for &reveal_period in &reveal_periods { + SubtensorModule::set_reveal_period(netuid, reveal_period); + + let salt: Vec = vec![42; 8]; + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + )); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + + // Retrieve commit information + let commit_block = SubtensorModule::get_current_block_as_u64(); + let commit_epoch = SubtensorModule::get_epoch_index(netuid, commit_block); + let reveal_epoch = commit_epoch.saturating_add(reveal_period); + + // Attempt to reveal before the allowed epoch + if reveal_period > 0 { + // Advance to epoch before the reveal epoch + if reveal_period >= 1 { + step_epochs((reveal_period - 1) as u16, netuid); + } + + // Attempt to reveal too early + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + ), + Error::::RevealTooEarly + ); + } + + // Advance to the exact reveal epoch + let current_epoch = SubtensorModule::get_epoch_index( + netuid, + SubtensorModule::get_current_block_as_u64(), + ); + if current_epoch < reveal_epoch { + step_epochs((reveal_epoch - current_epoch) as u16, netuid); + } + + // Reveal at the exact allowed epoch + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + )); + + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + ), + Error::::NoWeightsCommitFound + ); + + let new_salt: Vec = vec![43; 8]; + let new_commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + new_salt.clone(), + version_key, + )); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + new_commit_hash + )); + + // Advance past the reveal epoch to ensure commit expiration + step_epochs((reveal_period + 1) as u16, netuid); + + // Attempt to reveal after the allowed epoch + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + new_salt.clone(), + version_key, + ), + Error::::ExpiredWeightCommit + ); + + pallet_subtensor::WeightCommits::::remove(netuid, hotkey); + } + }); +} + +#[test] +fn test_tempo_and_reveal_period_change_during_commit_reveal_process() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let uids: Vec = vec![0, 1]; + let weight_values: Vec = vec![10, 10]; + let salt: Vec = vec![42; 8]; + let version_key: u64 = 0; + let hotkey: ::AccountId = U256::from(1); + + // Compute initial commit hash + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + )); + + System::set_block_number(0); + + let initial_tempo: u16 = 100; + let initial_reveal_period: u64 = 1; + add_network(netuid, initial_tempo, 0); + SubtensorModule::set_reveal_period(netuid, initial_reveal_period); + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + + // Step 1: Commit weights + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + log::info!( + "Commit successful at block {}", + SubtensorModule::get_current_block_as_u64() + ); + + // Retrieve commit block and epoch + let commit_block = SubtensorModule::get_current_block_as_u64(); + let commit_epoch = SubtensorModule::get_epoch_index(netuid, commit_block); + + // Step 2: Change tempo and reveal period after commit + let new_tempo: u16 = 50; + let new_reveal_period: u64 = 2; + SubtensorModule::set_tempo(netuid, new_tempo); + SubtensorModule::set_reveal_period(netuid, new_reveal_period); + log::info!( + "Changed tempo to {} and reveal period to {}", + new_tempo, + new_reveal_period + ); + + // Step 3: Advance blocks to reach the reveal epoch according to new tempo and reveal period + let current_block = SubtensorModule::get_current_block_as_u64(); + let current_epoch = SubtensorModule::get_epoch_index(netuid, current_block); + let reveal_epoch = commit_epoch.saturating_add(new_reveal_period); + + // Advance to one epoch before reveal epoch + if current_epoch < reveal_epoch { + let epochs_to_advance = reveal_epoch - current_epoch - 1; + step_epochs(epochs_to_advance as u16, netuid); + } + + // Attempt to reveal too early + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key + ), + Error::::RevealTooEarly + ); + log::info!( + "Attempted to reveal too early at block {}", + SubtensorModule::get_current_block_as_u64() + ); + + // Advance to reveal epoch + step_epochs(1, netuid); + + // Attempt to reveal at the correct epoch + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key + )); + log::info!( + "Revealed weights at block {}", + SubtensorModule::get_current_block_as_u64() + ); + + // Step 4: Change tempo and reveal period again after reveal + let new_tempo_after_reveal: u16 = 200; + let new_reveal_period_after_reveal: u64 = 1; + SubtensorModule::set_tempo(netuid, new_tempo_after_reveal); + SubtensorModule::set_reveal_period(netuid, new_reveal_period_after_reveal); + log::info!( + "Changed tempo to {} and reveal period to {} after reveal", + new_tempo_after_reveal, + new_reveal_period_after_reveal + ); + + // Step 5: Commit again + let new_salt: Vec = vec![43; 8]; + let new_commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + new_salt.clone(), + version_key, + )); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + new_commit_hash + )); + log::info!( + "Commit successful at block {}", + SubtensorModule::get_current_block_as_u64() + ); + + // Retrieve new commit block and epoch + let new_commit_block = SubtensorModule::get_current_block_as_u64(); + let new_commit_epoch = SubtensorModule::get_epoch_index(netuid, new_commit_block); + let new_reveal_epoch = new_commit_epoch.saturating_add(new_reveal_period_after_reveal); + + // Advance to reveal epoch + let current_block = SubtensorModule::get_current_block_as_u64(); + let current_epoch = SubtensorModule::get_epoch_index(netuid, current_block); + if current_epoch < new_reveal_epoch { + let epochs_to_advance = new_reveal_epoch - current_epoch; + step_epochs(epochs_to_advance as u16, netuid); + } + + // Attempt to reveal at the correct epoch + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + new_salt.clone(), + version_key + )); + log::info!( + "Revealed weights at block {}", + SubtensorModule::get_current_block_as_u64() + ); + + // Step 6: Attempt to reveal after the allowed epoch (commit expires) + // Advance past the reveal epoch + let expiration_epochs = 1; + step_epochs(expiration_epochs as u16, netuid); + + // Attempt to reveal again (should fail due to expired commit) + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + new_salt.clone(), + version_key + ), + Error::::NoWeightsCommitFound + ); + log::info!( + "Attempted to reveal after expiration at block {}", + SubtensorModule::get_current_block_as_u64() + ); + }); +} + +#[test] +fn test_commit_reveal_order_enforcement() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let hotkey: ::AccountId = U256::from(1); + let version_key: u64 = 0; + let uids: Vec = vec![0, 1]; + let weight_values: Vec = vec![10, 10]; + let tempo: u16 = 100; + + System::set_block_number(0); + add_network(netuid, tempo, 0); + + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + + // Commit three times: A, B, C + let mut commit_info = Vec::new(); + for i in 0..3 { + let salt: Vec = vec![i; 8]; + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + )); + commit_info.push((commit_hash, salt)); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + } + + step_epochs(1, netuid); + + // Attempt to reveal B first (index 1), should now succeed + let (_commit_hash_b, salt_b) = &commit_info[1]; + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt_b.clone(), + version_key, + )); + + // Check that commits A and B are removed + let remaining_commits = pallet_subtensor::WeightCommits::::get(netuid, hotkey) + .expect("expected 1 remaining commit"); + assert_eq!(remaining_commits.len(), 1); // Only commit C should remain + + // Attempt to reveal C (index 2), should succeed + let (_commit_hash_c, salt_c) = &commit_info[2]; + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt_c.clone(), + version_key, + )); + + // Attempting to reveal A (index 0) should fail as it's been removed + let (_commit_hash_a, salt_a) = &commit_info[0]; + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids, + weight_values, + salt_a.clone(), + version_key, + ), + Error::::NoWeightsCommitFound + ); + }); +} + +#[test] +fn test_reveal_at_exact_block() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let hotkey: ::AccountId = U256::from(1); + let version_key: u64 = 0; + let uids: Vec = vec![0, 1]; + let weight_values: Vec = vec![10, 10]; + let tempo: u16 = 360; + + System::set_block_number(0); + add_network(netuid, tempo, 0); + + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + + let reveal_periods: Vec = vec![ + 0, + 1, + 2, + 5, + 19, + 21, + 30, + 77, + 104, + 833, + 1999, + 36398, + u32::MAX as u64, + ]; + + for &reveal_period in &reveal_periods { + SubtensorModule::set_reveal_period(netuid, reveal_period); + + // Step 1: Commit weights + let salt: Vec = vec![42 + (reveal_period % 100) as u16; 8]; + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + )); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + + let commit_block = SubtensorModule::get_current_block_as_u64(); + let commit_epoch = SubtensorModule::get_epoch_index(netuid, commit_block); + let reveal_epoch = commit_epoch.saturating_add(reveal_period); + + // Calculate the block number where the reveal epoch starts + let tempo_plus_one = (tempo as u64).saturating_add(1); + let netuid_plus_one = (netuid as u64).saturating_add(1); + let reveal_epoch_start_block = reveal_epoch + .saturating_mul(tempo_plus_one) + .saturating_sub(netuid_plus_one); + + // Attempt to reveal before the reveal epoch starts + let current_block = SubtensorModule::get_current_block_as_u64(); + if current_block < reveal_epoch_start_block { + // Advance to one block before the reveal epoch starts + let blocks_to_advance = reveal_epoch_start_block.saturating_sub(current_block); + if blocks_to_advance > 1 { + // Advance to one block before the reveal epoch + let new_block_number = current_block + blocks_to_advance - 1; + System::set_block_number(new_block_number); + } + + // Attempt to reveal too early + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key + ), + Error::::RevealTooEarly + ); + + // Advance one more block to reach the exact reveal epoch start block + System::set_block_number(reveal_epoch_start_block); + } else { + // If we're already at or past the reveal epoch start block + System::set_block_number(reveal_epoch_start_block); + } + + // Reveal at the exact allowed block + assert_ok!(SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key + )); + + // Attempt to reveal again; should fail with NoWeightsCommitFound + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key + ), + Error::::NoWeightsCommitFound + ); + + // Commit again with new salt + let new_salt: Vec = vec![43 + (reveal_period % 100) as u16; 8]; + let new_commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + new_salt.clone(), + version_key, + )); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + new_commit_hash + )); + + // Advance blocks to after the commit expires + let commit_block = SubtensorModule::get_current_block_as_u64(); + let commit_epoch = SubtensorModule::get_epoch_index(netuid, commit_block); + let reveal_epoch = commit_epoch.saturating_add(reveal_period); + let expiration_epoch = reveal_epoch.saturating_add(1); + let expiration_epoch_start_block = expiration_epoch + .saturating_mul(tempo_plus_one) + .saturating_sub(netuid_plus_one); + + let current_block = SubtensorModule::get_current_block_as_u64(); + if current_block < expiration_epoch_start_block { + // Advance to the block where the commit expires + System::set_block_number(expiration_epoch_start_block); + } + + // Attempt to reveal after the commit has expired + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + new_salt.clone(), + version_key + ), + Error::::ExpiredWeightCommit + ); + + // Clean up for next iteration + pallet_subtensor::WeightCommits::::remove(netuid, hotkey); + } + }); +} + +#[test] +fn test_successful_batch_reveal() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let hotkey = U256::from(1); + let version_keys: Vec = vec![0, 0, 0]; + let uids_list: Vec> = vec![vec![0, 1], vec![1, 0], vec![0, 1]]; + let weight_values_list: Vec> = vec![vec![10, 20], vec![30, 40], vec![50, 60]]; + let tempo: u16 = 100; + + System::set_block_number(0); + add_network(netuid, tempo, 0); + + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + + // 1. Commit multiple times + let mut commit_info = Vec::new(); + for i in 0..3 { + let salt: Vec = vec![i as u16; 8]; + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids_list[i].clone(), + weight_values_list[i].clone(), + salt.clone(), + version_keys[i], + )); + commit_info.push((commit_hash, salt)); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + } + + step_epochs(1, netuid); + + // 2. Prepare batch reveal parameters + let salts_list: Vec> = commit_info.iter().map(|(_, salt)| salt.clone()).collect(); + + // 3. Perform batch reveal + assert_ok!(SubtensorModule::do_batch_reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids_list.clone(), + weight_values_list.clone(), + salts_list.clone(), + version_keys.clone(), + )); + + // 4. Ensure all commits are removed + let commits = pallet_subtensor::WeightCommits::::get(netuid, hotkey); + assert!(commits.is_none()); + }); +} + +#[test] +fn test_batch_reveal_with_expired_commits() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let hotkey = U256::from(1); + let version_keys: Vec = vec![0, 0, 0]; + let uids_list: Vec> = vec![vec![0, 1], vec![1, 0], vec![0, 1]]; + let weight_values_list: Vec> = vec![vec![10, 20], vec![30, 40], vec![50, 60]]; + let tempo: u16 = 100; + + System::set_block_number(0); + add_network(netuid, tempo, 0); + + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + + let mut commit_info = Vec::new(); + + // 1. Commit the first weight in epoch 0 + let salt0: Vec = vec![0u16; 8]; + let commit_hash0: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids_list[0].clone(), + weight_values_list[0].clone(), + salt0.clone(), + version_keys[0], + )); + commit_info.push((commit_hash0, salt0)); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash0 + )); + + // Advance to epoch 1 + step_epochs(1, netuid); + + // 2. Commit the next two weights in epoch 1 + for i in 1..3 { + let salt: Vec = vec![i as u16; 8]; + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids_list[i].clone(), + weight_values_list[i].clone(), + salt.clone(), + version_keys[i], + )); + commit_info.push((commit_hash, salt)); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + } + + // Advance to epoch 2 (after reveal period for first commit) + step_epochs(1, netuid); + + // 3. Prepare batch reveal parameters + let salts_list: Vec> = commit_info.iter().map(|(_, salt)| salt.clone()).collect(); + + // 4. Perform batch reveal + let result = SubtensorModule::do_batch_reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids_list.clone(), + weight_values_list.clone(), + salts_list.clone(), + version_keys.clone(), + ); + assert_err!(result, Error::::ExpiredWeightCommit); + + // 5. Expired commit is not removed until a successful call + let commits = pallet_subtensor::WeightCommits::::get(netuid, hotkey) + .expect("Expected remaining commits"); + assert_eq!(commits.len(), 3); + + // 6. Try revealing the remaining commits + let valid_uids_list = uids_list[1..].to_vec(); + let valid_weight_values_list = weight_values_list[1..].to_vec(); + let valid_salts_list = salts_list[1..].to_vec(); + let valid_version_keys = version_keys[1..].to_vec(); + + assert_ok!(SubtensorModule::do_batch_reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + valid_uids_list, + valid_weight_values_list, + valid_salts_list, + valid_version_keys, + )); + + // 7. Ensure all commits are removed + let commits = pallet_subtensor::WeightCommits::::get(netuid, hotkey); + assert!(commits.is_none()); + }); +} + +#[test] +fn test_batch_reveal_with_invalid_input_lengths() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let hotkey = U256::from(1); + let tempo: u16 = 100; + + System::set_block_number(0); + add_network(netuid, tempo, 0); + + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + + // Base data for valid inputs + let uids_list: Vec> = vec![vec![0, 1], vec![1, 0]]; + let weight_values_list: Vec> = vec![vec![10, 20], vec![30, 40]]; + let salts_list: Vec> = vec![vec![0u16; 8], vec![1u16; 8]]; + let version_keys: Vec = vec![0, 0]; + + // Test cases with mismatched input lengths + + // Case 1: uids_list has an extra element + let uids_list_case = vec![vec![0, 1], vec![1, 0], vec![2, 3]]; + let result = SubtensorModule::do_batch_reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids_list_case.clone(), + weight_values_list.clone(), + salts_list.clone(), + version_keys.clone(), + ); + assert_err!(result, Error::::InputLengthsUnequal); + + // Case 2: weight_values_list has an extra element + let weight_values_list_case = vec![vec![10, 20], vec![30, 40], vec![50, 60]]; + let result = SubtensorModule::do_batch_reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids_list.clone(), + weight_values_list_case.clone(), + salts_list.clone(), + version_keys.clone(), + ); + assert_err!(result, Error::::InputLengthsUnequal); + + // Case 3: salts_list has an extra element + let salts_list_case = vec![vec![0u16; 8], vec![1u16; 8], vec![2u16; 8]]; + let result = SubtensorModule::do_batch_reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids_list.clone(), + weight_values_list.clone(), + salts_list_case.clone(), + version_keys.clone(), + ); + assert_err!(result, Error::::InputLengthsUnequal); + + // Case 4: version_keys has an extra element + let version_keys_case = vec![0, 0, 0]; + let result = SubtensorModule::do_batch_reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids_list.clone(), + weight_values_list.clone(), + salts_list.clone(), + version_keys_case.clone(), + ); + assert_err!(result, Error::::InputLengthsUnequal); + + // Case 5: All input vectors have mismatched lengths + let uids_list_case = vec![vec![0, 1]]; + let weight_values_list_case = vec![vec![10, 20], vec![30, 40]]; + let salts_list_case = vec![vec![0u16; 8]]; + let version_keys_case = vec![0, 0, 0]; + let result = SubtensorModule::do_batch_reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids_list_case, + weight_values_list_case, + salts_list_case, + version_keys_case, + ); + assert_err!(result, Error::::InputLengthsUnequal); + + // Case 6: Valid input lengths (should not return an error) + let result = SubtensorModule::do_batch_reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids_list.clone(), + weight_values_list.clone(), + salts_list.clone(), + version_keys.clone(), + ); + // We expect an error because no commits have been made, but it should not be InputLengthsUnequal + assert_err!(result, Error::::NoWeightsCommitFound); + }); +} + +#[test] +fn test_batch_reveal_with_no_commits() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let hotkey = U256::from(1); + let version_keys: Vec = vec![0]; + let uids_list: Vec> = vec![vec![0, 1]]; + let weight_values_list: Vec> = vec![vec![10, 20]]; + let salts_list: Vec> = vec![vec![0u16; 8]]; + let tempo: u16 = 100; + + System::set_block_number(0); + add_network(netuid, tempo, 0); + + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + + // 1. Attempt to perform batch reveal without any commits + let result = SubtensorModule::do_batch_reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids_list, + weight_values_list, + salts_list, + version_keys, + ); + assert_err!(result, Error::::NoWeightsCommitFound); + }); +} + +#[test] +fn test_batch_reveal_before_reveal_period() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let hotkey = U256::from(1); + let version_keys: Vec = vec![0, 0]; + let uids_list: Vec> = vec![vec![0, 1], vec![1, 0]]; + let weight_values_list: Vec> = vec![vec![10, 20], vec![30, 40]]; + let tempo: u16 = 100; + + System::set_block_number(0); + add_network(netuid, tempo, 0); + + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + + // 1. Commit multiple times in the same epoch + let mut commit_info = Vec::new(); + for i in 0..2 { + let salt: Vec = vec![i as u16; 8]; + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids_list[i].clone(), + weight_values_list[i].clone(), + salt.clone(), + version_keys[i], + )); + commit_info.push((commit_hash, salt)); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + } + + // 2. Prepare batch reveal parameters + let salts_list: Vec> = commit_info.iter().map(|(_, salt)| salt.clone()).collect(); + + // 3. Attempt to reveal before reveal period + let result = SubtensorModule::do_batch_reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids_list.clone(), + weight_values_list.clone(), + salts_list.clone(), + version_keys.clone(), + ); + assert_err!(result, Error::::RevealTooEarly); + }); +} + +#[test] +fn test_batch_reveal_after_commits_expired() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let hotkey = U256::from(1); + let version_keys: Vec = vec![0, 0]; + let uids_list: Vec> = vec![vec![0, 1], vec![1, 0]]; + let weight_values_list: Vec> = vec![vec![10, 20], vec![30, 40]]; + let tempo: u16 = 100; + + System::set_block_number(0); + add_network(netuid, tempo, 0); + + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + + let mut commit_info = Vec::new(); + + // 1. Commit the first weight in epoch 0 + let salt0: Vec = vec![0u16; 8]; + let commit_hash0: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids_list[0].clone(), + weight_values_list[0].clone(), + salt0.clone(), + version_keys[0], + )); + commit_info.push((commit_hash0, salt0)); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash0 + )); + + // Advance to epoch 1 + step_epochs(1, netuid); + + // 2. Commit the second weight in epoch 1 + let salt1: Vec = vec![1u16; 8]; + let commit_hash1: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids_list[1].clone(), + weight_values_list[1].clone(), + salt1.clone(), + version_keys[1], + )); + commit_info.push((commit_hash1, salt1)); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash1 + )); + + // Advance to epoch 4 to ensure both commits have expired (assuming reveal_period is 1) + step_epochs(3, netuid); + + // 3. Prepare batch reveal parameters + let salts_list: Vec> = commit_info.iter().map(|(_, salt)| salt.clone()).collect(); + + // 4. Attempt to reveal after commits have expired + let result = SubtensorModule::do_batch_reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids_list.clone(), + weight_values_list.clone(), + salts_list, + version_keys.clone(), + ); + assert_err!(result, Error::::ExpiredWeightCommit); + }); +} + +#[test] +fn test_batch_reveal_when_commit_reveal_disabled() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let hotkey = U256::from(1); + let version_keys: Vec = vec![0]; + let uids_list: Vec> = vec![vec![0, 1]]; + let weight_values_list: Vec> = vec![vec![10, 20]]; + let salts_list: Vec> = vec![vec![0u16; 8]]; + let tempo: u16 = 100; + + System::set_block_number(0); + add_network(netuid, tempo, 0); + + SubtensorModule::set_commit_reveal_weights_enabled(netuid, false); + + // 1. Attempt to perform batch reveal when commit-reveal is disabled + let result = SubtensorModule::do_batch_reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids_list, + weight_values_list, + salts_list, + version_keys, + ); + assert_err!(result, Error::::CommitRevealDisabled); + }); +} + +#[test] +fn test_batch_reveal_with_out_of_order_commits() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let hotkey = U256::from(1); + let version_keys: Vec = vec![0, 0, 0]; + let uids_list: Vec> = vec![vec![0, 1], vec![1, 0], vec![0, 1]]; + let weight_values_list: Vec> = vec![vec![10, 20], vec![30, 40], vec![50, 60]]; + let tempo: u16 = 100; + + System::set_block_number(0); + add_network(netuid, tempo, 0); + + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + + // 1. Commit multiple times (A, B, C) + let mut commit_info = Vec::new(); + for i in 0..3 { + let salt: Vec = vec![i as u16; 8]; + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids_list[i].clone(), + weight_values_list[i].clone(), + salt.clone(), + version_keys[i], + )); + commit_info.push((commit_hash, salt)); + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + } + + step_epochs(1, netuid); + + // 2. Prepare batch reveal parameters for commits A and C (out of order) + let salts_list: Vec> = vec![ + commit_info[2].1.clone(), // Third commit (C) + commit_info[0].1.clone(), // First commit (A) + ]; + let uids_list_out_of_order = vec![ + uids_list[2].clone(), // C + uids_list[0].clone(), // A + ]; + let weight_values_list_out_of_order = vec![ + weight_values_list[2].clone(), // C + weight_values_list[0].clone(), // A + ]; + let version_keys_out_of_order = vec![ + version_keys[2], // C + version_keys[0], // A + ]; + + // 3. Attempt batch reveal of A and C out of order + let result = SubtensorModule::do_batch_reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids_list_out_of_order, + weight_values_list_out_of_order, + salts_list, + version_keys_out_of_order, + ); + + // 4. Ensure the batch reveal succeeds + assert_ok!(result); + + // 5. Prepare and reveal the remaining commit (B) + let remaining_salt = commit_info[1].1.clone(); + let remaining_uids = uids_list[1].clone(); + let remaining_weights = weight_values_list[1].clone(); + let remaining_version_key = version_keys[1]; + + assert_ok!(SubtensorModule::do_batch_reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + vec![remaining_uids], + vec![remaining_weights], + vec![remaining_salt], + vec![remaining_version_key], + )); + + // 6. Ensure all commits are removed + let commits = pallet_subtensor::WeightCommits::::get(netuid, hotkey); + assert!(commits.is_none()); + }); +} + +#[test] +fn test_highly_concurrent_commits_and_reveals_with_multiple_hotkeys() { + new_test_ext(1).execute_with(|| { + // ==== Test Configuration ==== + let netuid: u16 = 1; + let num_hotkeys: usize = 10; + let max_unrevealed_commits: usize = 10; + let commits_per_hotkey: usize = 20; + let initial_reveal_period: u64 = 5; + let initial_tempo: u16 = 100; + + // ==== Setup Network ==== + add_network(netuid, initial_tempo, 0); + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_reveal_period(netuid, initial_reveal_period); + SubtensorModule::set_max_registrations_per_block(netuid, u16::MAX); + SubtensorModule::set_target_registrations_per_interval(netuid, u16::MAX); + + // ==== Register Validators ==== + for uid in 0..5 { + let validator_id = U256::from(100 + uid as u64); + register_ok_neuron(netuid, validator_id, U256::from(200 + uid as u64), 300_000); + SubtensorModule::set_validator_permit_for_uid(netuid, uid, true); + } + + // ==== Register Hotkeys ==== + let mut hotkeys: Vec<::AccountId> = Vec::new(); + for i in 0..num_hotkeys { + let hotkey_id = U256::from(1000 + i as u64); + register_ok_neuron(netuid, hotkey_id, U256::from(2000 + i as u64), 100_000); + hotkeys.push(hotkey_id); + } + + // ==== Initialize Commit Information ==== + let mut commit_info_map: HashMap< + ::AccountId, + Vec<(H256, Vec, Vec, Vec, u64)>, + > = HashMap::new(); + + // Initialize the map + for hotkey in &hotkeys { + commit_info_map.insert(*hotkey, Vec::new()); + } + + // ==== Function to Generate Unique Data ==== + fn generate_unique_data(index: usize) -> (Vec, Vec, Vec, u64) { + let uids = vec![index as u16, (index + 1) as u16]; + let values = vec![(index * 10) as u16, ((index + 1) * 10) as u16]; + let salt = vec![(index % 100) as u16; 8]; + let version_key = index as u64; + (uids, values, salt, version_key) + } + + // ==== Simulate Concurrent Commits and Reveals ==== + for i in 0..commits_per_hotkey { + for hotkey in &hotkeys { + + let current_commits = pallet_subtensor::WeightCommits::::get(netuid, hotkey) + .unwrap_or_default(); + if current_commits.len() >= max_unrevealed_commits { + continue; + } + + let (uids, values, salt, version_key) = generate_unique_data(i); + let commit_hash: H256 = BlakeTwo256::hash_of(&( + *hotkey, + netuid, + uids.clone(), + values.clone(), + salt.clone(), + version_key, + )); + + if let Some(commits) = commit_info_map.get_mut(hotkey) { + commits.push((commit_hash, salt.clone(), uids.clone(), values.clone(), version_key)); + } + + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(*hotkey), + netuid, + commit_hash + )); + } + + // ==== Reveal Phase ==== + for hotkey in &hotkeys { + if let Some(commits) = commit_info_map.get_mut(hotkey) { + if commits.is_empty() { + continue; // No commits to reveal + } + + let (_commit_hash, salt, uids, values, version_key) = commits.first().expect("expected a value"); + + let reveal_result = SubtensorModule::reveal_weights( + RuntimeOrigin::signed(*hotkey), + netuid, + uids.clone(), + values.clone(), + salt.clone(), + *version_key, + ); + + match reveal_result { + Ok(_) => { + commits.remove(0); + } + Err(e) => { + if e == Error::::RevealTooEarly.into() + || e == Error::::ExpiredWeightCommit.into() + || e == Error::::InvalidRevealCommitHashNotMatch.into() + { + log::info!("Expected error during reveal after epoch advancement: {:?}", e); + } else { + panic!( + "Unexpected error during reveal: {:?}, expected RevealTooEarly, ExpiredWeightCommit, or InvalidRevealCommitHashNotMatch", + e + ); + } + } + } + } + } + } + + // ==== Modify Network Parameters During Commits ==== + SubtensorModule::set_tempo(netuid, 150); + SubtensorModule::set_reveal_period(netuid, 7); + log::info!("Changed tempo to 150 and reveal_period to 7 during commits."); + + step_epochs(3, netuid); + + // ==== Continue Reveals After Epoch Advancement ==== + for hotkey in &hotkeys { + if let Some(commits) = commit_info_map.get_mut(hotkey) { + while !commits.is_empty() { + let (_commit_hash, salt, uids, values, version_key) = &commits[0]; + + // Attempt to reveal + let reveal_result = SubtensorModule::reveal_weights( + RuntimeOrigin::signed(*hotkey), + netuid, + uids.clone(), + values.clone(), + salt.clone(), + *version_key, + ); + + match reveal_result { + Ok(_) => { + commits.remove(0); + } + Err(e) => { + // Check if the error is due to reveal being too early or commit expired + if e == Error::::RevealTooEarly.into() + || e == Error::::ExpiredWeightCommit.into() + || e == Error::::InvalidRevealCommitHashNotMatch.into() + { + log::info!("Expected error during reveal after epoch advancement: {:?}", e); + break; + } else { + panic!( + "Unexpected error during reveal after epoch advancement: {:?}, expected RevealTooEarly, ExpiredWeightCommit, or InvalidRevealCommitHashNotMatch", + e + ); + } + } + } + } + } + } + + // ==== Change Network Parameters Again ==== + SubtensorModule::set_tempo(netuid, 200); + SubtensorModule::set_reveal_period(netuid, 10); + log::info!("Changed tempo to 200 and reveal_period to 10 after initial reveals."); + + step_epochs(10, netuid); + + // ==== Final Reveal Attempts ==== + for (hotkey, commits) in commit_info_map.iter_mut() { + for (_commit_hash, salt, uids, values, version_key) in commits.iter() { + let reveal_result = SubtensorModule::reveal_weights( + RuntimeOrigin::signed(*hotkey), + netuid, + uids.clone(), + values.clone(), + salt.clone(), + *version_key, + ); + + assert_eq!( + reveal_result, + Err(Error::::ExpiredWeightCommit.into()), + "Expected ExpiredWeightCommit error, got {:?}", + reveal_result + ); + } + } + + for hotkey in &hotkeys { + commit_info_map.insert(*hotkey, Vec::new()); + + for i in 0..max_unrevealed_commits { + let (uids, values, salt, version_key) = generate_unique_data(i + commits_per_hotkey); + let commit_hash: H256 = BlakeTwo256::hash_of(&( + *hotkey, + netuid, + uids.clone(), + values.clone(), + salt.clone(), + version_key, + )); + + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(*hotkey), + netuid, + commit_hash + )); + } + + let (uids, values, salt, version_key) = generate_unique_data(max_unrevealed_commits + commits_per_hotkey); + let commit_hash: H256 = BlakeTwo256::hash_of(&( + *hotkey, + netuid, + uids.clone(), + values.clone(), + salt.clone(), + version_key, + )); + + assert_err!( + SubtensorModule::commit_weights( + RuntimeOrigin::signed(*hotkey), + netuid, + commit_hash + ), + Error::::TooManyUnrevealedCommits + ); + } + + // Attempt unauthorized reveal + let unauthorized_hotkey = hotkeys[0]; + let target_hotkey = hotkeys[1]; + if let Some(commits) = commit_info_map.get(&target_hotkey) { + if let Some((_commit_hash, salt, uids, values, version_key)) = commits.first() { + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(unauthorized_hotkey), + netuid, + uids.clone(), + values.clone(), + salt.clone(), + *version_key, + ), + Error::::InvalidRevealCommitHashNotMatch + ); + } + } + + let non_committing_hotkey: ::AccountId = U256::from(9999); + assert_err!( + SubtensorModule::reveal_weights( + RuntimeOrigin::signed(non_committing_hotkey), + netuid, + vec![0, 1], + vec![10, 20], + vec![0; 8], + 0, + ), + Error::::NoWeightsCommitFound + ); + + assert_eq!(SubtensorModule::get_reveal_period(netuid), 10); + assert_eq!(SubtensorModule::get_tempo(netuid), 200); + }) +} + +#[test] +fn test_get_reveal_blocks() { + new_test_ext(1).execute_with(|| { + // **1. Define Test Parameters** + let netuid: u16 = 1; + let uids: Vec = vec![0, 1]; + let weight_values: Vec = vec![10, 10]; + let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; + let version_key: u64 = 0; + let hotkey: U256 = U256::from(1); + + // **2. Generate the Commit Hash** + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + )); + + // **3. Initialize the Block Number to 0** + System::set_block_number(0); + + // **4. Define Network Parameters** + let tempo: u16 = 5; + add_network(netuid, tempo, 0); + + // **5. Register Neurons and Configure the Network** + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); + SubtensorModule::set_weights_set_rate_limit(netuid, 5); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + + // **6. Commit Weights at Block 0** + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + + // **7. Retrieve the Reveal Blocks Using `get_reveal_blocks`** + let (first_reveal_block, last_reveal_block) = SubtensorModule::get_reveal_blocks(netuid, 0); + + // **8. Assert Correct Calculation of Reveal Blocks** + // With tempo=5, netuid=1, reveal_period=1: + // commit_epoch = (0 + 2) / 6 = 0 + // reveal_epoch = 0 + 1 = 1 + // first_reveal_block = 1 * 6 - 2 = 4 + // last_reveal_block = 4 + 5 = 9 + assert_eq!(first_reveal_block, 4); + assert_eq!(last_reveal_block, 9); + + // **9. Attempt to Reveal Before `first_reveal_block` (Block 3)** + step_block(3); // Advance to block 3 + let result = SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + ); + assert_err!(result, Error::::RevealTooEarly); + + // **10. Advance to `first_reveal_block` (Block 4)** + step_block(1); // Advance to block 4 + let result = SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + ); + assert_ok!(result); + + // **11. Attempt to Reveal Again at Block 4 (Should Fail)** + let result = SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + ); + assert_err!(result, Error::::NoWeightsCommitFound); + + // **12. Advance to After `last_reveal_block` (Block 10)** + step_block(6); // Advance from block 4 to block 10 + + // **13. Attempt to Reveal at Block 10 (Should Fail)** + let result = SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + ); + assert_err!(result, Error::::NoWeightsCommitFound); + + // **14. Attempt to Reveal Outside of Any Reveal Window (No Commit)** + let result = SubtensorModule::reveal_weights( + RuntimeOrigin::signed(hotkey), + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + ); + assert_err!(result, Error::::NoWeightsCommitFound); + + // **15. Verify that All Commits Have Been Removed from Storage** + let commits = pallet_subtensor::WeightCommits::::get(netuid, hotkey); + assert!( + commits.is_none(), + "Commits should be cleared after successful reveal" + ); + }) +} + +#[test] +fn test_commit_weights_rate_limit() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let uids: Vec = vec![0, 1]; + let weight_values: Vec = vec![10, 10]; + let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; + let version_key: u64 = 0; + let hotkey: U256 = U256::from(1); + + let commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + salt.clone(), + version_key, + )); + System::set_block_number(11); + + let tempo: u16 = 5; + add_network(netuid, tempo, 0); + + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); + register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); + SubtensorModule::set_weights_set_rate_limit(netuid, 10); // Rate limit is 10 blocks + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + + let neuron_uid = + SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkey).expect("expected uid"); + SubtensorModule::set_last_update_for_uid(netuid, neuron_uid, 0); + + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + commit_hash + )); + + let new_salt: Vec = vec![9; 8]; + let new_commit_hash: H256 = BlakeTwo256::hash_of(&( + hotkey, + netuid, + uids.clone(), + weight_values.clone(), + new_salt.clone(), + version_key, + )); + assert_err!( + SubtensorModule::commit_weights(RuntimeOrigin::signed(hotkey), netuid, new_commit_hash), + Error::::CommittingWeightsTooFast + ); + + step_block(5); + assert_err!( + SubtensorModule::commit_weights(RuntimeOrigin::signed(hotkey), netuid, new_commit_hash), + Error::::CommittingWeightsTooFast + ); + + step_block(5); // Current block is now 21 + + assert_ok!(SubtensorModule::commit_weights( + RuntimeOrigin::signed(hotkey), + netuid, + new_commit_hash + )); + + SubtensorModule::set_commit_reveal_weights_enabled(netuid, false); + let weights_keys: Vec = vec![0]; + let weight_values: Vec = vec![1]; + + assert_err!( + SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey), + netuid, + weights_keys.clone(), + weight_values.clone(), + 0 + ), + Error::::SettingWeightsTooFast + ); + + step_block(10); + + assert_ok!(SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey), + netuid, + weights_keys.clone(), + weight_values.clone(), + 0 + )); + + assert_err!( + SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey), + netuid, + weights_keys.clone(), + weight_values.clone(), + 0 + ), + Error::::SettingWeightsTooFast + ); + + step_block(5); + + assert_err!( + SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey), + netuid, + weights_keys.clone(), + weight_values.clone(), + 0 + ), + Error::::SettingWeightsTooFast + ); + + step_block(5); + + assert_ok!(SubtensorModule::set_weights( + RuntimeOrigin::signed(hotkey), + netuid, + weights_keys.clone(), + weight_values.clone(), + 0 + )); + }); } diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 8a2886eb1..c82a5aa49 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -20,6 +20,7 @@ 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 } smallvec = { workspace = true } @@ -93,6 +94,23 @@ pallet-registry = { default-features = false, path = "../pallets/registry" } # Metadata commitment pallet pallet-commitments = { default-features = false, path = "../pallets/commitments" } +# Frontier +fp-evm = { workspace = true } +fp-rpc = { workspace = true } +fp-self-contained = { workspace = true } + +# Frontier FRAME +pallet-base-fee = { workspace = true } +pallet-dynamic-fee = { workspace = true } +pallet-ethereum = { workspace = true } +pallet-evm = { workspace = true } +pallet-evm-chain-id = { workspace = true } +pallet-evm-precompile-modexp = { workspace = true } +pallet-evm-precompile-sha3fips = { workspace = true } +pallet-evm-precompile-simple = { workspace = true } +pallet-hotfix-sufficients = { workspace = true } +fp-account = { workspace = true } + [dev-dependencies] frame-metadata = { workspace = true } sp-io = { workspace = true } @@ -110,6 +128,7 @@ std = [ "frame-system-benchmarking?/std", "frame-benchmarking/std", "codec/std", + "ed25519-dalek/std", "scale-info/std", "frame-executive/std", "frame-metadata-hash-extension/std", @@ -156,6 +175,21 @@ std = [ "log/std", "sp-storage/std", "sp-genesis-builder/std", + # Frontier + "fp-evm/std", + "fp-rpc/std", + "fp-self-contained/std", + # Frontier FRAME + "pallet-base-fee/std", + "pallet-dynamic-fee/std", + "pallet-ethereum/std", + "pallet-evm/std", + "pallet-evm-chain-id/std", + "pallet-evm-precompile-modexp/std", + "pallet-evm-precompile-sha3fips/std", + "pallet-evm-precompile-simple/std", + "pallet-hotfix-sufficients/std", + "fp-account/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", @@ -179,6 +213,11 @@ runtime-benchmarks = [ "pallet-preimage/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", + + # EVM + Frontier + "pallet-ethereum/runtime-benchmarks", + "pallet-evm/runtime-benchmarks", + "pallet-hotfix-sufficients/runtime-benchmarks", ] try-runtime = [ "frame-try-runtime/try-runtime", @@ -189,6 +228,7 @@ try-runtime = [ "pallet-sudo/try-runtime", "pallet-balances/try-runtime", "pallet-grandpa/try-runtime", + "pallet-hotfix-sufficients/try-runtime", "pallet-insecure-randomness-collective-flip/try-runtime", "pallet-timestamp/try-runtime", "pallet-transaction-payment/try-runtime", @@ -205,5 +245,13 @@ try-runtime = [ "pallet-admin-utils/try-runtime", "pallet-commitments/try-runtime", "pallet-registry/try-runtime", + + # EVM + Frontier + "fp-self-contained/try-runtime", + "pallet-base-fee/try-runtime", + "pallet-dynamic-fee/try-runtime", + "pallet-ethereum/try-runtime", + "pallet-evm/try-runtime", + "pallet-evm-chain-id/try-runtime", ] metadata-hash = ["substrate-wasm-builder/metadata-hash"] diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 509ef7b77..4caf906dc 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -40,14 +40,18 @@ use scale_info::TypeInfo; use smallvec::smallvec; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use sp_core::{crypto::KeyTypeId, OpaqueMetadata, RuntimeDebug}; +use sp_core::{ + crypto::{ByteArray, KeyTypeId}, + OpaqueMetadata, H160, H256, U256, +}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{ - AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, NumberFor, One, Verify, + AccountIdLookup, BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, + IdentifyAccount, NumberFor, One, PostDispatchInfoOf, UniqueSaturatedInto, Verify, }, - transaction_validity::{TransactionSource, TransactionValidity}, - AccountId32, ApplyExtrinsicResult, MultiSignature, + transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError}, + AccountId32, ApplyExtrinsicResult, ConsensusEngineId, MultiSignature, }; use sp_std::cmp::Ordering; use sp_std::prelude::*; @@ -59,8 +63,8 @@ use sp_version::RuntimeVersion; pub use frame_support::{ construct_runtime, parameter_types, traits::{ - ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, InstanceFilter, KeyOwnerProofSystem, - PrivilegeCmp, Randomness, StorageInfo, + ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, FindAuthor, InstanceFilter, + KeyOwnerProofSystem, OnFinalize, OnTimestampSet, PrivilegeCmp, Randomness, StorageInfo, }, weights::{ constants::{ @@ -74,11 +78,21 @@ pub use frame_support::{ pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; pub use pallet_timestamp::Call as TimestampCall; -use pallet_transaction_payment::{FungibleAdapter, Multiplier}; +use pallet_transaction_payment::{ConstFeeMultiplier, FungibleAdapter, Multiplier}; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; 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}; +use pallet_evm::{Account as EVMAccount, BalanceConverter, FeeCalculator, Runner}; + // Subtensor module pub use pallet_scheduler; pub use pallet_subtensor; @@ -152,7 +166,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 197, + spec_version: 206, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -181,6 +195,9 @@ 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); + // The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { @@ -198,7 +215,7 @@ parameter_types! { // We allow for 2 seconds of compute with a 6 second average block time. pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::with_sensible_defaults( - Weight::from_parts(4u64 * WEIGHT_REF_TIME_PER_SECOND, u64::MAX), + MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, ); pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength @@ -374,18 +391,15 @@ impl pallet_balances::Config for Runtime { type MaxFreezes = ConstU32<50>; } -pub struct LinearWeightToFee(sp_std::marker::PhantomData); +pub struct LinearWeightToFee; -impl WeightToFeePolynomial for LinearWeightToFee -where - C: Get, -{ +impl WeightToFeePolynomial for LinearWeightToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { let coefficient = WeightToFeeCoefficient { coeff_integer: 0, - coeff_frac: Perbill::from_parts(1_000_000), + coeff_frac: Perbill::from_parts(500_000), negative: false, degree: 1, }; @@ -395,9 +409,7 @@ where } parameter_types! { - // Used with LinearWeightToFee conversion. - pub const FeeWeightRatio: u64 = 1; - pub const TransactionByteFee: u128 = 1; + pub const OperationalFeeMultiplier: u8 = 5; pub FeeMultiplier: Multiplier = Multiplier::one(); } @@ -428,19 +440,12 @@ impl impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; - - //type TransactionByteFee = TransactionByteFee; type OnChargeTransaction = FungibleAdapter; - // Convert dispatch weight to a chargeable fee. - type WeightToFee = LinearWeightToFee; - - type FeeMultiplierUpdate = (); - - type OperationalFeeMultiplier = ConstU8<1>; - + type WeightToFee = LinearWeightToFee; + type OperationalFeeMultiplier = OperationalFeeMultiplier; type LengthToFee = IdentityFee; - //type FeeMultiplierUpdate = ConstFeeMultiplier; + type FeeMultiplierUpdate = ConstFeeMultiplier; } // Configure collective pallet for council @@ -628,17 +633,7 @@ parameter_types! { } #[derive( - Copy, - Clone, - Eq, - PartialEq, - Ord, - PartialOrd, - Encode, - Decode, - RuntimeDebug, - MaxEncodedLen, - TypeInfo, + Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, MaxEncodedLen, TypeInfo, )] pub enum ProxyType { Any, @@ -962,7 +957,7 @@ parameter_types! { pub const SubtensorInitialNetworkLockReductionInterval: u64 = 14 * 7200; pub const SubtensorInitialNetworkRateLimit: u64 = 7200; pub const SubtensorInitialTargetStakesPerInterval: u16 = 1; - pub const SubtensorInitialKeySwapCost: u64 = 1_000_000_000; + pub const SubtensorInitialKeySwapCost: u64 = 100_000_000; // 0.1 TAO pub const InitialAlphaHigh: u16 = 58982; // Represents 0.9 as per the production default pub const InitialAlphaLow: u16 = 45875; // Represents 0.7 as per the production default pub const InitialLiquidAlphaOn: bool = false; // Default value for LiquidAlphaOn @@ -1056,6 +1051,218 @@ impl pallet_admin_utils::Config for Runtime { type WeightInfo = pallet_admin_utils::weights::SubstrateWeight; } +// Define the ChainId +parameter_types! { + pub const SubtensorChainId: u64 = 0x03B1; // Unicode for lowercase alpha + // pub const SubtensorChainId: u64 = 0x03C4; // Unicode for lowercase tau +} + +impl pallet_evm_chain_id::Config for Runtime {} + +pub struct FindAuthorTruncated(PhantomData); +impl> FindAuthor for FindAuthorTruncated { + fn find_author<'a, I>(digests: I) -> Option + where + I: 'a + IntoIterator, + { + if let Some(author_index) = F::find_author(digests) { + pallet_aura::Authorities::::get() + .get(author_index as usize) + .and_then(|authority_id| { + let raw_vec = authority_id.to_raw_vec(); + raw_vec.get(4..24).map(H160::from_slice) + }) + } else { + None + } + } +} + +const BLOCK_GAS_LIMIT: u64 = 75_000_000; + +/// `WeightPerGas` is an approximate ratio of the amount of Weight per Gas. +/// +fn weight_per_gas() -> Weight { + (NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT).saturating_div(BLOCK_GAS_LIMIT) +} + +parameter_types! { + pub BlockGasLimit: U256 = U256::from(BLOCK_GAS_LIMIT); + pub const GasLimitPovSizeRatio: u64 = 0; + pub PrecompilesValue: FrontierPrecompiles = FrontierPrecompiles::<_>::new(); + pub WeightPerGas: Weight = weight_per_gas(); + pub SuicideQuickClearLimit: u32 = 0; +} + +/// The difference between EVM decimals and Substrate decimals. +/// Substrate balances has 9 decimals, while EVM has 18, so the +/// difference factor is 9 decimals, or 10^9 +const EVM_DECIMALS_FACTOR: u64 = 1_000_000_000_u64; + +pub struct SubtensorEvmBalanceConverter; +impl BalanceConverter for SubtensorEvmBalanceConverter { + fn into_evm_balance(value: U256) -> Option { + U256::from(UniqueSaturatedInto::::unique_saturated_into(value)) + .checked_mul(U256::from(EVM_DECIMALS_FACTOR)) + } + + fn into_substrate_balance(value: U256) -> Option { + if value <= U256::from(u64::MAX) { + value.checked_div(U256::from(EVM_DECIMALS_FACTOR)) + } else { + None + } + } +} + +impl pallet_evm::Config for Runtime { + type FeeCalculator = BaseFee; + type GasWeightMapping = pallet_evm::FixedGasWeightMapping; + type WeightPerGas = WeightPerGas; + type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping; + type CallOrigin = pallet_evm::EnsureAddressTruncated; + type WithdrawOrigin = pallet_evm::EnsureAddressTruncated; + type AddressMapping = pallet_evm::HashedAddressMapping; + type Currency = Balances; + type RuntimeEvent = RuntimeEvent; + type PrecompilesType = FrontierPrecompiles; + type PrecompilesValue = PrecompilesValue; + type ChainId = SubtensorChainId; + type BlockGasLimit = BlockGasLimit; + type Runner = pallet_evm::runner::stack::Runner; + type OnChargeTransaction = (); + type OnCreate = (); + type FindAuthor = FindAuthorTruncated; + type GasLimitPovSizeRatio = GasLimitPovSizeRatio; + type SuicideQuickClearLimit = SuicideQuickClearLimit; + type Timestamp = Timestamp; + type WeightInfo = pallet_evm::weights::SubstrateWeight; + type BalanceConverter = SubtensorEvmBalanceConverter; +} + +parameter_types! { + pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes; +} + +impl pallet_ethereum::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type StateRoot = pallet_ethereum::IntermediateStateRoot; + type PostLogContent = PostBlockAndTxnHashes; + type ExtraDataLength = ConstU32<30>; +} + +parameter_types! { + pub BoundDivision: U256 = U256::from(1024); +} + +impl pallet_dynamic_fee::Config for Runtime { + type MinGasPriceBoundDivisor = BoundDivision; +} + +parameter_types! { + pub DefaultBaseFeePerGas: U256 = U256::from(20_000_000_000_u128); + pub DefaultElasticity: Permill = Permill::from_parts(125_000); +} +pub struct BaseFeeThreshold; +impl pallet_base_fee::BaseFeeThreshold for BaseFeeThreshold { + fn lower() -> Permill { + Permill::zero() + } + fn ideal() -> Permill { + Permill::from_parts(500_000) + } + fn upper() -> Permill { + Permill::from_parts(1_000_000) + } +} +impl pallet_base_fee::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Threshold = BaseFeeThreshold; + type DefaultBaseFeePerGas = DefaultBaseFeePerGas; + type DefaultElasticity = DefaultElasticity; +} + +#[derive(Clone)] +pub struct TransactionConverter(PhantomData); + +impl Default for TransactionConverter { + fn default() -> Self { + Self(PhantomData) + } +} + +impl fp_rpc::ConvertTransaction<::Extrinsic> for TransactionConverter { + fn convert_transaction( + &self, + transaction: pallet_ethereum::Transaction, + ) -> ::Extrinsic { + let extrinsic = UncheckedExtrinsic::new_unsigned( + pallet_ethereum::Call::::transact { transaction }.into(), + ); + let encoded = extrinsic.encode(); + ::Extrinsic::decode(&mut &encoded[..]) + .expect("Encoded extrinsic is always valid") + } +} + +impl fp_self_contained::SelfContainedCall for RuntimeCall { + type SignedInfo = H160; + + fn is_self_contained(&self) -> bool { + match self { + RuntimeCall::Ethereum(call) => call.is_self_contained(), + _ => false, + } + } + + fn check_self_contained(&self) -> Option> { + match self { + RuntimeCall::Ethereum(call) => call.check_self_contained(), + _ => None, + } + } + + fn validate_self_contained( + &self, + info: &Self::SignedInfo, + dispatch_info: &DispatchInfoOf, + len: usize, + ) -> Option { + match self { + RuntimeCall::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len), + _ => None, + } + } + + fn pre_dispatch_self_contained( + &self, + info: &Self::SignedInfo, + dispatch_info: &DispatchInfoOf, + len: usize, + ) -> Option> { + match self { + RuntimeCall::Ethereum(call) => { + call.pre_dispatch_self_contained(info, dispatch_info, len) + } + _ => None, + } + } + + fn apply_self_contained( + self, + info: Self::SignedInfo, + ) -> Option>> { + match self { + call @ RuntimeCall::Ethereum(pallet_ethereum::Call::transact { .. }) => { + Some(call.dispatch(RuntimeOrigin::from( + pallet_ethereum::RawOrigin::EthereumTransaction(info), + ))) + } + _ => None, + } + } +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub struct Runtime @@ -1081,6 +1288,13 @@ construct_runtime!( Commitments: pallet_commitments = 18, AdminUtils: pallet_admin_utils = 19, SafeMode: pallet_safe_mode = 20, + + // Frontier + Ethereum: pallet_ethereum = 21, + EVM: pallet_evm = 22, + EVMChainId: pallet_evm_chain_id = 23, + DynamicFee: pallet_dynamic_fee = 24, + BaseFee: pallet_base_fee = 25, } ); @@ -1115,7 +1329,12 @@ type Migrations = ( // Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + fp_self_contained::UncheckedExtrinsic; + +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = + fp_self_contained::CheckedExtrinsic; + // The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; // Executive: handles dispatch to the various modules. @@ -1329,6 +1548,262 @@ impl_runtime_apis! { } } + impl fp_rpc::EthereumRuntimeRPCApi for Runtime { + fn chain_id() -> u64 { + ::ChainId::get() + } + + fn account_basic(address: H160) -> EVMAccount { + let (account, _) = pallet_evm::Pallet::::account_basic(&address); + account + } + + fn gas_price() -> U256 { + let (gas_price, _) = ::FeeCalculator::min_gas_price(); + gas_price + } + + fn account_code_at(address: H160) -> Vec { + pallet_evm::AccountCodes::::get(address) + } + + fn author() -> H160 { + >::find_author() + } + + fn storage_at(address: H160, index: U256) -> H256 { + let mut tmp = [0u8; 32]; + index.to_big_endian(&mut tmp); + pallet_evm::AccountStorages::::get(address, H256::from_slice(&tmp[..])) + } + + fn call( + from: H160, + to: H160, + data: Vec, + value: U256, + gas_limit: U256, + max_fee_per_gas: Option, + max_priority_fee_per_gas: Option, + nonce: Option, + estimate: bool, + access_list: Option)>>, + ) -> Result { + use pallet_evm::GasWeightMapping as _; + + let config = if estimate { + let mut config = ::config().clone(); + config.estimate = true; + Some(config) + } else { + None + }; + + // Estimated encoded transaction size must be based on the heaviest transaction + // type (EIP1559Transaction) to be compatible with all transaction types. + let mut estimated_transaction_len = data.len() + + // pallet ethereum index: 1 + // transact call index: 1 + // Transaction enum variant: 1 + // chain_id 8 bytes + // nonce: 32 + // max_priority_fee_per_gas: 32 + // max_fee_per_gas: 32 + // gas_limit: 32 + // action: 21 (enum varianrt + call address) + // value: 32 + // access_list: 1 (empty vec size) + // 65 bytes signature + 258; + + if access_list.is_some() { + estimated_transaction_len += access_list.encoded_size(); + } + + + let gas_limit = if gas_limit > U256::from(u64::MAX) { + u64::MAX + } else { + gas_limit.low_u64() + }; + let without_base_extrinsic_weight = true; + + let (weight_limit, proof_size_base_cost) = + match ::GasWeightMapping::gas_to_weight( + gas_limit, + without_base_extrinsic_weight + ) { + weight_limit if weight_limit.proof_size() > 0 => { + (Some(weight_limit), Some(estimated_transaction_len as u64)) + } + _ => (None, None), + }; + + ::Runner::call( + from, + to, + data, + value, + gas_limit.unique_saturated_into(), + max_fee_per_gas, + max_priority_fee_per_gas, + nonce, + access_list.unwrap_or_default(), + false, + true, + weight_limit, + proof_size_base_cost, + config.as_ref().unwrap_or(::config()), + ).map_err(|err| err.error.into()) + } + + fn create( + from: H160, + data: Vec, + value: U256, + gas_limit: U256, + max_fee_per_gas: Option, + max_priority_fee_per_gas: Option, + nonce: Option, + estimate: bool, + access_list: Option)>>, + ) -> Result { + use pallet_evm::GasWeightMapping as _; + + let config = if estimate { + let mut config = ::config().clone(); + config.estimate = true; + Some(config) + } else { + None + }; + + + let mut estimated_transaction_len = data.len() + + // from: 20 + // value: 32 + // gas_limit: 32 + // nonce: 32 + // 1 byte transaction action variant + // chain id 8 bytes + // 65 bytes signature + 190; + + if max_fee_per_gas.is_some() { + estimated_transaction_len += 32; + } + if max_priority_fee_per_gas.is_some() { + estimated_transaction_len += 32; + } + if access_list.is_some() { + estimated_transaction_len += access_list.encoded_size(); + } + + + let gas_limit = if gas_limit > U256::from(u64::MAX) { + u64::MAX + } else { + gas_limit.low_u64() + }; + let without_base_extrinsic_weight = true; + + let (weight_limit, proof_size_base_cost) = + match ::GasWeightMapping::gas_to_weight( + gas_limit, + without_base_extrinsic_weight + ) { + weight_limit if weight_limit.proof_size() > 0 => { + (Some(weight_limit), Some(estimated_transaction_len as u64)) + } + _ => (None, None), + }; + + let whitelist = pallet_evm::WhitelistedCreators::::get(); + ::Runner::create( + from, + data, + value, + gas_limit.unique_saturated_into(), + max_fee_per_gas, + max_priority_fee_per_gas, + nonce, + access_list.unwrap_or_default(), + whitelist, + false, + true, + weight_limit, + proof_size_base_cost, + config.as_ref().unwrap_or(::config()), + ).map_err(|err| err.error.into()) + } + + fn current_transaction_statuses() -> Option> { + pallet_ethereum::CurrentTransactionStatuses::::get() + } + + fn current_block() -> Option { + pallet_ethereum::CurrentBlock::::get() + } + + fn current_receipts() -> Option> { + pallet_ethereum::CurrentReceipts::::get() + } + + fn current_all() -> ( + Option, + Option>, + Option> + ) { + ( + pallet_ethereum::CurrentBlock::::get(), + pallet_ethereum::CurrentReceipts::::get(), + pallet_ethereum::CurrentTransactionStatuses::::get() + ) + } + + fn extrinsic_filter( + xts: Vec<::Extrinsic>, + ) -> Vec { + xts.into_iter().filter_map(|xt| match xt.0.function { + RuntimeCall::Ethereum(transact { transaction }) => Some(transaction), + _ => None + }).collect::>() + } + + fn elasticity() -> Option { + Some(pallet_base_fee::Elasticity::::get()) + } + + fn gas_limit_multiplier_support() {} + + fn pending_block( + xts: Vec<::Extrinsic>, + ) -> (Option, Option>) { + for ext in xts.into_iter() { + let _ = Executive::apply_extrinsic(ext); + } + + Ethereum::on_finalize(System::block_number() + 1); + + ( + pallet_ethereum::CurrentBlock::::get(), + pallet_ethereum::CurrentTransactionStatuses::::get() + ) + } + + fn initialize_pending_block(header: &::Header) { + Executive::initialize_block(header); + } + } + + impl fp_rpc::ConvertTransactionRuntimeApi for Runtime { + fn convert_transaction(transaction: EthereumTransaction) -> ::Extrinsic { + UncheckedExtrinsic::new_unsigned( + pallet_ethereum::Call::::transact { transaction }.into(), + ) + } + } + #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn benchmark_metadata(extra: bool) -> ( diff --git a/runtime/src/precompiles/balance_transfer.rs b/runtime/src/precompiles/balance_transfer.rs new file mode 100644 index 000000000..6ae554fa4 --- /dev/null +++ b/runtime/src/precompiles/balance_transfer.rs @@ -0,0 +1,63 @@ +use frame_system::RawOrigin; +use pallet_evm::{ + BalanceConverter, ExitError, ExitSucceed, PrecompileFailure, PrecompileHandle, + PrecompileOutput, PrecompileResult, +}; +use sp_core::U256; +use sp_runtime::traits::{Dispatchable, UniqueSaturatedInto}; +use sp_std::vec; + +use crate::{Runtime, RuntimeCall}; + +use crate::precompiles::{bytes_to_account_id, get_method_id, get_slice}; + +pub const BALANCE_TRANSFER_INDEX: u64 = 2048; + +pub struct BalanceTransferPrecompile; + +impl BalanceTransferPrecompile { + pub fn execute(handle: &mut impl PrecompileHandle) -> PrecompileResult { + let txdata = handle.input(); + + // Match method ID: keccak256("transfer(bytes32)") + let method: &[u8] = get_slice(txdata, 0, 4)?; + if get_method_id("transfer(bytes32)") == method { + // Forward all received value to the destination address + let amount: U256 = handle.context().apparent_value; + + // This is hardcoded hashed address mapping of + // 0x0000000000000000000000000000000000000800 to ss58 public key + // i.e. the contract sends funds it received to the destination address + // from the method parameter + let address_bytes_src: [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, + ]; + let address_bytes_dst: &[u8] = get_slice(txdata, 4, 36)?; + let account_id_src = bytes_to_account_id(&address_bytes_src)?; + let account_id_dst = bytes_to_account_id(address_bytes_dst)?; + let amount_sub = + ::BalanceConverter::into_substrate_balance(amount) + .ok_or(ExitError::OutOfFund)?; + + let call = + RuntimeCall::Balances(pallet_balances::Call::::transfer_allow_death { + dest: account_id_dst.into(), + value: amount_sub.unique_saturated_into(), + }); + + let result = call.dispatch(RawOrigin::Signed(account_id_src).into()); + if result.is_err() { + return Err(PrecompileFailure::Error { + exit_status: ExitError::OutOfFund, + }); + } + } + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: vec![], + }) + } +} diff --git a/runtime/src/precompiles/ed25519.rs b/runtime/src/precompiles/ed25519.rs new file mode 100644 index 000000000..83be4ca77 --- /dev/null +++ b/runtime/src/precompiles/ed25519.rs @@ -0,0 +1,44 @@ +extern crate alloc; + +use alloc::vec::Vec; + +use crate::precompiles::get_slice; +use ed25519_dalek::{Signature, Verifier, VerifyingKey}; +use fp_evm::{ExitError, ExitSucceed, LinearCostPrecompile, PrecompileFailure}; + +pub const EDVERIFY_PRECOMPILE_INDEX: u64 = 1026; + +pub struct Ed25519Verify; + +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 = get_slice(input, 4, 36)?; + let pk = VerifyingKey::try_from(get_slice(input, 36, 68)?).map_err(|_| { + PrecompileFailure::Error { + exit_status: ExitError::Other("Public key recover failed".into()), + } + })?; + let sig = Signature::try_from(get_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/mod.rs b/runtime/src/precompiles/mod.rs new file mode 100644 index 000000000..22f2a4881 --- /dev/null +++ b/runtime/src/precompiles/mod.rs @@ -0,0 +1,125 @@ +use core::marker::PhantomData; +use sp_core::{hashing::keccak_256, H160}; +use sp_runtime::AccountId32; + +use pallet_evm::{ + ExitError, 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}; + +// Include custom precompiles +mod balance_transfer; +mod ed25519; +mod staking; + +use balance_transfer::*; +use ed25519::*; +use staking::*; + +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; 10] { + [ + hash(1), + hash(2), + hash(3), + hash(4), + hash(5), + hash(1024), + hash(1025), + hash(EDVERIFY_PRECOMPILE_INDEX), + hash(BALANCE_TRANSFER_INDEX), + hash(STAKING_PRECOMPILE_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(EDVERIFY_PRECOMPILE_INDEX) => Some(Ed25519Verify::execute(handle)), + // Subtensor specific precompiles : + a if a == hash(BALANCE_TRANSFER_INDEX) => { + Some(BalanceTransferPrecompile::execute(handle)) + } + a if a == hash(STAKING_PRECOMPILE_INDEX) => Some(StakingPrecompile::execute(handle)), + _ => 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) +} + +/// Returns Ethereum method ID from an str method signature +/// +pub fn get_method_id(method_signature: &str) -> [u8; 4] { + // Calculate the full Keccak-256 hash of the method signature + let hash = keccak_256(method_signature.as_bytes()); + + // Extract the first 4 bytes to get the method ID + [hash[0], hash[1], hash[2], hash[3]] +} + +/// Convert bytes to AccountId32 with PrecompileFailure as Error +/// which consumes all gas +/// +pub fn bytes_to_account_id(account_id_bytes: &[u8]) -> Result { + AccountId32::try_from(account_id_bytes).map_err(|_| { + log::info!("Error parsing account id bytes {:?}", account_id_bytes); + PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + } + }) +} + +/// Takes a slice from bytes with PrecompileFailure as Error +/// +pub fn get_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 { + Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }) + } +} diff --git a/runtime/src/precompiles/solidity/balanceTransfer.abi b/runtime/src/precompiles/solidity/balanceTransfer.abi new file mode 100644 index 000000000..99913b900 --- /dev/null +++ b/runtime/src/precompiles/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/runtime/src/precompiles/solidity/balanceTransfer.sol b/runtime/src/precompiles/solidity/balanceTransfer.sol new file mode 100644 index 000000000..42790b900 --- /dev/null +++ b/runtime/src/precompiles/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/runtime/src/precompiles/solidity/ed25519Verify.abi b/runtime/src/precompiles/solidity/ed25519Verify.abi new file mode 100644 index 000000000..05d75ae6c --- /dev/null +++ b/runtime/src/precompiles/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/runtime/src/precompiles/solidity/ed25519Verify.sol b/runtime/src/precompiles/solidity/ed25519Verify.sol new file mode 100644 index 000000000..035feb4cc --- /dev/null +++ b/runtime/src/precompiles/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/runtime/src/precompiles/solidity/staking.abi b/runtime/src/precompiles/solidity/staking.abi new file mode 100644 index 000000000..44b1829c4 --- /dev/null +++ b/runtime/src/precompiles/solidity/staking.abi @@ -0,0 +1,43 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "addStake", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "removeStake", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/runtime/src/precompiles/solidity/staking.sol b/runtime/src/precompiles/solidity/staking.sol new file mode 100644 index 000000000..ec7fb7297 --- /dev/null +++ b/runtime/src/precompiles/solidity/staking.sol @@ -0,0 +1,45 @@ +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 (uint16). Currently a noop, functionality will be enabled with RAO. + * + * Requirements: + * - `hotkey` must be a valid hotkey registered on the network, ensuring that the stake is + * correctly attributed. + */ + function addStake(bytes32 hotkey, uint16 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 (uint16). Currently a noop, functionality will be enabled with RAO. + + * + * 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, uint16 netuid) external; +} diff --git a/runtime/src/precompiles/staking.rs b/runtime/src/precompiles/staking.rs new file mode 100644 index 000000000..e6237dfcf --- /dev/null +++ b/runtime/src/precompiles/staking.rs @@ -0,0 +1,186 @@ +// 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::{AddressMapping, BalanceConverter, HashedAddressMapping}; +use pallet_evm::{ + ExitError, ExitSucceed, PrecompileFailure, PrecompileHandle, PrecompileOutput, PrecompileResult, +}; +use sp_core::crypto::Ss58Codec; +use sp_core::U256; +use sp_runtime::traits::Dispatchable; +use sp_runtime::traits::{BlakeTwo256, UniqueSaturatedInto}; +use sp_runtime::AccountId32; + +use crate::precompiles::{get_method_id, get_slice}; +use sp_std::vec; + +use crate::{Runtime, RuntimeCall}; +pub const STAKING_PRECOMPILE_INDEX: u64 = 2049; + +pub struct StakingPrecompile; + +impl StakingPrecompile { + pub fn execute(handle: &mut impl PrecompileHandle) -> PrecompileResult { + let txdata = handle.input(); + let method_id = get_slice(txdata, 0, 4)?; + let method_input = txdata + .get(4..) + .map_or_else(vec::Vec::new, |slice| slice.to_vec()); // Avoiding borrowing conflicts + + match method_id { + id if id == get_method_id("addStake(bytes32,uint16)") => { + Self::add_stake(handle, &method_input) + } + id if id == get_method_id("removeStake(bytes32,uint256,uint16)") => { + Self::remove_stake(handle, &method_input) + } + _ => Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }), + } + } + + fn add_stake(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { + let hotkey = Self::parse_hotkey(data)?.into(); + let amount: U256 = handle.context().apparent_value; + let amount_sub = + ::BalanceConverter::into_substrate_balance(amount) + .ok_or(ExitError::OutOfFund)?; + + // Create the add_stake call + let call = RuntimeCall::SubtensorModule(pallet_subtensor::Call::::add_stake { + hotkey, + amount_staked: amount_sub.unique_saturated_into(), + }); + // Dispatch the add_stake call + Self::dispatch(handle, call) + } + fn remove_stake(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { + let hotkey = Self::parse_hotkey(data)?.into(); + + // We have to treat this as uint256 (because of Solidity ABI encoding rules, it pads uint64), + // but this will never exceed 8 bytes, se we will ignore higher bytes and will only use lower + // 8 bytes. + let amount = data + .get(56..64) + .map(U256::from_big_endian) + .ok_or(ExitError::OutOfFund)?; + let amount_sub = + ::BalanceConverter::into_substrate_balance(amount) + .ok_or(ExitError::OutOfFund)?; + + let call = RuntimeCall::SubtensorModule(pallet_subtensor::Call::::remove_stake { + hotkey, + amount_unstaked: amount_sub.unique_saturated_into(), + }); + Self::dispatch(handle, call) + } + + fn parse_hotkey(data: &[u8]) -> Result<[u8; 32], PrecompileFailure> { + if data.len() < 32 { + return Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }); + } + let mut hotkey = [0u8; 32]; + hotkey.copy_from_slice(get_slice(data, 0, 32)?); + Ok(hotkey) + } + + fn dispatch(handle: &mut impl PrecompileHandle, call: RuntimeCall) -> PrecompileResult { + let account_id = + as AddressMapping>::into_account_id( + handle.context().caller, + ); + + // Transfer the amount back to the caller before executing the staking operation + // let caller = handle.context().caller; + let amount = handle.context().apparent_value; + + if !amount.is_zero() { + Self::transfer_back_to_caller(&account_id, amount)?; + } + + let result = call.dispatch(RawOrigin::Signed(account_id.clone()).into()); + match &result { + Ok(post_info) => log::info!("Dispatch succeeded. Post info: {:?}", post_info), + Err(dispatch_error) => log::error!("Dispatch failed. Error: {:?}", dispatch_error), + } + match result { + Ok(_) => Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: vec![], + }), + Err(_) => Err(PrecompileFailure::Error { + exit_status: ExitError::Other("Subtensor call failed".into()), + }), + } + } + + fn transfer_back_to_caller( + account_id: &AccountId32, + amount: U256, + ) -> Result<(), PrecompileFailure> { + // this is staking smart contract's(0x0000000000000000000000000000000000000801) sr25519 address + let smart_contract_account_id = + match AccountId32::from_ss58check("5CwnBK9Ack1mhznmCnwiibCNQc174pYQVktYW3ayRpLm4K2X") { + Ok(addr) => addr, + Err(_) => { + return Err(PrecompileFailure::Error { + exit_status: ExitError::Other("Invalid SS58 address".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/scripts/localnet.sh b/scripts/localnet.sh index 51e3d05a8..1e9618954 100755 --- a/scripts/localnet.sh +++ b/scripts/localnet.sh @@ -56,6 +56,10 @@ echo "*** Building chainspec..." "$BASE_DIR/target/release/node-subtensor" build-spec --disable-default-bootnode --raw --chain $CHAIN >$FULL_PATH echo "*** Chainspec built and output to file" +# generate node keys +$BASE_DIR/target/release/node-subtensor key generate-node-key --chain="$FULL_PATH" --base-path /tmp/alice +$BASE_DIR/target/release/node-subtensor key generate-node-key --chain="$FULL_PATH" --base-path /tmp/bob + if [ $NO_PURGE -eq 1 ]; then echo "*** Purging previous state skipped..." else @@ -72,7 +76,7 @@ alice_start=( --chain="$FULL_PATH" --alice --port 30334 - --rpc-port 9946 + --rpc-port 9944 --validator --rpc-cors=all --allow-private-ipv4 diff --git a/zepter.yaml b/zepter.yaml index 2841580e5..e448fa228 100644 --- a/zepter.yaml +++ b/zepter.yaml @@ -12,13 +12,13 @@ workflows: # Check that `A` activates the features of `B`. "propagate-feature", # These are the features to check: - "--features=try-runtime,runtime-benchmarks,std", + "--features=try-runtime,runtime-benchmarks,std,sql,rocksdb,txpool", # Do not try to add a new section into `[features]` of `A` only because `B` expose that feature. There are edge-cases where this is still needed, but we can add them manually. "--left-side-feature-missing=ignore", # Ignore the case that `A` it outside of the workspace. Otherwise it will report errors in external dependencies that we have no influence on. "--left-side-outside-workspace=ignore", # Some features imply that they activate a specific dependency as non-optional. Otherwise the default behaviour with a `?` is used. - "--feature-enables-dep=try-runtime:frame-try-runtime,runtime-benchmarks:frame-benchmarking", # Auxillary flags: + "--feature-enables-dep=try-runtime:frame-try-runtime,runtime-benchmarks:frame-benchmarking", # Auxillary flags: "--offline", "--locked", "--show-path",