diff --git a/.cargo/config.toml b/.cargo/config.toml index f3b3949ea9e..2b51b34da4d 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -50,6 +50,8 @@ rustflags = [ "--cfg", "tokio_unstable", "-C", + "linker=clang", + "-C", "link-arg=-fuse-ld=lld", "-C", "force-frame-pointers=yes", @@ -71,3 +73,7 @@ rustflags = [ "-C", "link-arg=/STACK:8000000", # Set stack to 8 MB ] + +[env] +CMAKE_POLICY_VERSION_MINIMUM = "3.5" +CXXFLAGS = "-include cstdint" # Needed for `librocksdb-sys` build diff --git a/.cursorrules b/.cursorrules new file mode 100644 index 00000000000..fd8b71bdf30 --- /dev/null +++ b/.cursorrules @@ -0,0 +1,32 @@ +# Supra Move Development Rules + +CRITICAL: This is a Supra Move project, NOT Aptos Move. Never use aptos_framework. + +## Framework Rules: +1. ALWAYS use supra_framework:: instead of aptos_framework:: +2. Available namespaces: supra_framework::, std:: +3. Main modules in supra_framework: config_buffer, create_signer, system_addresses, block, reconfiguration, reconfiguration_with_dkg, genesis, automation_registry, event, randomness, state_storage, transaction_fee, util, fungible_asset, multisig_account, function_info, validator_consensus_info, dispatchable_fungible_asset, aggregator_v2, aggregator_factory, chain_id, chain_status, consensus_config, execution_config, gas_schedule, pbo_delegation_pool, staking_config, staking_contract, storage_gas, supra_config, supra_governance, timestamp, transaction_validation, version, vesting, vesting_without_staking, supra_coin, account, supra_account +4. Standard library modules: vector, table, borrow_mut, error, features, option, signer, string, fixed_point32 + +## Code Generation Rules: +- Use supra_framework::account for account operations +- Use supra_framework::supra_coin for native token operations +- Use supra_framework::timestamp for time operations +- Use supra_framework::event for event handling +- Use std::vector for vector operations +- Use std::table for table operations + +## Example Patterns: +```move +module supra_framework::example { + use supra_framework::account; + use supra_framework::signer; + use std::vector; + + public fun init(account: &signer) { + // Supra Move code + } +} +``` + +When generating Move code, ALWAYS use the Supra Move framework patterns above. \ No newline at end of file diff --git a/.github/workflows/aptos-framework-test.yaml b/.github/workflows/aptos-framework-test.yaml index d37d24d880f..aa5881e89a2 100644 --- a/.github/workflows/aptos-framework-test.yaml +++ b/.github/workflows/aptos-framework-test.yaml @@ -1,4 +1,5 @@ name: Run aptos framework checks + on: push: branches: [ "dev", "release/**", "feature/**" ] @@ -7,25 +8,55 @@ on: types: [opened, synchronize, ready_for_review] branches: [ "dev", "release/**", "feature/**" ] paths-ignore: [ '**/*.md' ] + concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true + env: CARGO_TERM_COLOR: always CARGO_NET_GIT_FETCH_WITH_CLI: true DOCKER_BUILDKIT: 1 - FORGE_BIN: ~/.foundry/bin/forge - SUI_BIN: ~/.cargo/bin/sui - APTOS_BIN: ~/.local/bin/aptos - SCRYPTO_BIN: ~/.cargo/bin/scrypto + jobs: build: - runs-on: ghr-elastic-supra-aptos-core-runner + runs-on: [self-hosted, do-ephemeral] timeout-minutes: 90 + steps: - - uses: dtolnay/rust-toolchain@stable - - uses: actions/checkout@v4 - - run: cargo test --release -p aptos-types --lib unit_tests --no-fail-fast - - run: cargo test --release -p aptos-framework -- --skip prover - - run: RUST_MIN_STACK=104857600 cargo test run -p language-e2e-testsuite --no-fail-fast - - run: RUST_MIN_STACK=104857600 cargo test run -p e2e-move-tests --no-fail-fast + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + + - name: Install cargo-nextest + uses: taiki-e/install-action@nextest + + - name: Setup SSH access + run: | + mkdir -p ~/.ssh + + echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + + ssh-keyscan github.com >> ~/.ssh/known_hosts + + echo "Host github.com + StrictHostKeyChecking no + " >> ~/.ssh/config + + - name: Test SSH connection + run: ssh -T git@github.com || true + + - name: Run aptos-types tests + run: cargo test --release -p aptos-types --lib unit_tests --no-fail-fast + + - name: Run aptos-framework tests + run: cargo test --release -p aptos-framework -- --skip prover + + - name: Run language e2e tests + run: RUST_MIN_STACK=104857600 cargo nextest run -p language-e2e-testsuite --no-fail-fast + + - name: Run move e2e tests + run: RUST_MIN_STACK=104857600 cargo nextest run -p e2e-move-tests --no-fail-fast diff --git a/Cargo.lock b/Cargo.lock index e6584661e23..968cd122129 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,9 +24,9 @@ dependencies = [ [[package]] name = "addchain" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2e69442aa5628ea6951fa33e24efe8313f4321a91bd729fc2f75bdfc858570" +checksum = "2e33f6a175ec6a9e0aca777567f9ff7c3deefc255660df887e7fa3585e9801d8" dependencies = [ "num-bigint 0.3.3", "num-integer", @@ -35,18 +35,18 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.21.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aead" @@ -54,19 +54,19 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "generic-array", ] [[package]] name = "aes" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -100,20 +100,20 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.17", "once_cell", "version_check", ] [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", "const-random", - "getrandom 0.2.11", + "getrandom 0.3.4", "once_cell", "serde", "version_check", @@ -122,9 +122,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -152,9 +152,9 @@ dependencies = [ [[package]] name = "allocative" -version = "0.3.3" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "082af274fd02beef17b7f0725a49ecafe6c075ef56cac9d6363eb3916a9817ae" +checksum = "d8cf9afc79c83d514444b55df3935d317da54b1ce3b17a133c646889cc260de8" dependencies = [ "allocative_derive", "ctor", @@ -162,26 +162,26 @@ dependencies = [ [[package]] name = "allocative_derive" -version = "0.3.3" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe233a377643e0fc1a56421d7c90acdec45c291b30345eb9f08e8d0ddce5a4ab" +checksum = "614043c56c1173b800acb007b81fd0cbc0a0d7d717b71ba705fc2230d0760a23" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "ambassador" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b27ba24e4d8a188489d5a03c7fabc167a60809a383cdb4d15feb37479cd2a48" +checksum = "e68de4cdc6006162265d0957edb4a860fe4e711b1dc17a5746fd95f952f08285" dependencies = [ "itertools 0.10.5", "proc-macro2", @@ -189,12 +189,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -211,7 +205,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" dependencies = [ "anstyle", - "unicode-width 0.2.0", + "unicode-width 0.2.2", ] [[package]] @@ -231,9 +225,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -246,36 +240,37 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", - "windows-sys 0.59.0", + "once_cell_polyfill", + "windows-sys 0.61.2", ] [[package]] @@ -286,12 +281,9 @@ checksum = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" -dependencies = [ - "backtrace", -] +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "approx" @@ -346,7 +338,7 @@ dependencies = [ "bcs 0.1.4", "bollard", "chrono", - "clap 4.5.21", + "clap 4.6.1", "clap_complete", "colored", "dashmap 7.0.0-rc2", @@ -381,7 +373,7 @@ dependencies = [ "poem", "rand 0.7.3", "regex", - "reqwest 0.11.23", + "reqwest 0.11.27", "self_update", "serde", "serde_json", @@ -390,11 +382,11 @@ dependencies = [ "shadow-rs", "supra-aptos", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "toml 0.7.8", "tracing", - "tracing-subscriber 0.3.18", + "tracing-subscriber 0.3.23", "url", ] @@ -438,8 +430,8 @@ dependencies = [ "aptos-types", "bcs 0.1.4", "futures-channel", - "http 0.2.11", - "hyper 0.14.28", + "http 0.2.12", + "hyper 0.14.32", "sha256", "tokio", "url", @@ -506,7 +498,7 @@ dependencies = [ "proptest", "rand 0.7.3", "regex", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "tokio", @@ -540,7 +532,7 @@ dependencies = [ "bcs 0.1.4", "bytes", "goldenfile", - "hyper 0.14.28", + "hyper 0.14.32", "rand 0.7.3", "regex", "serde_json", @@ -599,6 +591,7 @@ dependencies = [ "poem-openapi-derive", "serde", "serde_json", + "sha3 0.9.1", ] [[package]] @@ -629,7 +622,7 @@ dependencies = [ "async-trait", "bcs 0.1.4", "bytes", - "clap 4.5.21", + "clap 4.6.1", "csv", "futures", "itertools 0.13.0", @@ -637,19 +630,19 @@ dependencies = [ "move-bytecode-verifier", "num_cpus", "once_cell", - "pin-project 1.1.3", + "pin-project 1.1.13", "proptest", "rand 0.7.3", "regex", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "serde_yaml 0.8.26", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-io-timeout", "tokio-stream", - "tokio-util 0.7.10", + "tokio-util 0.7.18", "warp", ] @@ -668,9 +661,9 @@ dependencies = [ "aptos-types", "bcs 0.1.4", "bytes", - "hyper 0.14.28", + "hyper 0.14.32", "once_cell", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "tokio", "tokio-stream", @@ -726,7 +719,7 @@ dependencies = [ "crossbeam", "derivative", "fail", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "itertools 0.13.0", "move-binary-format", "move-core-types", @@ -734,7 +727,7 @@ dependencies = [ "move-vm-types", "num_cpus", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "proptest", "proptest-derive", "rand 0.7.3", @@ -752,7 +745,7 @@ dependencies = [ "aptos-metrics-core", "aptos-types", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "criterion", "dashmap 7.0.0-rc2", "itertools 0.13.0", @@ -802,13 +795,13 @@ dependencies = [ "anyhow", "camino", "chrono", - "clap 4.5.21", + "clap 4.6.1", "clap-verbosity-flag", "determinator", - "env_logger", + "env_logger 0.10.2", "guppy", "log", - "reqwest 0.11.23", + "reqwest 0.11.27", "url", ] @@ -829,7 +822,7 @@ name = "aptos-cli-common" version = "1.0.0" dependencies = [ "anstyle", - "clap 4.5.21", + "clap 4.6.1", "clap_complete", ] @@ -851,7 +844,7 @@ dependencies = [ "aptos-validator-interface", "aptos-vm", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "futures", "itertools 0.13.0", "legacy-move-compiler", @@ -879,7 +872,7 @@ dependencies = [ "once_cell", "rand 0.7.3", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -908,10 +901,10 @@ dependencies = [ "serde_json", "serde_merge", "serde_yaml 0.8.26", - "strum 0.27.1", - "strum_macros 0.27.1", + "strum 0.27.2", + "strum_macros 0.27.2", "tempfile", - "thiserror", + "thiserror 1.0.69", "url", ] @@ -966,7 +959,7 @@ dependencies = [ "bytes", "chrono", "claims", - "clap 4.5.21", + "clap 4.6.1", "dashmap 7.0.0-rc2", "enum_dispatch", "fail", @@ -993,10 +986,10 @@ dependencies = [ "serde_bytes", "serde_json", "sha3 0.9.1", - "strum 0.27.1", - "strum_macros 0.27.1", + "strum 0.27.2", + "strum_macros 0.27.2", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-retry", "tokio-stream", @@ -1014,7 +1007,7 @@ dependencies = [ "futures", "move-core-types", "serde", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -1087,9 +1080,9 @@ dependencies = [ "curve25519-dalek-ng", "digest 0.9.0", "ed25519-dalek 1.0.1", - "ff 0.13.0", + "ff 0.13.1", "hex", - "hkdf 0.10.0", + "hkdf", "libsecp256k1", "merlin", "more-asserts", @@ -1108,15 +1101,16 @@ dependencies = [ "serde-name", "serde_bytes", "serde_json", - "sha2 0.10.8", + "sha2 0.10.9", "sha2 0.9.9", "sha3 0.9.1", "signature 2.2.0", "static_assertions", - "thiserror", + "thiserror 1.0.69", "tiny-keccak", "trybuild", "typenum", + "utoipa", "x25519-dalek", ] @@ -1161,9 +1155,9 @@ dependencies = [ "maplit", "mockall 0.11.4", "ordered-float 3.9.2", - "rand 0.8.5", + "rand 0.8.6", "serde", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -1190,7 +1184,7 @@ dependencies = [ "once_cell", "rand 0.7.3", "serde", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", ] @@ -1225,7 +1219,7 @@ dependencies = [ "bcs 0.1.4", "byteorder", "claims", - "clap 4.5.21", + "clap 4.6.1", "crossbeam-channel", "dashmap 7.0.0-rc2", "either", @@ -1309,7 +1303,7 @@ dependencies = [ "aptos-types", "aptos-vm", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "itertools 0.13.0", "rayon", "serde_json", @@ -1326,7 +1320,7 @@ dependencies = [ "aptos-logger", "aptos-move-debugger", "aptos-push-metrics", - "clap 4.5.21", + "clap 4.6.1", "jemallocator", "tokio", ] @@ -1343,7 +1337,7 @@ dependencies = [ "blst", "blstrs 0.7.1", "criterion", - "ff 0.13.0", + "ff 0.13.1", "group 0.13.0", "hex", "merlin", @@ -1420,7 +1414,7 @@ dependencies = [ "aptos-types", "bcs 0.1.4", "e2e-move-tests", - "getrandom 0.2.11", + "getrandom 0.2.17", "move-binary-format", "move-bytecode-verifier", "move-core-types", @@ -1462,7 +1456,7 @@ dependencies = [ "move-binary-format", "move-core-types", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1546,7 +1540,7 @@ dependencies = [ "bcs 0.1.4", "bytes", "chrono", - "clap 4.5.21", + "clap 4.6.1", "dashmap 7.0.0-rc2", "derivative", "indicatif 0.15.0", @@ -1584,7 +1578,7 @@ dependencies = [ "aptos-types", "aptos-vm", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "crossbeam-channel", "ctrlc", "dashmap 7.0.0-rc2", @@ -1593,7 +1587,7 @@ dependencies = [ "once_cell", "rayon", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1633,13 +1627,13 @@ dependencies = [ "aptos-types", "bcs 0.1.4", "criterion", - "derive_more 2.0.1", + "derive_more 2.1.1", "itertools 0.13.0", "once_cell", "ouroboros", "rayon", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1654,10 +1648,10 @@ dependencies = [ "aptos-transaction-generator-lib", "bcs 0.1.4", "chrono", - "clap 4.5.21", + "clap 4.6.1", "futures", "rand 0.7.3", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "tokio", @@ -1684,7 +1678,7 @@ dependencies = [ name = "aptos-experimental-layered-map" version = "0.1.0" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "anyhow", "aptos-crypto", "aptos-drop-helper", @@ -1716,7 +1710,7 @@ dependencies = [ "aptos-vm-environment", "aptos-vm-logging", "aptos-vm-types", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "move-core-types", "once_cell", "rayon", @@ -1738,7 +1732,7 @@ dependencies = [ name = "aptos-fallible" version = "0.1.0" dependencies = [ - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1749,7 +1743,7 @@ dependencies = [ "aptos-faucet-core", "aptos-logger", "aptos-sdk", - "clap 4.5.21", + "clap 4.6.1", "tokio", ] @@ -1765,7 +1759,7 @@ dependencies = [ "aptos-sdk", "async-trait", "captcha", - "clap 4.5.21", + "clap 4.6.1", "deadpool-redis", "enum_dispatch", "firebase-token", @@ -1779,7 +1773,7 @@ dependencies = [ "poem-openapi", "rand 0.7.3", "redis", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "serde_yaml 0.8.26", @@ -1806,7 +1800,7 @@ dependencies = [ "anyhow", "aptos-faucet-core", "aptos-logger", - "clap 4.5.21", + "clap 4.6.1", "tokio", ] @@ -1818,11 +1812,11 @@ dependencies = [ "aptos-logger", "aptos-node-checker", "aptos-sdk", - "clap 4.5.21", - "env_logger", + "clap 4.6.1", + "env_logger 0.10.2", "futures", "gcp-bigquery-client", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "tokio", @@ -1856,11 +1850,11 @@ dependencies = [ "aptos-transaction-workloads-lib", "async-trait", "chrono", - "clap 4.5.21", + "clap 4.6.1", "either", "futures", "hex", - "hyper 0.14.28", + "hyper 0.14.32", "itertools 0.13.0", "json-patch", "k8s-openapi", @@ -1872,7 +1866,7 @@ dependencies = [ "quick-junit", "rand 0.7.3", "regex", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "serde_merge", @@ -1880,10 +1874,10 @@ dependencies = [ "sugars", "tempfile", "termcolor", - "thiserror", + "thiserror 1.0.69", "tokio", "url", - "uuid 1.11.0", + "uuid 1.23.2", ] [[package]] @@ -1901,14 +1895,14 @@ dependencies = [ "aptos-testcases", "async-trait", "chrono", - "clap 4.5.21", - "env_logger", + "clap 4.6.1", + "env_logger 0.10.2", "futures", "jemallocator", "once_cell", "rand 0.7.3", "random_word", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde_json", "serde_yaml 0.8.26", "sugars", @@ -1947,8 +1941,9 @@ dependencies = [ "bulletproofs 5.0.0", "byteorder", "claims", - "clap 4.5.21", + "clap 4.6.1", "codespan-reporting", + "crypto", "curve25519-dalek-ng", "either", "eth_trie", @@ -1984,7 +1979,7 @@ dependencies = [ "rlp", "serde", "serde_bytes", - "sha2 0.10.8", + "sha2 0.10.9", "sha2 0.9.9", "sha3 0.9.1", "siphasher 0.3.11", @@ -2015,12 +2010,12 @@ dependencies = [ "aptos-language-e2e-tests", "aptos-types", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "float-cmp", "move-binary-format", "move-core-types", "move-ir-compiler", - "nalgebra", + "nalgebra 0.32.6", "walkdir", ] @@ -2080,7 +2075,7 @@ dependencies = [ "aptos-package-builder", "aptos-types", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "move-core-types", "move-model", "tempfile", @@ -2118,7 +2113,7 @@ dependencies = [ "base64 0.13.1", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "ureq", ] @@ -2174,14 +2169,14 @@ dependencies = [ "aptos-moving-average 0.1.0 (git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=62beedc881d1b76632318ceb186ee9065236468e)", "aptos-protos 1.3.1", "async-trait", - "clap 4.5.21", + "clap 4.6.1", "futures", "futures-core", "jemallocator", "once_cell", - "prost 0.13.4", + "prost 0.13.5", "redis", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "tempfile", "tokio", @@ -2202,11 +2197,11 @@ dependencies = [ "aptos-protos 1.3.1", "aptos-transaction-filter 0.1.0", "async-trait", - "clap 4.5.21", + "clap 4.6.1", "futures", "jemallocator", "once_cell", - "prost 0.13.4", + "prost 0.13.5", "redis", "rstest", "serde", @@ -2216,7 +2211,7 @@ dependencies = [ "tonic 0.12.3", "tonic-reflection", "tracing", - "uuid 1.11.0", + "uuid 1.23.2", ] [[package]] @@ -2231,12 +2226,12 @@ dependencies = [ "aptos-transaction-filter 0.1.0", "async-trait", "build_html", - "clap 4.5.21", + "clap 4.6.1", "dashmap 7.0.0-rc2", "futures", "jemallocator", "once_cell", - "prost 0.13.4", + "prost 0.13.5", "rand 0.7.3", "serde", "tokio", @@ -2245,7 +2240,7 @@ dependencies = [ "tonic 0.12.3", "tonic-reflection", "tracing", - "uuid 1.11.0", + "uuid 1.23.2", "warp", ] @@ -2258,7 +2253,7 @@ dependencies = [ "aptos-indexer-grpc-utils", "aptos-metrics-core", "async-trait", - "clap 4.5.21", + "clap 4.6.1", "cloud-storage", "jemallocator", "once_cell", @@ -2278,7 +2273,7 @@ dependencies = [ "aptos-metrics-core", "aptos-moving-average 0.1.0 (git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=62beedc881d1b76632318ceb186ee9065236468e)", "async-trait", - "clap 4.5.21", + "clap 4.6.1", "futures", "jemallocator", "once_cell", @@ -2297,7 +2292,7 @@ dependencies = [ "aptos-indexer-grpc-utils", "aptos-protos 1.3.1", "async-trait", - "clap 4.5.21", + "clap 4.6.1", "futures", "jemallocator", "serde", @@ -2347,7 +2342,7 @@ dependencies = [ "futures", "goldenfile", "hex", - "hyper 0.14.28", + "hyper 0.14.32", "itertools 0.13.0", "move-core-types", "once_cell", @@ -2389,12 +2384,12 @@ dependencies = [ "aptos-protos 1.3.1", "async-trait", "build_html", - "clap 4.5.21", + "clap 4.6.1", "dashmap 7.0.0-rc2", "futures", "jemallocator", "once_cell", - "prost 0.13.4", + "prost 0.13.5", "rand 0.7.3", "serde", "serde_json", @@ -2414,7 +2409,7 @@ dependencies = [ "aptos-system-utils 0.1.0", "async-trait", "backtrace", - "clap 4.5.21", + "clap 4.6.1", "figment", "prometheus", "serde", @@ -2422,7 +2417,7 @@ dependencies = [ "tokio", "toml 0.7.8", "tracing", - "tracing-subscriber 0.3.18", + "tracing-subscriber 0.3.23", "warp", ] @@ -2446,7 +2441,7 @@ dependencies = [ "flate2", "futures", "google-cloud-storage", - "hyper 0.14.28", + "hyper 0.14.32", "itertools 0.13.0", "once_cell", "rocksdb", @@ -2456,7 +2451,7 @@ dependencies = [ "tempfile", "tokio", "tokio-stream", - "tokio-util 0.7.10", + "tokio-util 0.7.18", ] [[package]] @@ -2480,14 +2475,14 @@ dependencies = [ "lz4", "once_cell", "prometheus", - "prost 0.13.4", + "prost 0.13.5", "redis", "redis-test", "ripemd", "serde", "serde_json", "tokio", - "tokio-util 0.7.10", + "tokio-util 0.7.18", "tonic 0.12.3", "tracing", "url", @@ -2503,7 +2498,7 @@ dependencies = [ "aptos-indexer-grpc-utils", "aptos-protos 1.3.1", "async-trait", - "clap 4.5.21", + "clap 4.6.1", "futures", "jemallocator", "serde", @@ -2520,19 +2515,19 @@ name = "aptos-indexer-processor-sdk" version = "0.1.0" source = "git+https://github.com/aptos-labs/aptos-indexer-processor-sdk.git?tag=aptos-indexer-processor-sdk-v2.1.2#188ba1a37597739a2e503165dec0c3fcc63c89ec" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "anyhow", "aptos-indexer-transaction-stream", "aptos-protos 1.3.1 (git+https://github.com/aptos-labs/aptos-core.git?rev=2dd9c73b27fdcbe78c7391fd43c9a5d00b93e686)", "aptos-system-utils 0.1.0 (git+https://github.com/aptos-labs/aptos-core.git?rev=2dd9c73b27fdcbe78c7391fd43c9a5d00b93e686)", "async-trait", "autometrics", - "axum 0.7.5", + "axum 0.7.9", "backtrace", "bcs 0.1.4", "bigdecimal", "chrono", - "clap 4.5.21", + "clap 4.6.1", "derive_builder", "diesel", "diesel-async", @@ -2541,7 +2536,7 @@ dependencies = [ "futures", "futures-util", "hex", - "indexmap 2.7.0", + "indexmap 2.14.0", "instrumented-channel", "kanal", "mockall 0.12.1", @@ -2557,13 +2552,13 @@ dependencies = [ "serde_yaml 0.8.26", "sha2 0.9.9", "tempfile", - "thiserror", + "thiserror 1.0.69", "tiny-keccak", "tokio", "tokio-postgres", "toml 0.7.8", "tracing", - "tracing-subscriber 0.3.18", + "tracing-subscriber 0.3.23", "url", ] @@ -2585,7 +2580,7 @@ dependencies = [ "aptos-faucet-core", "aptos-indexer-grpc-utils", "aptos-protos 1.3.1", - "clap 4.5.21", + "clap 4.6.1", "futures", "itertools 0.13.0", "rand 0.7.3", @@ -2613,7 +2608,7 @@ dependencies = [ "futures-util", "once_cell", "prometheus", - "prost 0.13.4", + "prost 0.13.5", "sample", "serde", "tokio", @@ -2644,10 +2639,10 @@ dependencies = [ "aptos-time-service", "assert_approx_eq", "futures", - "hyper 0.14.28", + "hyper 0.14.32", "once_cell", "prometheus", - "reqwest 0.11.23", + "reqwest 0.11.27", "rusty-fork", "serde_json", "tokio", @@ -2679,7 +2674,7 @@ dependencies = [ "rand 0.7.3", "rayon", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2724,9 +2719,9 @@ version = "0.1.0" dependencies = [ "anyhow", "aptos-types", - "http 0.2.11", + "http 0.2.12", "move-core-types", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "tokio", @@ -2767,7 +2762,7 @@ dependencies = [ "regex", "serde", "serde-big-array", - "sha2 0.10.8", + "sha2 0.10.9", ] [[package]] @@ -2783,7 +2778,7 @@ dependencies = [ "bcs 0.1.4", "firestore", "hex", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde_json", "tokio", ] @@ -2811,18 +2806,18 @@ dependencies = [ "dashmap 7.0.0-rc2", "firestore", "hex", - "hyper 0.14.28", + "hyper 0.14.32", "jsonwebtoken 8.3.0", "jwt", "once_cell", "rand 0.7.3", "regex", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "sha3 0.9.1", "tokio", - "uuid 1.11.0", + "uuid 1.23.2", ] [[package]] @@ -2882,7 +2877,7 @@ dependencies = [ "hex", "ledger-apdu", "ledger-transport-hid", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2899,7 +2894,7 @@ dependencies = [ "dirs 5.0.1", "futures", "processor", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "tokio", @@ -2935,11 +2930,11 @@ dependencies = [ "prometheus", "serde", "serde_json", - "strum 0.27.1", - "strum_macros 0.27.1", + "strum 0.27.2", + "strum_macros 0.27.2", "tokio", "tracing", - "tracing-subscriber 0.3.18", + "tracing-subscriber 0.3.23", ] [[package]] @@ -2993,7 +2988,7 @@ dependencies = [ "rand 0.7.3", "rayon", "serde", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", ] @@ -3008,7 +3003,7 @@ dependencies = [ "claims", "futures", "serde", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -3048,10 +3043,10 @@ dependencies = [ "aptos-vm-logging", "aptos-vm-types", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "itertools 0.13.0", "regex", - "reqwest 0.11.23", + "reqwest 0.11.27", "tokio", "url", ] @@ -3065,7 +3060,7 @@ dependencies = [ "aptos-transaction-generator-lib", "aptos-transaction-workloads-lib", "aptos-types", - "clap 4.5.21", + "clap 4.6.1", "rand 0.7.3", "serde_json", ] @@ -3078,7 +3073,7 @@ dependencies = [ "aptos-gas-schedule", "aptos-types", "aptos-vm", - "clap 4.5.21", + "clap 4.6.1", "move-cli", "move-model", "move-package", @@ -3177,10 +3172,10 @@ dependencies = [ "aptos-types", "bytes", "futures", - "pin-project 1.1.3", + "pin-project 1.1.13", "serde", "tokio", - "tokio-util 0.7.10", + "tokio-util 0.7.18", "url", ] @@ -3217,20 +3212,20 @@ dependencies = [ "maplit", "once_cell", "ordered-float 3.9.2", - "pin-project 1.1.3", + "pin-project 1.1.13", "proptest", "proptest-derive", "rand 0.7.3", - "rand 0.8.5", + "rand 0.8.6", "rand_core 0.5.1", "serde", "serde_bytes", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-retry", "tokio-stream", - "tokio-util 0.7.10", + "tokio-util 0.7.18", ] [[package]] @@ -3284,7 +3279,7 @@ dependencies = [ "aptos-logger", "aptos-network", "aptos-types", - "clap 4.5.21", + "clap 4.6.1", "futures", "serde", "tokio", @@ -3321,16 +3316,16 @@ dependencies = [ name = "aptos-nft-metadata-crawler" version = "0.1.0" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "anyhow", "aptos-indexer-grpc-server-framework", "aptos-metrics-core", "async-trait", - "axum 0.7.5", + "axum 0.7.9", "backoff", "bytes", "chrono", - "clap 4.5.21", + "clap 4.6.1", "diesel", "diesel_migrations", "enum_dispatch", @@ -3341,7 +3336,7 @@ dependencies = [ "once_cell", "rayon", "regex", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "sha256", @@ -3406,7 +3401,7 @@ dependencies = [ "aptos-vm", "aptos-vm-environment", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "either", "fail", "futures", @@ -3439,17 +3434,17 @@ dependencies = [ "aptos-transaction-emitter-lib", "aptos-transaction-workloads-lib", "async-trait", - "clap 4.5.21", + "clap 4.6.1", "futures", "once_cell", "poem", "poem-openapi", "prometheus-parse", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "serde_yaml 0.8.26", - "thiserror", + "thiserror 1.0.69", "tokio", "url", ] @@ -3510,7 +3505,7 @@ dependencies = [ "aptos-mempool", "aptos-storage-interface", "aptos-types", - "clap 4.5.21", + "clap 4.6.1", ] [[package]] @@ -3550,7 +3545,7 @@ dependencies = [ "rand 0.7.3", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", ] @@ -3582,7 +3577,7 @@ dependencies = [ "once_cell", "rand 0.7.3", "serde", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -3594,7 +3589,7 @@ dependencies = [ "aptos-types", "bcs 0.1.4", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3637,7 +3632,7 @@ version = "1.3.1" dependencies = [ "futures-core", "pbjson", - "prost 0.13.4", + "prost 0.13.5", "serde", "tonic 0.12.3", ] @@ -3648,7 +3643,7 @@ version = "1.3.1" source = "git+https://github.com/aptos-labs/aptos-core.git?rev=2dd9c73b27fdcbe78c7391fd43c9a5d00b93e686#2dd9c73b27fdcbe78c7391fd43c9a5d00b93e686" dependencies = [ "pbjson", - "prost 0.13.4", + "prost 0.13.5", "serde", "tonic 0.12.3", ] @@ -3679,9 +3674,9 @@ dependencies = [ "aptos-logger", "aptos-metrics-core", "futures", - "pin-project 1.1.3", + "pin-project 1.1.13", "tokio", - "tokio-util 0.7.10", + "tokio-util 0.7.18", ] [[package]] @@ -3710,7 +3705,7 @@ dependencies = [ "aptos-vm-logging", "aptos-vm-types", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "futures", "git2 0.16.1", "handlebars", @@ -3722,13 +3717,13 @@ dependencies = [ "move-vm-runtime", "move-vm-types", "once_cell", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "serde_yaml 0.8.26", "sha3 0.9.1", - "strum 0.27.1", - "strum_macros 0.27.1", + "strum 0.27.2", + "strum_macros 0.27.2", "tokio", "url", "walkdir", @@ -3773,10 +3768,10 @@ dependencies = [ "aptos-vm-environment", "bcs 0.1.4", "claims", - "clap 4.5.21", + "clap 4.6.1", "colored", "move-core-types", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "rand 0.7.3", "serde", "tokio", @@ -3809,13 +3804,13 @@ dependencies = [ "aptos-types", "bcs 0.1.4", "bytes", - "clap 4.5.21", + "clap 4.6.1", "hex", "move-core-types", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "url", ] @@ -3853,13 +3848,13 @@ dependencies = [ "aptos-types", "aptos-warp-webserver", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "futures", "hex", "itertools 0.13.0", "move-core-types", "once_cell", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "tokio", @@ -3876,7 +3871,7 @@ dependencies = [ "aptos-logger", "aptos-rosetta", "aptos-types", - "clap 4.5.21", + "clap 4.6.1", "serde", "serde_json", "tokio", @@ -3917,7 +3912,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3957,7 +3952,7 @@ dependencies = [ "proptest", "rand 0.7.3", "rayon", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3980,7 +3975,7 @@ dependencies = [ "once_cell", "rand 0.7.3", "rand_core 0.5.1", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "tiny-bip39", @@ -3997,7 +3992,7 @@ dependencies = [ "aptos-framework", "aptos-types", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "heck 0.4.1", "move-core-types", "once_cell", @@ -4021,7 +4016,7 @@ dependencies = [ "crossbeam-channel", "once_cell", "serde", - "thiserror", + "thiserror 1.0.69", "tokio", "tonic 0.12.3", "tonic-reflection", @@ -4045,7 +4040,7 @@ dependencies = [ "rand 0.7.3", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4057,7 +4052,7 @@ dependencies = [ "proptest", "serde", "static_assertions", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4068,7 +4063,7 @@ dependencies = [ "aptos-infallible", "claims", "crossbeam", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "proptest", "proptest-derive", "rayon", @@ -4117,7 +4112,7 @@ dependencies = [ "once_cell", "rand 0.7.3", "serde", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", ] @@ -4137,17 +4132,17 @@ dependencies = [ "arr_macro", "bcs 0.1.4", "dashmap 7.0.0-rc2", - "derive_more 2.0.1", + "derive_more 2.1.1", "itertools 0.13.0", "lru", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "proptest", "proptest-derive", "rand 0.7.3", "rayon", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4157,7 +4152,7 @@ dependencies = [ "aptos-config", "aptos-network", "aptos-storage-service-types", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4170,7 +4165,7 @@ dependencies = [ "claims", "futures", "serde", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -4205,7 +4200,7 @@ dependencies = [ "once_cell", "rand 0.7.3", "serde", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -4224,7 +4219,7 @@ dependencies = [ "proptest", "rand 0.7.3", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4234,8 +4229,8 @@ dependencies = [ "anyhow", "aptos-profiler 0.1.0", "async-mutex", - "http 0.2.11", - "hyper 0.14.28", + "http 0.2.12", + "hyper 0.14.32", "lazy_static", "mime", "pprof", @@ -4254,8 +4249,8 @@ dependencies = [ "anyhow", "aptos-profiler 0.1.0 (git+https://github.com/aptos-labs/aptos-core.git?rev=2dd9c73b27fdcbe78c7391fd43c9a5d00b93e686)", "async-mutex", - "http 0.2.11", - "hyper 0.14.28", + "http 0.2.12", + "hyper 0.14.32", "lazy_static", "mime", "pprof", @@ -4310,7 +4305,7 @@ dependencies = [ "prometheus", "rand 0.7.3", "rand_core 0.5.1", - "reqwest 0.11.23", + "reqwest 0.11.27", "reqwest-middleware", "reqwest-retry", "serde", @@ -4319,7 +4314,7 @@ dependencies = [ "tokio", "tokio-stream", "url", - "uuid 1.11.0", + "uuid 1.23.2", ] [[package]] @@ -4338,7 +4333,7 @@ dependencies = [ "bcs 0.1.4", "chrono", "claims", - "clap 4.5.21", + "clap 4.6.1", "debug-ignore", "flate2", "futures", @@ -4349,17 +4344,17 @@ dependencies = [ "prometheus", "rand 0.7.3", "rand_core 0.5.1", - "reqwest 0.11.23", + "reqwest 0.11.27", "reqwest-middleware", "reqwest-retry", "serde", "serde_json", "serde_yaml 0.8.26", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "url", - "uuid 1.11.0", + "uuid 1.23.2", "warp", ] @@ -4397,7 +4392,7 @@ dependencies = [ "itertools 0.13.0", "log", "rand 0.7.3", - "reqwest 0.11.23", + "reqwest 0.11.27", "tokio", ] @@ -4408,8 +4403,8 @@ dependencies = [ "aptos-infallible", "enum_dispatch", "futures", - "pin-project 1.1.3", - "thiserror", + "pin-project 1.1.13", + "thiserror 1.0.69", "tokio", "tokio-test", ] @@ -4431,7 +4426,7 @@ dependencies = [ "aptos-types", "aptos-vm", "aptos-vm-logging", - "clap 4.5.21", + "clap 4.6.1", "criterion", "criterion-cpu-time", "num_cpus", @@ -4448,7 +4443,7 @@ dependencies = [ "aptos-sdk", "aptos-transaction-emitter-lib", "aptos-transaction-workloads-lib", - "clap 4.5.21", + "clap 4.6.1", "futures", "rand 0.7.3", "tokio", @@ -4471,7 +4466,7 @@ dependencies = [ "aptos-types", "async-trait", "base64 0.13.1", - "clap 4.5.21", + "clap 4.6.1", "futures", "hex", "itertools 0.13.0", @@ -4479,7 +4474,7 @@ dependencies = [ "once_cell", "rand 0.7.3", "rand_core 0.5.1", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "tokio", @@ -4497,11 +4492,11 @@ dependencies = [ "lz4", "memchr", "once_cell", - "prost 0.13.4", + "prost 0.13.5", "serde", "serde_json", "serde_yaml 0.8.26", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4515,11 +4510,11 @@ dependencies = [ "derive_builder", "memchr", "once_cell", - "prost 0.13.4", + "prost 0.13.5", "serde", "serde_json", "serde_yaml 0.8.26", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4544,7 +4539,7 @@ dependencies = [ "aptos-logger", "aptos-sdk", "async-trait", - "clap 4.5.21", + "clap 4.6.1", "log", "move-binary-format", "move-package", @@ -4567,7 +4562,7 @@ dependencies = [ "move-binary-format", "move-core-types", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "proptest", "serde", ] @@ -4581,7 +4576,7 @@ dependencies = [ "aptos-sdk", "aptos-transaction-generator-lib", "async-trait", - "clap 4.5.21", + "clap 4.6.1", "move-binary-format", "once_cell", "rand 0.7.3", @@ -4609,7 +4604,7 @@ dependencies = [ "aptos-vm-genesis", "aptos-vm-types", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "codespan-reporting", "datatest-stable", "hex", @@ -4632,7 +4627,7 @@ dependencies = [ name = "aptos-types" version = "0.0.3" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "anyhow", "aptos-bitvec", "aptos-crypto", @@ -4653,18 +4648,19 @@ dependencies = [ "bcs 0.1.4", "bytes", "chrono", - "chrono-tz 0.10.1", + "chrono-tz 0.10.4", "ciborium", "claims", "coset", "criterion", + "crypto", "dashmap 7.0.0-rc2", "derivative", "derive-getters", - "derive_more 2.0.1", + "derive_more 2.1.1", "fixed", "fxhash", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", "itertools 0.13.0", "jsonwebtoken 8.3.0", @@ -4690,21 +4686,22 @@ dependencies = [ "rand 0.7.3", "rayon", "ref-cast", - "reqwest 0.11.23", + "reqwest 0.11.27", "ring 0.16.20", - "rsa 0.9.6", + "rsa 0.9.10", "serde", "serde-big-array", "serde_bytes", "serde_json", "serde_with", "serde_yaml 0.8.26", - "strum 0.27.1", - "strum_macros 0.27.1", - "thiserror", + "strum 0.27.2", + "strum_macros 0.27.2", + "thiserror 1.0.69", "tokio", "tracing", "url", + "utoipa", ] [[package]] @@ -4753,7 +4750,7 @@ dependencies = [ "proptest", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "ureq", ] @@ -4792,7 +4789,8 @@ dependencies = [ "bytes", "claims", "crossbeam-channel", - "derive_more 2.0.1", + "crypto", + "derive_more 2.1.1", "fail", "futures", "hex", @@ -4823,7 +4821,7 @@ dependencies = [ "aptos-language-e2e-tests", "aptos-types", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "move-binary-format", "move-core-types", ] @@ -4866,6 +4864,7 @@ dependencies = [ "bcs 0.1.4", "bytes", "claims", + "crypto", "move-binary-format", "move-core-types", "move-vm-runtime", @@ -4906,7 +4905,7 @@ dependencies = [ "aptos-types", "aptos-vm", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "glob", "move-binary-format", "move-core-types", @@ -4978,7 +4977,7 @@ dependencies = [ "aptos-config", "aptos-logger", "bcs 0.1.4", - "hyper 0.14.28", + "hyper 0.14.32", "serde", "serde_json", "warp", @@ -4997,7 +4996,7 @@ dependencies = [ "aptos-node", "aptos-types", "bollard", - "clap 4.5.21", + "clap 4.6.1", "diesel", "diesel-async", "futures", @@ -5006,25 +5005,28 @@ dependencies = [ "rand 0.7.3", "tempfile", "tokio", - "tokio-util 0.7.10", + "tokio-util 0.7.18", "url", - "uuid 1.11.0", + "uuid 1.23.2", ] [[package]] name = "arbitrary" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" dependencies = [ "derive_arbitrary", ] [[package]] name = "arc-swap" -version = "1.6.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207" +dependencies = [ + "rustversion", +] [[package]] name = "ark-bls12-381" @@ -5065,7 +5067,7 @@ dependencies = [ "derivative", "digest 0.10.7", "rayon", - "sha2 0.10.8", + "sha2 0.10.9", ] [[package]] @@ -5099,7 +5101,7 @@ dependencies = [ "derivative", "digest 0.10.7", "itertools 0.10.5", - "num-bigint 0.4.4", + "num-bigint 0.4.6", "num-traits", "paste", "rayon", @@ -5123,7 +5125,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ - "num-bigint 0.4.4", + "num-bigint 0.4.6", "num-traits", "proc-macro2", "quote", @@ -5181,7 +5183,7 @@ dependencies = [ "ark-serialize-derive", "ark-std", "digest 0.10.7", - "num-bigint 0.4.4", + "num-bigint 0.4.6", ] [[package]] @@ -5214,7 +5216,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", - "rand 0.8.5", + "rand 0.8.6", "rayon", ] @@ -5242,9 +5244,9 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" @@ -5263,9 +5265,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "ascii-canvas" @@ -5273,7 +5275,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" dependencies = [ - "term", + "term 0.7.0", ] [[package]] @@ -5305,12 +5307,11 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.1.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" dependencies = [ "concurrent-queue", - "event-listener 4.0.3", "event-listener-strategy", "futures-core", "pin-project-lite", @@ -5318,29 +5319,27 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.11" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd066d0b4ef8ecb03a55319dc13aa6910616d0f44008a045bb1835af830abff5" +checksum = "e79b3f8a79cccc2898f31920fc69f304859b3bd567490f75ebf51ae1c792a9ac" dependencies = [ - "brotli", - "flate2", - "futures-core", - "memchr", + "compression-codecs", + "compression-core", "pin-project-lite", "tokio", ] [[package]] name = "async-executor" -version = "1.8.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" dependencies = [ - "async-lock 3.2.0", "async-task", "concurrent-queue", - "fastrand 2.0.1", - "futures-lite 2.2.0", + "fastrand", + "futures-lite", + "pin-project-lite", "slab", ] @@ -5350,154 +5349,125 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel 2.1.1", + "async-channel 2.5.0", "async-executor", - "async-io 2.2.2", - "async-lock 3.2.0", + "async-io", + "async-lock", "blocking", - "futures-lite 2.2.0", + "futures-lite", "once_cell", ] [[package]] name = "async-io" -version = "1.13.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" dependencies = [ - "async-lock 2.8.0", "autocfg", "cfg-if", "concurrent-queue", - "futures-lite 1.13.0", - "log", - "parking", - "polling 2.8.0", - "rustix 0.37.27", - "slab", - "socket2 0.4.10", - "waker-fn", -] - -[[package]] -name = "async-io" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6afaa937395a620e33dc6a742c593c01aced20aa376ffb0f628121198578ccc7" -dependencies = [ - "async-lock 3.2.0", - "cfg-if", - "concurrent-queue", "futures-io", - "futures-lite 2.2.0", + "futures-lite", "parking", - "polling 3.3.1", - "rustix 0.38.28", + "polling", + "rustix 1.1.4", "slab", - "tracing", - "windows-sys 0.52.0", -] - -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener 2.5.3", + "windows-sys 0.61.2", ] [[package]] name = "async-lock" -version = "3.2.0" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7125e42787d53db9dd54261812ef17e937c95a51e4d291373b670342fa44310c" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ - "event-listener 4.0.3", + "event-listener 5.4.1", "event-listener-strategy", "pin-project-lite", ] [[package]] name = "async-mutex" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" +checksum = "73112ce9e1059d8604242af62c7ec8e5975ac58ac251686c8403b45e8a6fe778" dependencies = [ "event-listener 2.5.3", ] [[package]] name = "async-object-pool" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeb901c30ebc2fc4ab46395bbfbdba9542c16559d853645d75190c3056caf3bc" +checksum = "333c456b97c3f2d50604e8b2624253b7f787208cb72eb75e64b0ad11b221652c" dependencies = [ "async-std", ] [[package]] name = "async-process" -version = "1.8.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" dependencies = [ - "async-io 1.13.0", - "async-lock 2.8.0", + "async-channel 2.5.0", + "async-io", + "async-lock", "async-signal", + "async-task", "blocking", "cfg-if", - "event-listener 3.1.0", - "futures-lite 1.13.0", - "rustix 0.38.28", - "windows-sys 0.48.0", + "event-listener 5.4.1", + "futures-lite", + "rustix 1.1.4", ] [[package]] name = "async-recursion" -version = "1.0.5" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "async-signal" -version = "0.2.5" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" +checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" dependencies = [ - "async-io 2.2.2", - "async-lock 2.8.0", + "async-io", + "async-lock", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.28", + "rustix 1.1.4", "signal-hook-registry", "slab", - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] name = "async-std" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" dependencies = [ "async-channel 1.9.0", "async-global-executor", - "async-io 1.13.0", - "async-lock 2.8.0", + "async-io", + "async-lock", "async-process", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", - "futures-lite 1.13.0", + "futures-lite", "gloo-timers", "kv-log-macro", "log", @@ -5511,9 +5481,9 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -5522,30 +5492,30 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "async-task" -version = "4.7.0" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.82" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -5561,9 +5531,9 @@ dependencies = [ [[package]] name = "atomic" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" dependencies = [ "bytemuck", ] @@ -5593,14 +5563,14 @@ checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "autometrics" @@ -5610,7 +5580,7 @@ checksum = "10eaae539e7319a3813dc8cd53776a7128bdd6d82067275c12586f5a0fce9137" dependencies = [ "autometrics-macros", "cfg_aliases 0.1.1", - "http 1.1.0", + "http 1.4.1", "linkme", "metrics-exporter-prometheus", "once_cell", @@ -5619,7 +5589,7 @@ dependencies = [ "prometheus", "prometheus-client", "spez", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -5632,7 +5602,29 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.87", + "syn 2.0.117", +] + +[[package]] +name = "aws-lc-rs" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", ] [[package]] @@ -5646,9 +5638,9 @@ dependencies = [ "bitflags 1.3.2", "bytes", "futures-util", - "http 0.2.11", + "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.32", "itoa", "matchit", "memchr", @@ -5658,25 +5650,25 @@ dependencies = [ "rustversion", "serde", "sync_wrapper 0.1.2", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", ] [[package]] name = "axum" -version = "0.7.5" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ "async-trait", - "axum-core 0.4.3", + "axum-core 0.4.5", "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http 1.4.1", + "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.10.1", "hyper-util", "itoa", "matchit", @@ -5689,9 +5681,9 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tokio", - "tower", + "tower 0.5.3", "tower-layer", "tower-service", "tracing", @@ -5706,7 +5698,7 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 0.2.11", + "http 0.2.12", "http-body 0.4.6", "mime", "rustversion", @@ -5716,20 +5708,20 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http 1.4.1", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", "rustversion", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.2", "tower-layer", "tower-service", "tracing", @@ -5737,9 +5729,9 @@ dependencies = [ [[package]] name = "az" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" +checksum = "be5eb007b7cacc6c660343e96f650fedf4b5a77512399eb952ca6642cf8d13f7" [[package]] name = "backoff" @@ -5748,28 +5740,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" dependencies = [ "futures-core", - "getrandom 0.2.11", + "getrandom 0.2.17", "instant", "pin-project-lite", - "rand 0.8.5", + "rand 0.8.6", "tokio", ] [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-link", ] +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base16ct" version = "0.2.0" @@ -5802,40 +5800,30 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.6.0" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "basic-cookies" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb53b6b315f924c7f113b162e53b3901c05fc9966baf84d201dfcc7432a4bb38" +checksum = "67bd8fd42c16bdb08688243dc5f0cc117a3ca9efeeaba3a345a18a6159ad96f7" dependencies = [ - "lalrpop 0.19.12", - "lalrpop-util 0.19.12", + "lalrpop", + "lalrpop-util", "regex", ] -[[package]] -name = "basic-toml" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2db21524cad41c5591204d22d75e1970a2d1f71060214ca931dc7d5afe2c14e5" -dependencies = [ - "serde", -] - [[package]] name = "bb8" -version = "0.8.1" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98b4b0f25f18bcdc3ac72bdb486ed0acf7e185221fd4dc985bc15db5800b0ba2" +checksum = "d89aabfae550a5c44b43ab941844ffcd2e993cb6900b342debf59e9ea74acdb8" dependencies = [ "async-trait", - "futures-channel", "futures-util", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "tokio", ] @@ -5845,7 +5833,7 @@ version = "0.1.4" source = "git+https://github.com/aptos-labs/bcs.git?rev=d31fab9d81748e2594be5cd5cdf845786a30562d#d31fab9d81748e2594be5cd5cdf845786a30562d" dependencies = [ "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -5855,7 +5843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b6598a2f5d564fb7855dc6b06fd1c38cff5a72bd8b863a4d021938497b440a" dependencies = [ "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -5872,7 +5860,7 @@ checksum = "9ae286c2cb403324ab644c7cc68dceb25fe52ca9429908a726d7ed272c1edf7b" dependencies = [ "bellpepper-core", "byteorder", - "ff 0.13.0", + "ff 0.13.1", ] [[package]] @@ -5883,9 +5871,9 @@ checksum = "1d8abb418570756396d722841b19edfec21d4e89e1cf8990610663040ecb1aea" dependencies = [ "blake2s_simd", "byteorder", - "ff 0.13.0", + "ff 0.13.1", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -5908,15 +5896,28 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "bicycl_rs" +version = "0.1.0" +source = "git+ssh://git@github.com/Entropy-Foundation/bicycl-rs?rev=e67e3ab#e67e3ab867ce4e2f302534c868d0dec24c59b043" +dependencies = [ + "gmp-mpfr-sys", + "libc", + "rand 0.8.6", + "serde", + "serde_bytes", + "sha3 0.10.9", +] + [[package]] name = "bigdecimal" -version = "0.4.2" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06619be423ea5bb86c95f087d5707942791a08a85530df0db2209a3ecfb8bc9" +checksum = "4d6867f1565b3aad85681f1015055b087fcfd840d6aeee6eee7f2da317603695" dependencies = [ "autocfg", "libm", - "num-bigint 0.4.4", + "num-bigint 0.4.6", "num-integer", "num-traits", "serde", @@ -5933,11 +5934,11 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.69.4" +version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.12.1", "cexpr", "clang-sys", "itertools 0.12.1", @@ -5946,9 +5947,9 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash", - "shlex", - "syn 2.0.87", + "rustc-hash 1.1.0", + "shlex 1.3.0", + "syn 2.0.117", ] [[package]] @@ -5983,9 +5984,9 @@ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bit_field" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" [[package]] name = "bitflags" @@ -5995,9 +5996,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a" [[package]] name = "bitmaps" @@ -6053,24 +6054,24 @@ dependencies = [ [[package]] name = "blake2b_simd" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +checksum = "b79834656f71332577234b50bfc009996f7449e0c056884e6a02492ded0ca2f3" dependencies = [ "arrayref", - "arrayvec 0.7.4", - "constant_time_eq 0.3.0", + "arrayvec 0.7.6", + "constant_time_eq 0.4.2", ] [[package]] name = "blake2s_simd" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94230421e395b9920d23df13ea5d77a20e1725331f90fbbf6df6040b33f756ae" +checksum = "ee29928bad1e3f94c9d1528da29e07a1d3d04817ae8332de1e8b846c8439f4b3" dependencies = [ "arrayref", - "arrayvec 0.7.4", - "constant_time_eq 0.3.0", + "arrayvec 0.7.6", + "constant_time_eq 0.4.2", ] [[package]] @@ -6092,33 +6093,48 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +dependencies = [ + "hybrid-array", +] + [[package]] name = "block-padding" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + [[package]] name = "blocking" -version = "1.5.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" dependencies = [ - "async-channel 2.1.1", - "async-lock 3.2.0", + "async-channel 2.5.0", "async-task", - "fastrand 2.0.1", "futures-io", - "futures-lite 2.2.0", + "futures-lite", "piper", - "tracing", ] [[package]] name = "blst" -version = "0.3.11" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" +checksum = "dcdb4c7013139a150f9fc55d123186dbfaba0d912817466282c73ac49e71fb45" dependencies = [ "cc", "glob", @@ -6150,7 +6166,7 @@ checksum = "7a8a8ed6fefbeef4a8c7b460e4110e12c5e22a5b7cf32621aae6ad650c4dcf29" dependencies = [ "blst", "byte-slice-cast", - "ff 0.13.0", + "ff 0.13.1", "group 0.13.0", "pairing 0.23.0", "rand_core 0.6.4", @@ -6171,10 +6187,10 @@ dependencies = [ "hex", "hex_fmt", "pairing 0.22.0", - "rand 0.8.5", + "rand 0.8.6", "rand_chacha 0.3.1", "serde", - "thiserror", + "thiserror 1.0.69", "tiny-keccak", "zeroize", ] @@ -6191,8 +6207,8 @@ dependencies = [ "futures-core", "futures-util", "hex", - "http 0.2.11", - "hyper 0.14.28", + "http 0.2.12", + "hyper 0.14.32", "hyperlocal", "log", "pin-project-lite", @@ -6201,9 +6217,9 @@ dependencies = [ "serde_json", "serde_repr", "serde_urlencoded", - "thiserror", + "thiserror 1.0.69", "tokio", - "tokio-util 0.7.10", + "tokio-util 0.7.18", "url", "winapi 0.3.9", ] @@ -6221,9 +6237,9 @@ dependencies = [ [[package]] name = "brotli" -version = "6.0.0" +version = "8.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" +checksum = "8119e4516436f5708bbc474a9d395bf12f1b5395e93a92a56e647ac3388c8610" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -6232,9 +6248,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "4.0.1" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" +checksum = "5962523e1b92ce1b5e793d9169b9943eece10d39f62550bc04bb605d75b94924" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -6242,40 +6258,36 @@ dependencies = [ [[package]] name = "bs58" -version = "0.5.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" -dependencies = [ - "sha2 0.10.8", - "tinyvec", -] +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] -name = "bstr" -version = "0.2.17" +name = "bs58" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ - "lazy_static", - "memchr", - "regex-automata 0.1.10", + "sha2 0.10.9", + "tinyvec", ] [[package]] name = "bstr" -version = "1.9.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" dependencies = [ "memchr", + "regex-automata", "serde", ] [[package]] name = "build_html" -version = "2.5.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225eb82ce9e70dcc0cfa6e404d0f353326b6e163bf500ec4711cec317d11935c" +checksum = "f1829197343f1874c1979c988a5e75c2539c4645792d87494286ce2cb6dc890d" [[package]] name = "bulletproofs" @@ -6288,13 +6300,13 @@ dependencies = [ "curve25519-dalek-ng", "digest 0.9.0", "merlin", - "rand 0.8.5", + "rand 0.8.6", "rand_core 0.6.4", "serde", "serde_derive", "sha3 0.9.1", "subtle-ng", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -6308,27 +6320,27 @@ dependencies = [ "digest 0.10.7", "group 0.13.0", "merlin", - "rand 0.8.5", + "rand 0.8.6", "rand_chacha 0.3.1", "rand_core 0.6.4", "serde", "serde_derive", - "sha3 0.10.8", + "sha3 0.10.9", "subtle", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "byte-slice-cast" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" [[package]] name = "bytecode-verifier-libfuzzer" @@ -6368,15 +6380,15 @@ dependencies = [ [[package]] name = "bytecount" -version = "0.6.7" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" +checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" [[package]] name = "byteorder" @@ -6386,37 +6398,26 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] [[package]] name = "bytesize" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" - -[[package]] -name = "bzip2" -version = "0.4.4" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] +checksum = "2e93abca9e28e0a1b9877922aacb20576e05d4679ffa78c3d6dc22a26a216659" [[package]] name = "bzip2-sys" -version = "0.1.11+1.0.8" +version = "0.1.13+1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" dependencies = [ "cc", - "libc", "pkg-config", ] @@ -6431,7 +6432,7 @@ name = "calc-dep-sizes" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.5.21", + "clap 4.6.1", "futures", "move-binary-format", "move-core-types", @@ -6441,11 +6442,11 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.6" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -6458,7 +6459,7 @@ dependencies = [ "regex", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -6471,17 +6472,27 @@ dependencies = [ "hound", "image", "lodepng", - "rand 0.8.5", + "rand 0.8.6", "serde_json", ] [[package]] name = "cargo-platform" -version = "0.1.6" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" +checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" dependencies = [ "serde", + "serde_core", ] [[package]] @@ -6491,8 +6502,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", - "cargo-platform", - "semver", + "cargo-platform 0.1.9", + "semver 1.0.28", "serde", "serde_json", ] @@ -6504,11 +6515,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" dependencies = [ "camino", - "cargo-platform", - "semver", + "cargo-platform 0.1.9", + "semver 1.0.28", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +dependencies = [ + "camino", + "cargo-platform 0.3.3", + "semver 1.0.28", "serde", "serde_json", - "thiserror", + "thiserror 2.0.18", ] [[package]] @@ -6525,19 +6550,23 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "castaway" -version = "0.1.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" +checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" +dependencies = [ + "rustversion", +] [[package]] name = "cc" -version = "1.2.16" +version = "1.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" dependencies = [ + "find-msvc-tools", "jobserver", "libc", - "shlex", + "shlex 2.0.1", ] [[package]] @@ -6551,9 +6580,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.6" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6100bc57b6209840798d95cb2775684849d332f7bd788db2a8c8caf7ef82a41a" +checksum = "fb693542bcafa528e198be0ebd9d3632ca5b7c93dbe7237460e199910835997c" dependencies = [ "smallvec", "target-lexicon", @@ -6561,9 +6590,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -6577,61 +6606,60 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", +] + [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.6", + "windows-link", ] [[package]] name = "chrono-tz" -version = "0.8.5" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d7b79e99bfaa0d47da0687c43aa3b7381938a62ad3a6498599039321f660b7" +checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb" dependencies = [ "chrono", - "chrono-tz-build 0.2.1", - "phf 0.11.2", + "chrono-tz-build", + "phf 0.11.3", ] [[package]] name = "chrono-tz" -version = "0.10.1" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c6ac4f2c0bf0f44e9161aec9675e1050aa4a530663c4a9e37e108fa948bca9f" +checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3" dependencies = [ "chrono", - "chrono-tz-build 0.4.0", - "phf 0.11.2", + "phf 0.12.1", ] [[package]] name = "chrono-tz-build" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433e39f13c9a060046954e0592a8d0a4bcb1040125cbf91cb8ee58964cfb350f" -dependencies = [ - "parse-zoneinfo", - "phf 0.11.2", - "phf_codegen", -] - -[[package]] -name = "chrono-tz-build" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94fea34d77a245229e7746bd2beb786cd2a896f306ff491fb8cecb3074b10a7" +checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1" dependencies = [ "parse-zoneinfo", + "phf 0.11.3", "phf_codegen", ] @@ -6643,9 +6671,9 @@ checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" [[package]] name = "ciborium" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", @@ -6654,18 +6682,18 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", - "half 1.8.2", + "half 2.7.1", ] [[package]] @@ -6674,7 +6702,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "inout", ] @@ -6689,9 +6717,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -6709,7 +6737,7 @@ dependencies = [ "bitflags 1.3.2", "strsim 0.8.0", "textwrap 0.11.0", - "unicode-width 0.1.11", + "unicode-width 0.1.14", "vec_map", ] @@ -6727,49 +6755,49 @@ dependencies = [ "once_cell", "strsim 0.10.0", "termcolor", - "textwrap 0.16.0", + "textwrap 0.16.2", ] [[package]] name = "clap" -version = "4.5.21" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", - "clap_derive 4.5.18", + "clap_derive 4.6.1", ] [[package]] name = "clap-verbosity-flag" -version = "2.1.1" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c90e95e5bd4e8ac34fa6f37c774b0c6f8ed06ea90c79931fd448fcf941a9767" +checksum = "34c77f67047557f62582784fd7482884697731b2932c7d37ced54bce2312e1e2" dependencies = [ - "clap 4.5.21", + "clap 4.6.1", "log", ] [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", - "clap_lex 0.7.3", + "clap_lex 1.1.0", "strsim 0.11.1", "terminal_size", ] [[package]] name = "clap_complete" -version = "4.4.6" +version = "4.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97aeaa95557bd02f23fbb662f981670c3d20c5a26e69f7354b28f57092437fcd" +checksum = "e0a7a9bfdb35811f9e59832f0f05975114d2251b415fb534108e6f34060fd772" dependencies = [ - "clap 4.5.21", + "clap 4.6.1", ] [[package]] @@ -6787,14 +6815,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -6808,9 +6836,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "clear_on_drop" @@ -6838,13 +6866,28 @@ dependencies = [ "lazy_static", "pem 0.8.3", "percent-encoding", - "reqwest 0.11.23", + "reqwest 0.11.27", "ring 0.16.20", "serde", "serde_json", "tokio", ] +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + [[package]] name = "codespan" version = "0.11.1" @@ -6863,7 +6906,7 @@ checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" dependencies = [ "serde", "termcolor", - "unicode-width 0.1.11", + "unicode-width 0.1.14", ] [[package]] @@ -6872,14 +6915,14 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b6be4a5df2098cd811f3194f64ddb96c267606bffd9689ac7b0160097b01ad3" dependencies = [ - "bs58", + "bs58 0.5.1", "coins-core", "digest 0.10.7", "hmac 0.12.1", - "k256", + "k256 0.13.4", "serde", - "sha2 0.10.8", - "thiserror", + "sha2 0.10.9", + "thiserror 1.0.69", ] [[package]] @@ -6893,9 +6936,9 @@ dependencies = [ "hmac 0.12.1", "once_cell", "pbkdf2 0.12.2", - "rand 0.8.5", - "sha2 0.10.8", - "thiserror", + "rand 0.8.6", + "sha2 0.10.9", + "thiserror 1.0.69", ] [[package]] @@ -6906,16 +6949,16 @@ checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" dependencies = [ "base64 0.21.7", "bech32", - "bs58", + "bs58 0.5.1", "digest 0.10.7", "generic-array", "hex", "ripemd", "serde", "serde_derive", - "sha2 0.10.8", - "sha3 0.10.8", - "thiserror", + "sha2 0.10.9", + "sha3 0.10.9", + "thiserror 1.0.69", ] [[package]] @@ -6926,40 +6969,60 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "colored" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "combine" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", "futures-core", "memchr", "pin-project-lite", "tokio", - "tokio-util 0.7.10", + "tokio-util 0.7.18", +] + +[[package]] +name = "compression-codecs" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce2548391e9c1929c21bf6aa2680af86fe4c1b33e6cea9ac1cfeec0bd11218cf" +dependencies = [ + "brotli", + "compression-core", + "flate2", + "memchr", + "zstd", + "zstd-safe", ] +[[package]] +name = "compression-core" +version = "0.4.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc14f565cf027a105f7a44ccf9e5b424348421a1d8952a8fc9d499d313107789" + [[package]] name = "compute-module-expansion-size" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.5.21", + "clap 4.6.1", "futures", "move-binary-format", "move-core-types", @@ -6969,24 +7032,36 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] [[package]] name = "console" -version = "0.15.7" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" dependencies = [ - "encode_unicode 0.3.6", - "lazy_static", + "encode_unicode", "libc", - "unicode-width 0.1.11", - "windows-sys 0.45.0", + "once_cell", + "unicode-width 0.2.2", + "windows-sys 0.59.0", +] + +[[package]] +name = "console" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" +dependencies = [ + "encode_unicode", + "libc", + "unicode-width 0.2.2", + "windows-sys 0.61.2", ] [[package]] @@ -6996,8 +7071,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a257c22cd7e487dd4a13d413beabc512c5052f0bc048db0da6a84c3d8a6142fd" dependencies = [ "futures-core", - "prost 0.12.3", - "prost-types 0.12.3", + "prost 0.12.6", + "prost-types 0.12.6", "tonic 0.11.0", "tracing-core", ] @@ -7014,8 +7089,8 @@ dependencies = [ "futures-task", "hdrhistogram", "humantime", - "prost 0.12.3", - "prost-types 0.12.3", + "prost 0.12.6", + "prost-types 0.12.6", "serde", "serde_json", "thread_local", @@ -7024,20 +7099,19 @@ dependencies = [ "tonic 0.11.0", "tracing", "tracing-core", - "tracing-subscriber 0.3.18", + "tracing-subscriber 0.3.23", ] [[package]] name = "const-hex" -version = "1.14.0" +version = "1.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0485bab839b018a8f1723fc5391819fea5f8f0f32288ef8a735fd096b6160c" +checksum = "33e2a781ebdf4467d1428dc4593067825fb646f6871475098d8577421af73558" dependencies = [ "cfg-if", - "cpufeatures", - "hex", + "cpufeatures 0.2.17", "proptest", - "serde", + "serde_core", ] [[package]] @@ -7052,6 +7126,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + [[package]] name = "const-random" version = "0.1.18" @@ -7067,24 +7147,25 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.17", "once_cell", "tiny-keccak", ] [[package]] name = "const_fn" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" +checksum = "413d67b29ef1021b4d60f4aa1e925ca031751e213832b4b1d588fae623c05c60" [[package]] name = "const_format" -version = "0.2.34" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" dependencies = [ "const_format_proc_macros", + "konst", ] [[package]] @@ -7106,65 +7187,47 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "constant_time_eq" -version = "0.3.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" [[package]] name = "convert_case" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" dependencies = [ "unicode-segmentation", ] [[package]] name = "convert_case" -version = "0.7.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" dependencies = [ "unicode-segmentation", ] [[package]] name = "cookie" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - -[[package]] -name = "cookie" -version = "0.18.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24" dependencies = [ - "aes-gcm", - "base64 0.22.1", - "hkdf 0.12.4", - "hmac 0.12.1", "percent-encoding", - "rand 0.8.5", - "sha2 0.10.8", - "subtle", "time", "version_check", ] [[package]] name = "cookie_store" -version = "0.16.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d606d0fba62e13cf04db20536c05cb7f13673c161cb47a47a82b9b9e7d3f1daa" +checksum = "387461abbc748185c3a6e1673d826918b450b87ff22639429c694619a83b6cf6" dependencies = [ - "cookie 0.16.2", - "idna 0.2.3", + "cookie", + "idna 0.3.0", "log", "publicsuffix", "serde", @@ -7184,6 +7247,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -7192,9 +7265,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core_affinity" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622892f5635ce1fc38c8f16dfc938553ed64af482edb5e150bf4caedbfcb2304" +checksum = "a034b3a7b624016c6e13f5df875747cc25f884156aad2abd12b6c46797971342" dependencies = [ "libc", "num_cpus", @@ -7203,37 +7276,65 @@ dependencies = [ [[package]] name = "coset" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c214bbc5c8b4518856d79cae4d323feaa881ecf3e31b5af6572bb5313c11d5" +checksum = "f4c8cc80f631f8307b887faca24dcc3abc427cd0367f6eb6188f6e8f5b7ad8fb" dependencies = [ "ciborium", "ciborium-io", ] +[[package]] +name = "cpp_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a4fc172d5c7797a79e4f0e976bec2d4b80b39989d48d58386aaa9a533ff389" +dependencies = [ + "libc", +] + [[package]] name = "cpp_demangle" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8227005286ec39567949b33df9896bcadfa6051bccca2488129f108ca23119" +checksum = "f2bb79cb74d735044c972aae58ed0aaa9a837e85b01106a54c39e42e97f62253" dependencies = [ "cfg-if", ] +[[package]] +name = "cpp_std" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6acdfb694abd411532cd836467462172cf3f9b78d3d3aff28a69d676665339" +dependencies = [ + "cpp_core", + "ritual_build", +] + [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] @@ -7299,18 +7400,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.11" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -7327,18 +7428,18 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crossterm" @@ -7350,7 +7451,7 @@ dependencies = [ "crossterm_winapi", "libc", "mio 0.8.11", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "signal-hook", "signal-hook-mio", "winapi 0.3.9", @@ -7366,7 +7467,7 @@ dependencies = [ "crossterm_winapi", "libc", "mio 0.8.11", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "signal-hook", "signal-hook-mio", "winapi 0.3.9", @@ -7383,9 +7484,36 @@ dependencies = [ [[package]] name = "crunchy" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto" +version = "0.1.0" +source = "git+ssh://git@github.com/Entropy-Foundation/crypto?rev=d045a68#d045a6875200975fb60c34ac74be08eef5b164b4" +dependencies = [ + "base64 0.22.1", + "bicycl_rs", + "bincode", + "blst", + "blsttc", + "cpp_std", + "ed25519-dalek 2.2.0", + "hex", + "lazy_static", + "miracl_core_bls12381", + "rand 0.8.6", + "rand_chacha 0.2.2", + "rand_core 0.6.4", + "rayon", + "serde", + "sha3 0.10.9", + "statrs", + "thiserror 1.0.69", + "tiny-keccak", + "zeroize", +] [[package]] name = "crypto-bigint" @@ -7397,6 +7525,18 @@ dependencies = [ "subtle", ] +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -7411,15 +7551,24 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "rand_core 0.6.4", "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + [[package]] name = "crypto-mac" version = "0.8.0" @@ -7442,33 +7591,33 @@ dependencies = [ [[package]] name = "csv" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" dependencies = [ "csv-core", "itoa", "ryu", - "serde", + "serde_core", ] [[package]] name = "csv-core" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" dependencies = [ "memchr", ] [[package]] name = "ctor" -version = "0.1.26" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +checksum = "01334b89b69ff726750c5ce5073fc8bd860e99aa9a8fc5ca11b04730e3aee97a" dependencies = [ - "quote", - "syn 1.0.109", + "link-section", + "linktime-proc-macro", ] [[package]] @@ -7482,34 +7631,44 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.2" +version = "3.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b" +checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" dependencies = [ - "nix 0.27.1", - "windows-sys 0.52.0", + "dispatch2", + "nix 0.31.3", + "windows-sys 0.61.2", +] + +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", ] [[package]] name = "curl" -version = "0.4.44" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" +checksum = "79fc3b6dd0b87ba36e565715bf9a2ced221311db47bd18011676f24a6066edbc" dependencies = [ "curl-sys", "libc", - "openssl-probe", + "openssl-probe 0.1.6", "openssl-sys", "schannel", - "socket2 0.4.10", - "winapi 0.3.9", + "socket2 0.6.4", + "windows-sys 0.59.0", ] [[package]] name = "curl-sys" -version = "0.4.70+curl-8.5.0" +version = "0.4.87+curl-8.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0333d8849afe78a4c8102a429a446bfdd055832af071945520e835ae2d841e" +checksum = "61a460380f0ef783703dcbe909107f39c162adeac050d73c850055118b5b6327" dependencies = [ "cc", "libc", @@ -7518,7 +7677,7 @@ dependencies = [ "openssl-sys", "pkg-config", "vcpkg", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -7541,7 +7700,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", @@ -7558,7 +7717,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -7587,12 +7746,22 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.10" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" dependencies = [ - "darling_core 0.20.10", - "darling_macro 0.20.10", + "darling_core 0.23.0", + "darling_macro 0.23.0", ] [[package]] @@ -7611,16 +7780,29 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.87", + "syn 2.0.117", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim 0.11.1", + "syn 2.0.117", ] [[package]] @@ -7636,13 +7818,24 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ - "darling_core 0.20.10", + "darling_core 0.23.0", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -7652,10 +7845,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.3", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core 0.9.12", +] + +[[package]] +name = "dashmap" +version = "6.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", "lock_api", "once_cell", - "parking_lot_core 0.9.10", + "parking_lot_core 0.9.12", ] [[package]] @@ -7667,16 +7874,16 @@ dependencies = [ "cfg-if", "crossbeam-utils", "equivalent", - "hashbrown 0.15.3", + "hashbrown 0.15.5", "lock_api", - "parking_lot_core 0.9.10", + "parking_lot_core 0.9.12", ] [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] name = "datatest-stable" @@ -7714,9 +7921,9 @@ dependencies = [ [[package]] name = "deadpool-runtime" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63dfa964fe2a66f3fde91fc70b267fe193d822c7e603e2a675a49a7f46ad3f49" +checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" dependencies = [ "tokio", ] @@ -7745,7 +7952,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" dependencies = [ - "uuid 1.11.0", + "uuid 1.23.2", ] [[package]] @@ -7756,7 +7963,7 @@ checksum = "4e018fccbeeb50ff26562ece792ed06659b9c2dae79ece77c4456bb10d9bf79b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -7772,9 +7979,19 @@ dependencies = [ [[package]] name = "der" -version = "0.7.8" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid 0.9.6", + "zeroize", +] + +[[package]] +name = "der" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid 0.9.6", "pem-rfc7468 0.7.0", @@ -7783,12 +8000,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", - "serde", + "serde_core", ] [[package]] @@ -7816,49 +8033,49 @@ checksum = "74ef43543e701c01ad77d3a5922755c6a1d71b22d942cb8042be4994b380caff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "derive_arbitrary" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "derive_builder" -version = "0.20.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ "derive_builder_macro", ] [[package]] name = "derive_builder_core" -version = "0.20.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ - "darling 0.20.10", + "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "derive_builder_macro" -version = "0.20.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -7883,11 +8100,11 @@ dependencies = [ [[package]] name = "derive_more" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ - "derive_more-impl 2.0.1", + "derive_more-impl 2.1.1", ] [[package]] @@ -7898,20 +8115,20 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", - "unicode-xid", + "syn 2.0.117", ] [[package]] name = "derive_more-impl" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ - "convert_case 0.7.1", + "convert_case 0.10.0", "proc-macro2", "quote", - "syn 2.0.87", + "rustc_version", + "syn 2.0.117", "unicode-xid", ] @@ -7934,9 +8151,9 @@ dependencies = [ [[package]] name = "deunicode" -version = "1.4.2" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae2a35373c5c74340b79ae6780b498b2b183915ec5dacf263aac5a099bf485a" +checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04" [[package]] name = "diesel" @@ -7945,18 +8162,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35b696af9ff4c0d2a507db2c5faafa8aa0205e297e5f11e203a24226d5355e7a" dependencies = [ "bigdecimal", - "bitflags 2.9.1", + "bitflags 2.12.1", "byteorder", "chrono", "diesel_derives", "itoa", - "num-bigint 0.4.4", + "num-bigint 0.4.6", "num-integer", "num-traits", "pq-sys", "r2d2", "serde_json", - "uuid 1.11.0", + "uuid 1.23.2", ] [[package]] @@ -7975,15 +8192,15 @@ dependencies = [ [[package]] name = "diesel_derives" -version = "2.2.4" +version = "2.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a93958254b70bea63b4187ff73d10180599d9d8d177071b7f91e6da4e0c0ad55" +checksum = "1b96984c469425cb577bf6f17121ecb3e4fe1e81de5d8f780dd372802858d756" dependencies = [ "diesel_table_macro_syntax", "dsl_auto_type", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -8003,7 +8220,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "209c735641a413bc68c4923a9d6ad4bcb3ca306b794edaa7eb0b3228a99ffb25" dependencies = [ - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -8050,10 +8267,22 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "const-oid 0.9.6", - "crypto-common", + "crypto-common 0.1.7", "subtle", ] +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.0", + "const-oid 0.10.2", + "crypto-common 0.2.2", + "ctutils", +] + [[package]] name = "dir-diff" version = "0.3.3" @@ -8125,11 +8354,34 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.12.1", + "block2", + "libc", + "objc2", +] + +[[package]] +name = "displaydoc" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "doc-comment" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +checksum = "780955b8b195a21ab8e4ac6b60dd1dbdcec1dc6c51c0617964b08c81785e12c9" [[package]] name = "dotenv" @@ -8149,25 +8401,25 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "139ae9aca7527f85f26dd76483eb38533fd84bd571065da1739656ef71c5ff5b" dependencies = [ - "darling 0.20.10", + "darling 0.20.11", "either", "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "dtoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" [[package]] name = "dunce" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "dw" @@ -8192,9 +8444,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.17" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "e2e-move-tests" @@ -8219,6 +8471,7 @@ dependencies = [ "aptos-vm-types", "bcs 0.1.4", "claims", + "crypto", "hex", "move-binary-format", "move-core-types", @@ -8236,16 +8489,28 @@ dependencies = [ "tokio", ] +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der 0.6.1", + "elliptic-curve 0.12.3", + "rfc6979 0.3.1", + "signature 1.6.4", +] + [[package]] name = "ecdsa" version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der 0.7.8", + "der 0.7.10", "digest 0.10.7", - "elliptic-curve", - "rfc6979", + "elliptic-curve 0.13.8", + "rfc6979 0.4.0", "signature 2.2.0", "spki 0.7.3", ] @@ -8287,14 +8552,15 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" dependencies = [ "curve25519-dalek 4.1.3", "ed25519 2.2.3", + "rand_core 0.6.4", "serde", - "sha2 0.10.8", + "sha2 0.10.9", "signature 2.2.0", "subtle", "zeroize", @@ -8309,14 +8575,34 @@ dependencies = [ "derivation-path", "ed25519-dalek 1.0.1", "hmac 0.12.1", - "sha2 0.10.8", + "sha2 0.10.9", ] [[package]] name = "either" -version = "1.9.0" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + +[[package]] +name = "elliptic-curve" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct 0.1.1", + "crypto-bigint 0.4.9", + "der 0.6.1", + "digest 0.10.7", + "ff 0.12.1", + "generic-array", + "group 0.12.1", + "pkcs8 0.9.0", + "rand_core 0.6.4", + "sec1 0.3.0", + "subtle", + "zeroize", +] [[package]] name = "elliptic-curve" @@ -8324,17 +8610,17 @@ version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ - "base16ct", + "base16ct 0.2.0", "base64ct", "crypto-bigint 0.5.5", "digest 0.10.7", - "ff 0.13.0", + "ff 0.13.1", "generic-array", "group 0.13.0", "pem-rfc7468 0.7.0", "pkcs8 0.10.2", "rand_core 0.6.4", - "sec1", + "sec1 0.7.3", "serde_json", "serdect", "subtle", @@ -8343,19 +8629,13 @@ dependencies = [ [[package]] name = "ena" -version = "0.14.2" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" +checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1" dependencies = [ "log", ] -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - [[package]] name = "encode_unicode" version = "1.0.0" @@ -8364,48 +8644,58 @@ checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] [[package]] name = "enr" -version = "0.10.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a3d8dc56e02f954cac8eb489772c552c473346fc34f67412bb6244fd647f7e4" +checksum = "492a7e5fc2504d5fdce8e124d3e263b244a68b283cac67a69eda0cd43e0aebad" dependencies = [ - "base64 0.21.7", + "base64 0.13.1", + "bs58 0.4.0", "bytes", "hex", - "k256", + "k256 0.11.6", "log", - "rand 0.8.5", + "rand 0.8.6", "rlp", "serde", - "sha3 0.10.8", + "sha3 0.10.9", "zeroize", ] [[package]] name = "enum_dispatch" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f33313078bb8d4d05a2733a94ac4c2d8a0df9a2b84424ebf4f33bfc224a890e" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", +] + +[[package]] +name = "env_filter" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" +dependencies = [ + "log", ] [[package]] name = "env_logger" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" dependencies = [ "humantime", "is-terminal", @@ -8414,11 +8704,21 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.11.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" +dependencies = [ + "env_filter", + "log", +] + [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "erased-serde" @@ -8431,12 +8731,12 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.8" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -8460,13 +8760,13 @@ dependencies = [ "hex", "hmac 0.12.1", "pbkdf2 0.11.0", - "rand 0.8.5", + "rand 0.8.6", "scrypt", "serde", "serde_json", - "sha2 0.10.8", - "sha3 0.10.8", - "thiserror", + "sha2 0.10.9", + "sha3 0.10.9", + "thiserror 1.0.69", "uuid 0.8.2", ] @@ -8477,10 +8777,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3aeb0284b473041df2419a28e3cdf0c64a78d2b9511af4b6e40bad3964b172" dependencies = [ "ethereum-types", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "keccak-hash", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "rlp", ] @@ -8496,8 +8796,8 @@ dependencies = [ "regex", "serde", "serde_json", - "sha3 0.10.8", - "thiserror", + "sha3 0.10.9", + "thiserror 1.0.69", "uint", ] @@ -8534,9 +8834,9 @@ dependencies = [ [[package]] name = "ethers" -version = "2.0.14" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816841ea989f0c69e459af1cf23a6b0033b19a55424a1ea3a30099becdb8dec0" +checksum = "839a392641e746a1ff365ef7c901238410b5c6285d240cf2409ffaaa7df9a78a" dependencies = [ "ethers-addressbook", "ethers-contract", @@ -8545,7 +8845,6 @@ dependencies = [ "ethers-middleware", "ethers-providers", "ethers-signers", - "ethers-solc", ] [[package]] @@ -8570,13 +8869,12 @@ dependencies = [ "ethers-contract-abigen", "ethers-contract-derive", "ethers-core", - "ethers-providers", "futures-util", "once_cell", - "pin-project 1.1.3", + "pin-project 1.1.13", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -8589,17 +8887,15 @@ dependencies = [ "const-hex", "dunce", "ethers-core", - "ethers-etherscan", "eyre", "prettyplease", "proc-macro2", "quote", "regex", - "reqwest 0.11.23", "serde", "serde_json", - "syn 2.0.87", - "toml 0.8.12", + "syn 2.0.117", + "toml 0.8.23", "walkdir", ] @@ -8616,7 +8912,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -8625,26 +8921,26 @@ version = "2.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "bytes", "cargo_metadata 0.18.1", "chrono", "const-hex", - "elliptic-curve", + "elliptic-curve 0.13.8", "ethabi", "generic-array", - "k256", + "k256 0.13.4", "num_enum", "once_cell", "open-fastrlp", - "rand 0.8.5", + "rand 0.8.6", "rlp", "serde", "serde_json", "strum 0.26.3", - "syn 2.0.87", + "syn 2.0.117", "tempfile", - "thiserror", + "thiserror 1.0.69", "tiny-keccak", "unicode-xid", ] @@ -8657,19 +8953,19 @@ checksum = "e79e5973c26d4baf0ce55520bd732314328cabe53193286671b47144145b9649" dependencies = [ "chrono", "ethers-core", - "reqwest 0.11.23", - "semver", + "reqwest 0.11.27", + "semver 1.0.28", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tracing", ] [[package]] name = "ethers-middleware" -version = "2.0.14" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f9fdf09aec667c099909d91908d5eaf9be1bd0e2500ba4172c1d28bfaa43de" +checksum = "a7dd311b76eab9d15209e4fd16bb419e25543709cbdf33079e8923dfa597517c" dependencies = [ "async-trait", "auto_impl", @@ -8678,14 +8974,13 @@ dependencies = [ "ethers-etherscan", "ethers-providers", "ethers-signers", - "futures-channel", "futures-locks", "futures-util", "instant", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "tracing-futures", @@ -8694,37 +8989,36 @@ dependencies = [ [[package]] name = "ethers-providers" -version = "2.0.14" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6434c9a33891f1effc9c75472e12666db2fa5a0fec4b29af6221680a6fe83ab2" +checksum = "ed7174af93619e81844d3d49887106a3721e5caecdf306e0b824bfb4316db3be" dependencies = [ "async-trait", "auto_impl", "base64 0.21.7", - "bytes", - "const-hex", "enr", "ethers-core", "futures-core", "futures-timer", "futures-util", + "getrandom 0.2.17", "hashers", - "http 0.2.11", - "instant", - "jsonwebtoken 8.3.0", + "hex", + "http 0.2.12", "once_cell", - "pin-project 1.1.3", - "reqwest 0.11.23", + "parking_lot 0.11.2", + "pin-project 1.1.13", + "reqwest 0.11.27", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", - "tokio-tungstenite", "tracing", "tracing-futures", "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-timer", "web-sys", "ws_stream_wasm", ] @@ -8739,52 +9033,20 @@ dependencies = [ "coins-bip32", "coins-bip39", "const-hex", - "elliptic-curve", + "elliptic-curve 0.13.8", "eth-keystore", "ethers-core", - "rand 0.8.5", - "sha2 0.10.8", - "thiserror", - "tracing", -] - -[[package]] -name = "ethers-solc" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66244a771d9163282646dbeffe0e6eca4dda4146b6498644e678ac6089b11edd" -dependencies = [ - "cfg-if", - "const-hex", - "dirs 5.0.1", - "dunce", - "ethers-core", - "glob", - "home", - "md-5", - "num_cpus", - "once_cell", - "path-slash", - "rayon", - "regex", - "semver", - "serde", - "serde_json", - "solang-parser", - "svm-rs", - "thiserror", - "tiny-keccak", - "tokio", + "rand 0.8.6", + "sha2 0.10.9", + "thiserror 1.0.69", "tracing", - "walkdir", - "yansi 0.5.1", ] [[package]] name = "ethnum" -version = "1.5.0" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" +checksum = "40404c3f5f511ec4da6fe866ddf6a717c309fdbb69fbbad7b0f3edab8f2e835f" [[package]] name = "event-listener" @@ -8794,20 +9056,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener" -version = "4.0.3" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ "concurrent-queue", "parking", @@ -8816,23 +9067,22 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.4.0" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener 4.0.3", + "event-listener 5.4.1", "pin-project-lite", ] [[package]] name = "exr" -version = "1.71.0" +version = "1.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" dependencies = [ "bit_field", - "flume", - "half 2.2.1", + "half 2.7.1", "lebe", "miniz_oxide", "rayon-core", @@ -8858,44 +9108,48 @@ checksum = "fe5e43d0f78a42ad591453aedb1d7ae631ce7ee445c7643691055a9ed8d3b01c" dependencies = [ "log", "once_cell", - "rand 0.8.5", + "rand 0.8.6", ] [[package]] -name = "fallible-iterator" -version = "0.2.0" +name = "failure" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] [[package]] -name = "fallible_collections" -version = "0.4.9" +name = "failure_derive" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88c69768c0a15262df21899142bc6df9b9b823546d4b4b9a7bc2d6c448ec6fd" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "hashbrown 0.13.2", + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure 0.12.6", ] [[package]] -name = "fastrand" -version = "1.9.0" +name = "fallible-iterator" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "fastrand" -version = "2.0.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "fdeflate" -version = "0.3.3" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209098dd6dfc4445aa6111f0e98653ac323eaa4dfd212c9ca3931bf9955c31bd" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ "simd-adler32", ] @@ -8913,9 +9167,9 @@ dependencies = [ [[package]] name = "ff" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ "bitvec 1.0.1", "byteorder", @@ -8926,12 +9180,11 @@ dependencies = [ [[package]] name = "ff_derive" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f54704be45ed286151c5e11531316eaef5b8f5af7d597b806fdb8af108d84a" +checksum = "f10d12652036b0e99197587c6ba87a8fc3031986499973c030d8b44fcc151b60" dependencies = [ "addchain", - "cfg-if", "num-bigint 0.3.3", "num-integer", "num-traits", @@ -8974,7 +9227,7 @@ dependencies = [ "atomic", "pear", "serde", - "serde_yaml 0.9.30", + "serde_yaml 0.9.34+deprecated", "uncased", "version_check", ] @@ -8987,16 +9240,20 @@ checksum = "31a7a908b8f32538a2143e59a6e4e2508988832d5d4d6f7c156b3cbc762643a5" [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + [[package]] name = "findshlibs" version = "0.10.2" @@ -9009,19 +9266,13 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "finl_unicode" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" - [[package]] name = "firebase-token" version = "0.3.0" source = "git+https://github.com/aptos-labs/firebase-token?rev=34ea512d3d1fad6c11df3e7d82ff72beccc05836#34ea512d3d1fad6c11df3e7d82ff72beccc05836" dependencies = [ "jsonwebtoken 8.3.0", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "tokio", "tracing", @@ -9029,9 +9280,9 @@ dependencies = [ [[package]] name = "firestore" -version = "0.43.0" +version = "0.43.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f7f676812c6a51d8584aa52252e2d3a02417ee0b27966c7059fe4ef80945d5" +checksum = "483bce3ebe3bec625c4a3800a84966e966604e274ea9acbe7e6429477f915445" dependencies = [ "async-trait", "backoff", @@ -9039,8 +9290,8 @@ dependencies = [ "futures", "gcloud-sdk", "hex", - "hyper 1.4.1", - "rand 0.8.5", + "hyper 1.10.1", + "rand 0.8.6", "rsb_derive", "rvstruct", "serde", @@ -9052,13 +9303,13 @@ dependencies = [ [[package]] name = "fixed" -version = "1.25.1" +version = "1.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e29e5681dc8556fb9df1409e95eae050e12e8776394313da3546dcb8cf390c73" +checksum = "9af2cbf772fa6d1c11358f92ef554cb6b386201210bcf0e91fb7fba8a907fb40" dependencies = [ "az", "bytemuck", - "half 2.2.1", + "half 2.7.1", "typenum", ] @@ -9069,7 +9320,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" dependencies = [ "byteorder", - "rand 0.8.5", + "rand 0.8.6", "rustc-hex", "static_assertions", ] @@ -9081,7 +9332,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ "byteorder", - "rand 0.8.5", + "rand 0.8.6", "rustc-hex", "static_assertions", ] @@ -9098,14 +9349,21 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "flate2" -version = "1.0.28" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", + "zlib-rs", ] [[package]] @@ -9121,7 +9379,7 @@ dependencies = [ "log", "nu-ansi-term 0.49.0", "regex", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -9133,15 +9391,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "flume" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" -dependencies = [ - "spin 0.9.8", -] - [[package]] name = "fnv" version = "1.0.7" @@ -9154,6 +9403,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.3.2" @@ -9181,7 +9436,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -9198,28 +9453,27 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] [[package]] name = "fragile" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" +checksum = "8878864ba14bb86e818a412bfd6f18f9eabd4ec0f008a28e8f7eb61db532fcf9" +dependencies = [ + "futures-core", +] [[package]] -name = "fs2" -version = "0.4.3" +name = "fs_extra" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi 0.3.9", -] +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "fst" @@ -9241,8 +9495,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" -source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -9255,8 +9510,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" -source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -9264,13 +9520,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" -source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.30" -source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -9279,42 +9537,28 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" -source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-lite" -version = "1.13.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ - "fastrand 1.9.0", + "fastrand", "futures-core", "futures-io", - "memchr", "parking", "pin-project-lite", - "waker-fn", ] [[package]] -name = "futures-lite" -version = "2.2.0" +name = "futures-locks" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" -dependencies = [ - "fastrand 2.0.1", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - -[[package]] -name = "futures-locks" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06" +checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06" dependencies = [ "futures-channel", "futures-task", @@ -9322,38 +9566,38 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.30" -source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "futures-sink" -version = "0.3.30" -source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.30" -source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-timer" -version = "3.0.2" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" -dependencies = [ - "gloo-timers", - "send_wrapper 0.4.0", -] +checksum = "af43fadb8a98512d547e37b4e92e0ced13e205c061b87b4623eff01d918d6968" [[package]] name = "futures-util" -version = "0.3.30" -source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -9363,7 +9607,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -9377,7 +9620,7 @@ dependencies = [ "arbitrary", "base64 0.21.7", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "csv", "dearbitrary", "hex", @@ -9437,26 +9680,26 @@ checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" [[package]] name = "gcloud-sdk" -version = "0.25.3" +version = "0.25.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "898e349fb0fabc16892de7858e5650b70a8044edeee13469cb2f7649040bf3c2" +checksum = "0775bfa745cdf7287ae9765a685a813b91049b6b6d5ca3de20a3d5d16a80d8b2" dependencies = [ "async-trait", "bytes", "chrono", "futures", - "hyper 1.4.1", - "jsonwebtoken 9.3.0", + "hyper 1.10.1", + "jsonwebtoken 9.3.1", "once_cell", - "prost 0.13.4", - "prost-types 0.13.1", - "reqwest 0.12.5", + "prost 0.13.5", + "prost-types 0.13.5", + "reqwest 0.12.28", "secret-vault-value", "serde", "serde_json", "tokio", "tonic 0.12.3", - "tower", + "tower 0.5.3", "tower-layer", "tower-util", "tracing", @@ -9472,13 +9715,13 @@ dependencies = [ "async-stream", "async-trait", "dyn-clone", - "hyper 0.14.28", + "hyper 0.14.32", "hyper-rustls 0.24.2", "log", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "time", "tokio", "tokio-stream", @@ -9499,7 +9742,7 @@ dependencies = [ "aptos-network", "aptos-types", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "move-core-types", "rand 0.7.3", "serde", @@ -9555,34 +9798,50 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "r-efi 6.0.0", + "rand_core 0.10.1", + "wasip2", + "wasip3", ] [[package]] name = "ghash" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" dependencies = [ "opaque-debug", "polyval", @@ -9590,9 +9849,9 @@ dependencies = [ [[package]] name = "gif" -version = "0.12.0" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" +checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" dependencies = [ "color_quant", "weezl", @@ -9600,9 +9859,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "git2" @@ -9627,46 +9886,46 @@ dependencies = [ "libc", "libgit2-sys", "log", - "openssl-probe", + "openssl-probe 0.1.6", "openssl-sys", "url", ] [[package]] name = "glob" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "globset" -version = "0.4.14" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" dependencies = [ "aho-corasick", - "bstr 1.9.0", + "bstr", "log", - "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "regex-automata", + "regex-syntax", ] [[package]] name = "globwalk" -version = "0.8.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.12.1", "ignore", "walkdir", ] [[package]] name = "gloo-timers" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" dependencies = [ "futures-channel", "futures-core", @@ -9674,16 +9933,27 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gmp-mpfr-sys" +version = "1.6.8" +source = "git+ssh://git@github.com/Entropy-Foundation/gmp-mpfr-sys.git?branch=master#6d5c91968d809b692df0abdcc3d93ce3588ff7ad" +dependencies = [ + "cc", + "libc", + "windows-sys 0.60.2", +] + [[package]] name = "goldenfile" -version = "1.6.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a67453a3b358bd8213aedafd4feed75eecab9fb04bed26ba6fdf94694be560" +checksum = "206600f27ef687e85a572315eb297c79f66620b2b3eeb3a6cde17f25e049ae5b" dependencies = [ "scopeguard", "similar-asserts", + "static_assertions", "tempfile", - "yansi 1.0.0-rc.1", + "yansi", ] [[package]] @@ -9698,10 +9968,10 @@ dependencies = [ "google-cloud-token", "home", "jsonwebtoken 8.3.0", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "time", "tokio", "tracing", @@ -9715,12 +9985,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8bdaaa4bc036e8318274d1b25f0f2265b3e95418b765fd1ea1c7ef938fd69bd" dependencies = [ "google-cloud-token", - "http 0.2.11", - "thiserror", + "http 0.2.12", + "thiserror 1.0.69", "tokio", "tokio-retry", "tonic 0.9.2", - "tower", + "tower 0.4.13", "tracing", ] @@ -9741,8 +10011,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96e4ad0802d3f416f62e7ce01ac1460898ee0efc98f8b45cd4aab7611607012f" dependencies = [ - "reqwest 0.11.23", - "thiserror", + "reqwest 0.11.27", + "thiserror 1.0.69", "tokio", ] @@ -9759,9 +10029,9 @@ dependencies = [ "google-cloud-googleapis", "google-cloud-token", "prost-types 0.11.9", - "thiserror", + "thiserror 1.0.69", "tokio", - "tokio-util 0.7.10", + "tokio-util 0.7.18", "tracing", ] @@ -9782,13 +10052,13 @@ dependencies = [ "once_cell", "percent-encoding", "regex", - "reqwest 0.11.23", + "reqwest 0.11.27", "ring 0.16.20", "rsa 0.6.1", "serde", "serde_json", - "sha2 0.10.8", - "thiserror", + "sha2 0.10.9", + "thiserror 1.0.69", "time", "tokio", "tracing", @@ -9811,7 +10081,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ "ff 0.12.1", - "rand 0.8.5", + "rand 0.8.6", "rand_core 0.6.4", "rand_xorshift 0.3.0", "subtle", @@ -9823,8 +10093,8 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "ff 0.13.0", - "rand 0.8.5", + "ff 0.13.1", + "rand 0.8.6", "rand_core 0.6.4", "rand_xorshift 0.3.0", "subtle", @@ -9832,26 +10102,26 @@ dependencies = [ [[package]] name = "guppy" -version = "0.17.5" +version = "0.17.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34e99a7734579b834a076ef11789783c153c6eb5fb3520ed15bc41f483f0f317" +checksum = "eb611f63088c20f3f7252d896f0beaa176a9628da8c21cdf258fe9ae179bebda" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "camino", - "cargo_metadata 0.18.1", + "cargo_metadata 0.23.1", "cfg-if", "debug-ignore", - "fixedbitset 0.4.2", + "fixedbitset 0.5.7", "guppy-summaries", "guppy-workspace-hack", - "indexmap 2.7.0", - "itertools 0.12.1", + "indexmap 2.14.0", + "itertools 0.14.0", "nested", "once_cell", - "pathdiff", - "petgraph 0.6.5", + "pathdiff 0.2.3", + "petgraph 0.8.3", "rayon", - "semver", + "semver 1.0.28", "serde", "serde_json", "smallvec", @@ -9870,7 +10140,7 @@ dependencies = [ "cfg-if", "diffus", "guppy-workspace-hack", - "semver", + "semver 1.0.28", "serde", "toml 0.5.11", ] @@ -9883,56 +10153,58 @@ checksum = "92620684d99f750bae383ecb3be3748142d6095760afd5cbcf2261e9a279d780" [[package]] name = "h2" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http 0.2.11", - "indexmap 2.7.0", + "http 0.2.12", + "indexmap 2.14.0", "slab", "tokio", - "tokio-util 0.7.10", + "tokio-util 0.7.18", "tracing", ] [[package]] name = "h2" -version = "0.4.5" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http 1.1.0", - "indexmap 2.7.0", + "http 1.4.1", + "indexmap 2.14.0", "slab", "tokio", - "tokio-util 0.7.10", + "tokio-util 0.7.18", "tracing", ] [[package]] name = "half" -version = "1.8.2" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" [[package]] name = "half" -version = "2.2.1" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ + "cfg-if", "crunchy", "num-traits", + "zerocopy", ] [[package]] @@ -9946,7 +10218,7 @@ dependencies = [ "pest_derive", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -9964,30 +10236,45 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", ] [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "allocator-api2", ] [[package]] name = "hashbrown" -version = "0.15.3" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.2.0", ] +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + [[package]] name = "hashers" version = "1.0.1" @@ -10019,7 +10306,7 @@ dependencies = [ "base64 0.21.7", "bytes", "headers-core 0.2.0", - "http 0.2.11", + "http 0.2.12", "httpdate", "mime", "sha1", @@ -10027,14 +10314,14 @@ dependencies = [ [[package]] name = "headers" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" +checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "bytes", "headers-core 0.3.0", - "http 1.1.0", + "http 1.4.1", "httpdate", "mime", "sha1", @@ -10046,7 +10333,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" dependencies = [ - "http 0.2.11", + "http 0.2.12", ] [[package]] @@ -10055,7 +10342,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" dependencies = [ - "http 1.1.0", + "http 1.4.1", ] [[package]] @@ -10094,6 +10381,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + [[package]] name = "hex" version = "0.4.3" @@ -10137,15 +10430,6 @@ dependencies = [ "hmac 0.10.1", ] -[[package]] -name = "hkdf" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" -dependencies = [ - "hmac 0.12.1", -] - [[package]] name = "hmac" version = "0.8.1" @@ -10175,6 +10459,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "hmac" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" +dependencies = [ + "digest 0.11.3", +] + [[package]] name = "hmac-drbg" version = "0.3.0" @@ -10188,11 +10481,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.9" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -10214,9 +10507,9 @@ checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -10225,12 +10518,11 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0" dependencies = [ "bytes", - "fnv", "itoa", ] @@ -10241,30 +10533,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http 0.2.11", + "http 0.2.12", "pin-project-lite", ] [[package]] name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http 1.4.1", ] [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "futures-core", + "http 1.4.1", + "http-body 1.0.1", "pin-project-lite", ] @@ -10276,9 +10568,9 @@ checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" [[package]] name = "httparse" -version = "1.8.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" @@ -10300,7 +10592,7 @@ dependencies = [ "crossbeam-utils", "form_urlencoded", "futures-util", - "hyper 0.14.28", + "hyper 0.14.32", "isahc", "lazy_static", "levenshtein", @@ -10325,28 +10617,37 @@ dependencies = [ [[package]] name = "humantime" -version = "2.1.0" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" + +[[package]] +name = "hybrid-array" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" +dependencies = [ + "typenum", +] [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", - "h2 0.3.26", - "http 0.2.11", + "h2 0.3.27", + "http 0.2.12", "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.5", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -10355,16 +10656,17 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", - "h2 0.4.5", - "http 1.1.0", - "http-body 1.0.0", + "futures-core", + "h2 0.4.14", + "http 1.4.1", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -10380,8 +10682,8 @@ version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" dependencies = [ - "http 0.2.11", - "hyper 0.14.28", + "http 0.2.12", + "hyper 0.14.32", "log", "rustls 0.20.9", "rustls-native-certs 0.6.3", @@ -10396,10 +10698,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http 0.2.11", - "hyper 0.14.28", + "http 0.2.12", + "hyper 0.14.32", "log", - "rustls 0.21.10", + "rustls 0.21.12", "rustls-native-certs 0.6.3", "tokio", "tokio-rustls 0.24.1", @@ -10407,19 +10709,17 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ - "futures-util", - "http 1.1.0", - "hyper 1.4.1", + "http 1.4.1", + "hyper 1.10.1", "hyper-util", - "rustls 0.23.7", - "rustls-native-certs 0.7.0", - "rustls-pki-types", + "rustls 0.23.40", + "rustls-native-certs 0.8.4", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.4", "tower-service", ] @@ -10429,7 +10729,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper 0.14.28", + "hyper 0.14.32", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -10437,11 +10737,11 @@ dependencies = [ [[package]] name = "hyper-timeout" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.4.1", + "hyper 1.10.1", "hyper-util", "pin-project-lite", "tokio", @@ -10455,7 +10755,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper 0.14.28", + "hyper 0.14.32", "native-tls", "tokio", "tokio-native-tls", @@ -10463,20 +10763,23 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.6" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "hyper 1.4.1", + "http 1.4.1", + "http-body 1.0.1", + "hyper 1.10.1", + "ipnet", + "libc", + "percent-encoding", "pin-project-lite", - "socket2 0.5.5", + "socket2 0.6.4", "tokio", - "tower", "tower-service", "tracing", ] @@ -10489,21 +10792,22 @@ checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" dependencies = [ "futures-util", "hex", - "hyper 0.14.28", - "pin-project 1.1.3", + "hyper 0.14.32", + "pin-project 1.1.13", "tokio", ] [[package]] name = "iana-time-zone" -version = "0.1.59" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -10518,22 +10822,99 @@ dependencies = [ ] [[package]] -name = "ident_case" -version = "1.0.1" +name = "icu_collections" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] [[package]] -name = "idna" -version = "0.2.3" +name = "icu_locale_core" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.3.0" @@ -10554,17 +10935,38 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "ignore" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" +checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a" dependencies = [ "crossbeam-deque", "globset", "log", "memchr", - "regex-automata 0.4.6", + "regex-automata", "same-file", "walkdir", "winapi-util", @@ -10586,9 +10988,9 @@ dependencies = [ [[package]] name = "image" -version = "0.24.7" +version = "0.24.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" dependencies = [ "bytemuck", "byteorder", @@ -10596,7 +10998,6 @@ dependencies = [ "exr", "gif", "jpeg-decoder", - "num-rational 0.4.1", "num-traits", "png", "qoi", @@ -10618,7 +11019,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" dependencies = [ - "parity-scale-codec 3.6.12", + "parity-scale-codec 3.7.5", ] [[package]] @@ -10650,13 +11051,13 @@ dependencies = [ [[package]] name = "impl-trait-for-tuples" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] @@ -10685,9 +11086,9 @@ dependencies = [ [[package]] name = "indenter" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" [[package]] name = "indexmap" @@ -10702,13 +11103,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.15.3", + "hashbrown 0.17.1", "serde", + "serde_core", ] [[package]] @@ -10717,7 +11119,7 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7baab56125e25686df467fe470785512329883aab42696d661247aca2a2896e4" dependencies = [ - "console", + "console 0.16.3", "lazy_static", "number_prefix 0.3.0", "regex", @@ -10729,10 +11131,10 @@ version = "0.17.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" dependencies = [ - "console", + "console 0.15.11", "number_prefix 0.4.0", "portable-atomic", - "unicode-width 0.2.0", + "unicode-width 0.2.2", "web-time", ] @@ -10744,17 +11146,17 @@ checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" [[package]] name = "inferno" -version = "0.11.19" +version = "0.11.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" +checksum = "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88" dependencies = [ - "ahash 0.8.11", - "clap 4.5.21", + "ahash 0.8.12", + "clap 4.6.1", "crossbeam-channel", "crossbeam-utils", - "dashmap 5.5.3", - "env_logger", - "indexmap 2.7.0", + "dashmap 6.2.1", + "env_logger 0.11.10", + "indexmap 2.14.0", "is-terminal", "itoa", "log", @@ -10773,18 +11175,18 @@ checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" [[package]] name = "inout" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ "generic-array", ] [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", "js-sys", @@ -10821,7 +11223,7 @@ dependencies = [ "dashmap 5.5.3", "hashbrown 0.12.3", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.5", ] [[package]] @@ -10837,9 +11239,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.9.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "iprange" @@ -10861,13 +11263,13 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.10" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ - "hermit-abi 0.3.9", - "rustix 0.38.28", - "windows-sys 0.52.0", + "hermit-abi 0.5.2", + "libc", + "windows-sys 0.61.2", ] [[package]] @@ -10882,35 +11284,34 @@ dependencies = [ [[package]] name = "is_debug" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06d198e9919d9822d5f7083ba8530e04de87841eaf21ead9af8f2304efd57c89" +checksum = "1fe266d2e243c931d8190177f20bf7f24eed45e96f39e87dc49a27b32d12d407" [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "isahc" -version = "1.7.2" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "334e04b4d781f436dc315cb1e7515bd96826426345d498149e4bde36b67f8ee9" +checksum = "82d93e1769c5c2b13a8e0d8ca9b6466c60bafade047326f25e3bcb97a947d875" dependencies = [ - "async-channel 1.9.0", + "async-channel 2.5.0", "castaway", "crossbeam-utils", "curl", "curl-sys", "encoding_rs", - "event-listener 2.5.3", - "futures-lite 1.13.0", - "http 0.2.11", + "event-listener 5.4.1", + "futures-lite", + "http 0.2.12", "log", "mime", - "once_cell", - "polling 2.8.0", + "polling", "slab", "sluice", "tracing", @@ -10919,6 +11320,15 @@ dependencies = [ "waker-fn", ] +[[package]] +name = "itertools" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.10.5" @@ -10956,12 +11366,21 @@ dependencies = [ ] [[package]] -name = "itoa" -version = "1.0.10" +name = "itertools" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" - -[[package]] +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] name = "jemalloc-sys" version = "0.5.4+5.3.0-patched" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -10983,27 +11402,28 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ + "getrandom 0.3.4", "libc", ] [[package]] name = "jpeg-decoder" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" +checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07" dependencies = [ "rayon", ] [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", @@ -11056,22 +11476,22 @@ dependencies = [ "ring 0.16.20", "serde", "serde_json", - "simple_asn1 0.6.2", + "simple_asn1 0.6.4", ] [[package]] name = "jsonwebtoken" -version = "9.3.0" +version = "9.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f" +checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "js-sys", - "pem 3.0.4", - "ring 0.17.7", + "pem 3.0.6", + "ring 0.17.14", "serde", "serde_json", - "simple_asn1 0.6.2", + "simple_asn1 0.6.4", ] [[package]] @@ -11081,12 +11501,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6204285f77fe7d9784db3fdc449ecce1a0114927a51d5a41c4c7a292011c015f" dependencies = [ "base64 0.13.1", - "crypto-common", + "crypto-common 0.1.7", "digest 0.10.7", "hmac 0.12.1", "serde", "serde_json", - "sha2 0.10.8", + "sha2 0.10.9", +] + +[[package]] +name = "k256" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +dependencies = [ + "cfg-if", + "ecdsa 0.14.8", + "elliptic-curve 0.12.3", + "sha2 0.10.9", ] [[package]] @@ -11096,10 +11528,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", - "ecdsa", - "elliptic-curve", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", "once_cell", - "sha2 0.10.8", + "sha2 0.10.9", "signature 2.2.0", ] @@ -11129,11 +11561,11 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -11146,6 +11578,31 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "konst" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb" +dependencies = [ + "konst_macro_rules", +] + +[[package]] +name = "konst_macro_rules" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" + [[package]] name = "kube" version = "0.65.0" @@ -11170,26 +11627,26 @@ dependencies = [ "dirs-next", "either", "futures", - "http 0.2.11", + "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.32", "hyper-rustls 0.23.2", "hyper-timeout 0.4.1", "jsonpath_lib", "k8s-openapi", "kube-core", "pem 1.1.1", - "pin-project 1.1.3", + "pin-project 1.1.13", "rustls 0.20.9", "rustls-pemfile 0.2.1", "serde", "serde_json", "serde_yaml 0.8.26", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-util 0.6.10", - "tower", - "tower-http", + "tower 0.4.13", + "tower-http 0.2.5", "tracing", ] @@ -11201,13 +11658,13 @@ checksum = "c52b6ab05d160691083430f6f431707a4e05b64903f2ffa0095ee5efde759117" dependencies = [ "chrono", "form_urlencoded", - "http 0.2.11", + "http 0.2.12", "json-patch", "k8s-openapi", "once_cell", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -11232,28 +11689,6 @@ dependencies = [ "log", ] -[[package]] -name = "lalrpop" -version = "0.19.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1cbf952127589f2851ab2046af368fd20645491bb4b376f04b7f94d7a9837b" -dependencies = [ - "ascii-canvas", - "bit-set 0.5.3", - "diff", - "ena", - "is-terminal", - "itertools 0.10.5", - "lalrpop-util 0.19.12", - "petgraph 0.6.5", - "regex", - "regex-syntax 0.6.29", - "string_cache", - "term", - "tiny-keccak", - "unicode-xid", -] - [[package]] name = "lalrpop" version = "0.20.2" @@ -11264,33 +11699,25 @@ dependencies = [ "bit-set 0.5.3", "ena", "itertools 0.11.0", - "lalrpop-util 0.20.2", + "lalrpop-util", "petgraph 0.6.5", + "pico-args", "regex", - "regex-syntax 0.8.2", + "regex-syntax", "string_cache", - "term", + "term 0.7.0", "tiny-keccak", "unicode-xid", "walkdir", ] -[[package]] -name = "lalrpop-util" -version = "0.19.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3c48237b9604c5a4702de6b824e02006c3214327564636aef27c1028a8fa0ed" -dependencies = [ - "regex", -] - [[package]] name = "lalrpop-util" version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" dependencies = [ - "regex-automata 0.4.6", + "regex-automata", ] [[package]] @@ -11321,11 +11748,11 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.5.2", + "spin 0.9.8", ] [[package]] @@ -11334,11 +11761,17 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "lebe" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" [[package]] name = "ledger-apdu" @@ -11374,7 +11807,7 @@ dependencies = [ "ledger-transport", "libc", "log", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -11383,7 +11816,7 @@ version = "0.0.1" dependencies = [ "anyhow", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "codespan-reporting", "hex", "move-binary-format", @@ -11407,15 +11840,15 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.177" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libfuzzer-sys" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" +checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d" dependencies = [ "arbitrary", "cc", @@ -11437,25 +11870,25 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.1" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-link", ] [[package]] name = "libm" -version = "0.2.8" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libnghttp2-sys" -version = "0.1.9+1.58.0" +version = "0.1.13+1.68.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b57e858af2798e167e709b9d969325b6d8e9d50232fcbc494d7d54f976854a64" +checksum = "492e00167f1418c15648144f42bbfc63099806ecee9bf8d09a6353d6b4856b3c" dependencies = [ "cc", "libc", @@ -11463,13 +11896,14 @@ dependencies = [ [[package]] name = "libredox" -version = "0.0.1" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.12.1", "libc", - "redox_syscall 0.4.1", + "plain", + "redox_syscall 0.8.1", ] [[package]] @@ -11489,18 +11923,18 @@ dependencies = [ [[package]] name = "libsecp256k1" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +checksum = "e79019718125edc905a079a70cfa5f3820bc76139fc91d6f9abc27ea2a887139" dependencies = [ "arrayref", - "base64 0.13.1", + "base64 0.22.1", "digest 0.9.0", "hmac-drbg", "libsecp256k1-core", "libsecp256k1-gen-ecmult", "libsecp256k1-gen-genmult", - "rand 0.8.5", + "rand 0.8.6", "serde", "sha2 0.9.9", "typenum", @@ -11562,9 +11996,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.22" +version = "1.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" +checksum = "85bc9657773828b90eeb625adff10eeac83cc21bbfd8e23a03eaa8a33c9e28d9" dependencies = [ "cc", "libc", @@ -11572,6 +12006,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "link-section" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "014e440054ce8170890229eeef5bcda955305e056ec713de40ed366944483f09" + [[package]] name = "linked-hash-map" version = "0.5.6" @@ -11580,24 +12020,30 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linkme" -version = "0.3.32" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22d227772b5999ddc0690e733f734f95ca05387e329c4084fe65678c51198ffe" +checksum = "e83272d46373fb8decca684579ac3e7c8f3d71d4cc3aa693df8759e260ae41cf" dependencies = [ "linkme-impl", ] [[package]] name = "linkme-impl" -version = "0.3.32" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71a98813fa0073a317ed6a8055dcd4722a49d9b862af828ee68449adb799b6be" +checksum = "32d59e20403c7d08fe62b4376edfe5c7fb2ef1e6b1465379686d0f21c8df444b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] +[[package]] +name = "linktime-proc-macro" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7b0a3383c2a1002d11349c92c85a666a5fb679e96c79d782cf0dbe557fd6ee" + [[package]] name = "linux-raw-sys" version = "0.1.4" @@ -11606,34 +12052,38 @@ checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "lodepng" -version = "3.9.2" +version = "3.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00f56ff9bcd5721ab172b73eac8a7d4e9439f47a98581e666178dbe7df97e13" +checksum = "fe7982db11054edc023a1b424dddcc65be18f71fa46ec6bde2efcfc1fb6b22da" dependencies = [ "crc32fast", - "fallible_collections", "flate2", "libc", "rgb", @@ -11641,23 +12091,29 @@ dependencies = [ [[package]] name = "log" -version = "0.4.27" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "113b30b4cd05f7c06868fdb2854f66a7b9fece9a48425351cd532e810d74024f" dependencies = [ - "serde", + "serde_core", "value-bag", ] [[package]] name = "lru" -version = "0.16.0" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ea4e65087ff52f3862caff188d489f1fab49a0cb09e01b2e3f1a617b10aaed" +checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" dependencies = [ - "hashbrown 0.15.3", + "hashbrown 0.16.1", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "lz4" version = "1.28.1" @@ -11679,18 +12135,18 @@ dependencies = [ [[package]] name = "lz4_flex" -version = "0.11.3" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5" +checksum = "373f5eceeeab7925e0c1098212f2fbc4d416adec9d35051a6ab251e824c1854a" dependencies = [ - "twox-hash", + "twox-hash 2.1.2", ] [[package]] name = "mach2" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" dependencies = [ "libc", ] @@ -11709,19 +12165,13 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata 0.1.10", + "regex-automata", ] -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - [[package]] name = "matchit" version = "0.7.3" @@ -11730,9 +12180,9 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "matrixmultiply" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" dependencies = [ "autocfg", "rawpointer", @@ -11740,19 +12190,19 @@ dependencies = [ [[package]] name = "md-5" -version = "0.10.6" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" dependencies = [ "cfg-if", - "digest 0.10.7", + "digest 0.11.3", ] [[package]] name = "memchr" -version = "2.7.4" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" [[package]] name = "memmap2" @@ -11765,12 +12215,12 @@ dependencies = [ [[package]] name = "memory-stats" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34f79cf9964c5c9545493acda1263f1912f8d2c56c8a2ffee2606cb960acaacc" +checksum = "c73f5c649995a115e1a0220b35e4df0a1294500477f97a91d0660fb5abeb574a" dependencies = [ "libc", - "winapi 0.3.9", + "windows-sys 0.52.0", ] [[package]] @@ -11790,7 +12240,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde3af1a009ed76a778cb84fdef9e7dbbdf5775ae3e4cc1f434a6a307f6f76c5" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "metrics-macros", "portable-atomic", ] @@ -11806,7 +12256,7 @@ dependencies = [ "metrics", "metrics-util", "quanta", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -11817,7 +12267,7 @@ checksum = "38b4faf00617defe497754acde3024865bc143d44a86799b24e191ecff91354f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -11837,12 +12287,12 @@ dependencies = [ [[package]] name = "migrations_internals" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd01039851e82f8799046eabbb354056283fb265c8ec0996af940f4e85a380ff" +checksum = "3bda1634d70d5bd53553cf15dca9842a396e8c799982a3ad22998dc44d961f24" dependencies = [ "serde", - "toml 0.8.12", + "toml 0.9.12+spec-1.1.0", ] [[package]] @@ -11864,9 +12314,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -11895,11 +12345,11 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "adler", + "adler2", "simd-adler32", ] @@ -11911,22 +12361,27 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.48.0", ] [[package]] name = "mio" -version = "1.0.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" dependencies = [ - "hermit-abi 0.3.9", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.61.2", ] +[[package]] +name = "miracl_core_bls12381" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07cbe42e2a8dd41df582fb8e00fc24d920b5561cc301fcb6d14e2e0434b500f" + [[package]] name = "mirai-annotations" version = "1.12.0" @@ -11959,7 +12414,7 @@ dependencies = [ "fragile", "lazy_static", "mockall_derive 0.12.1", - "predicates 3.1.3", + "predicates 3.1.4", "predicates-tree", ] @@ -11984,7 +12439,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -11993,7 +12448,7 @@ version = "0.1.0" dependencies = [ "anyhow", "aptos-transaction-generator-lib", - "clap 4.5.21", + "clap 4.6.1", ] [[package]] @@ -12029,7 +12484,7 @@ name = "move-asm" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.5.21", + "clap 4.6.1", "codespan", "codespan-reporting", "either", @@ -12062,7 +12517,7 @@ dependencies = [ "arbitrary", "backtrace", "dearbitrary", - "indexmap 2.7.0", + "indexmap 2.14.0", "move-bytecode-spec", "move-core-types", "once_cell", @@ -12141,7 +12596,7 @@ name = "move-bytecode-viewer" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.5.21", + "clap 4.6.1", "crossterm 0.26.1", "move-binary-format", "move-bytecode-source-map", @@ -12155,7 +12610,7 @@ name = "move-cli" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.5.21", + "clap 4.6.1", "codespan-reporting", "colored", "datatest-stable", @@ -12204,7 +12659,7 @@ dependencies = [ "abstract-domain-derive", "anyhow", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "codespan", "codespan-reporting", "ethnum", @@ -12227,7 +12682,7 @@ dependencies = [ "move-stackless-bytecode", "move-stdlib", "move-symbol-pool", - "num 0.4.1", + "num 0.4.3", "once_cell", "petgraph 0.6.5", "serde_json", @@ -12257,20 +12712,20 @@ dependencies = [ "bytes", "dearbitrary", "ethnum", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", - "num 0.4.1", + "num 0.4.3", "once_cell", "primitive-types 0.10.1", "proptest", "proptest-derive", - "rand 0.8.5", + "rand 0.8.6", "ref-cast", "regex", "serde", "serde_bytes", "serde_json", - "thiserror", + "thiserror 1.0.69", "uint", ] @@ -12280,7 +12735,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "codespan", "colored", "move-binary-format", @@ -12298,7 +12753,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "codespan", "codespan-reporting", "datatest-stable", @@ -12317,7 +12772,7 @@ name = "move-disassembler" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.5.21", + "clap 4.6.1", "colored", "legacy-move-compiler", "move-binary-format", @@ -12333,7 +12788,7 @@ name = "move-docgen" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.5.21", + "clap 4.6.1", "codespan", "codespan-reporting", "datatest-stable", @@ -12378,7 +12833,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "move-binary-format", "move-bytecode-source-map", "move-bytecode-verifier", @@ -12448,7 +12903,7 @@ dependencies = [ "move-model", "move-prover-test-utils", "move-stackless-bytecode", - "num 0.4.1", + "num 0.4.3", ] [[package]] @@ -12472,7 +12927,7 @@ dependencies = [ "move-ir-types", "move-prover-test-utils", "move-symbol-pool", - "num 0.4.1", + "num 0.4.3", "num-traits", "once_cell", "regex", @@ -12484,7 +12939,7 @@ name = "move-package" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.5.21", + "clap 4.6.1", "colored", "datatest-stable", "itertools 0.13.0", @@ -12511,7 +12966,7 @@ dependencies = [ "termcolor", "toml 0.7.8", "walkdir", - "whoami", + "whoami 1.6.1", ] [[package]] @@ -12535,7 +12990,7 @@ version = "0.1.0" dependencies = [ "anyhow", "atty", - "clap 4.5.21", + "clap 4.6.1", "codespan-reporting", "itertools 0.13.0", "legacy-move-compiler", @@ -12553,7 +13008,7 @@ dependencies = [ "move-stackless-bytecode", "once_cell", "serde", - "shell-words", + "shell-words 1.1.1", "simplelog", "tempfile", "toml 0.7.8", @@ -12578,7 +13033,7 @@ dependencies = [ "move-model", "move-prover-bytecode-pipeline", "move-stackless-bytecode", - "num 0.4.1", + "num 0.4.3", "once_cell", "pretty", "rand 0.7.3", @@ -12603,7 +13058,7 @@ dependencies = [ "move-stackless-bytecode", "move-stackless-bytecode-test-utils", "serde", - "shell-words", + "shell-words 1.1.1", "tempfile", "walkdir", ] @@ -12614,7 +13069,7 @@ version = "0.1.0" dependencies = [ "anyhow", "chrono", - "clap 4.5.21", + "clap 4.6.1", "codespan-reporting", "itertools 0.13.0", "move-model", @@ -12663,7 +13118,7 @@ dependencies = [ "move-core-types", "move-model", "move-stackless-bytecode-test-utils", - "num 0.4.1", + "num 0.4.3", "paste", "petgraph 0.6.5", "topological-sort", @@ -12749,7 +13204,7 @@ dependencies = [ "aptos-framework", "arbitrary", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "datatest-stable", "dearbitrary", "difference", @@ -12784,7 +13239,7 @@ version = "0.1.0" dependencies = [ "anyhow", "better_any", - "clap 4.5.21", + "clap 4.6.1", "codespan-reporting", "colored", "datatest-stable", @@ -12856,7 +13311,7 @@ dependencies = [ "cfg-if", "claims", "fail", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", "lazy_static", "legacy-move-compiler", @@ -12869,7 +13324,7 @@ dependencies = [ "move-vm-test-utils", "move-vm-types", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "proptest", "serde", "smallbitvec", @@ -12921,12 +13376,12 @@ dependencies = [ "crossbeam", "dashmap 7.0.0-rc2", "derivative", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "itertools 0.13.0", "mockall 0.11.4", "move-binary-format", "move-core-types", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "proptest", "rand 0.7.3", "serde", @@ -12945,7 +13400,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 0.2.11", + "http 0.2.12", "httparse", "log", "memchr", @@ -12963,7 +13418,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 1.1.0", + "http 1.4.1", "httparse", "memchr", "mime", @@ -12974,29 +13429,46 @@ dependencies = [ [[package]] name = "nalgebra" -version = "0.32.3" +version = "0.32.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307ed9b18cc2423f29e83f84fd23a8e73628727990181f18641a8b5dc2ab1caa" +checksum = "7b5c17de023a86f59ed79891b2e5d5a94c705dbe904a5b5c9c952ea6221b03e4" dependencies = [ "approx", "matrixmultiply", "nalgebra-macros", - "num-complex 0.4.4", - "num-rational 0.4.1", + "num-complex 0.4.6", + "num-rational 0.4.2", + "num-traits", + "simba 0.8.1", + "typenum", +] + +[[package]] +name = "nalgebra" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d43ddcacf343185dfd6de2ee786d9e8b1c2301622afab66b6c73baf9882abfd" +dependencies = [ + "approx", + "matrixmultiply", + "num-complex 0.4.6", + "num-rational 0.4.2", "num-traits", - "simba", + "rand 0.8.6", + "rand_distr", + "simba 0.9.1", "typenum", ] [[package]] name = "nalgebra-macros" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91761aed67d03ad966ef783ae962ef9bbaca728d2dd7ceb7939ec110fffad998" +checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] @@ -13007,26 +13479,25 @@ checksum = "40a3eb6b7c682b65d1f631ec3176829d72ab450b3aacdd3f719bf220822e59ac" dependencies = [ "libc", "once_cell", - "parking_lot 0.12.1", - "thiserror", + "parking_lot 0.12.5", + "thiserror 1.0.69", "widestring", "winapi 0.3.9", ] [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" dependencies = [ - "lazy_static", "libc", "log", "openssl", - "openssl-probe", + "openssl-probe 0.2.1", "openssl-sys", "schannel", - "security-framework", + "security-framework 3.7.0", "security-framework-sys", "tempfile", ] @@ -13042,7 +13513,7 @@ dependencies = [ "blake2s_simd", "blstrs 0.7.1", "byteorder", - "ff 0.13.0", + "ff 0.13.1", "generic-array", "log", "pasta_curves", @@ -13058,17 +13529,17 @@ checksum = "ca2b420f638f07fe83056b55ea190bb815f609ec5a35e7017884a10f78839c9e" [[package]] name = "new_debug_unreachable" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "newtype-uuid" -version = "1.1.3" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8781e2ef64806278a55ad223f0bc875772fd40e1fe6e73e8adbf027817229d" +checksum = "5c012d14ef788ab066a347d19e3dda699916c92293b05b85ba2c76b8c82d2830" dependencies = [ - "uuid 1.11.0", + "uuid 1.23.2", ] [[package]] @@ -13084,22 +13555,23 @@ dependencies = [ [[package]] name = "nix" -version = "0.27.1" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.12.1", "cfg-if", + "cfg_aliases 0.2.1", "libc", ] [[package]] name = "nix" -version = "0.29.0" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.12.1", "cfg-if", "cfg_aliases 0.2.1", "libc", @@ -13135,18 +13607,18 @@ checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] name = "ntapi" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" dependencies = [ "winapi 0.3.9", ] [[package]] name = "ntest" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb183f0a1da7a937f672e5ee7b7edb727bf52b8a52d531374ba8ebb9345c0330" +checksum = "54d1aa56874c2152c24681ed0df95ee155cc06c5c61b78e2d1e8c0cae8bc5326" dependencies = [ "ntest_test_cases", "ntest_timeout", @@ -13154,9 +13626,9 @@ dependencies = [ [[package]] name = "ntest_test_cases" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d0d3f2a488592e5368ebbe996e7f1d44aa13156efad201f5b4d84e150eaa93" +checksum = "6913433c6319ef9b2df316bb8e3db864a41724c2bb8f12555e07dc4ec69d3db1" dependencies = [ "proc-macro2", "quote", @@ -13165,11 +13637,11 @@ dependencies = [ [[package]] name = "ntest_timeout" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc7c92f190c97f79b4a332f5e81dcf68c8420af2045c936c9be0bc9de6f63b5" +checksum = "9224be3459a0c1d6e9b0f42ab0e76e98b29aef5aba33c0487dfcf47ea08b5150" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", "syn 1.0.109", @@ -13177,21 +13649,20 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" dependencies = [ - "overload", - "winapi 0.3.9", + "windows-sys 0.48.0", ] [[package]] name = "nu-ansi-term" -version = "0.49.0" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -13210,15 +13681,15 @@ dependencies = [ [[package]] name = "num" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ - "num-bigint 0.4.4", - "num-complex 0.4.4", + "num-bigint 0.4.6", + "num-complex 0.4.6", "num-integer", "num-iter", - "num-rational 0.4.1", + "num-rational 0.4.2", "num-traits", ] @@ -13247,28 +13718,26 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-bigint-dig" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" dependencies = [ - "byteorder", "lazy_static", "libm", "num-integer", "num-iter", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "smallvec", "zeroize", ] @@ -13284,18 +13753,18 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-derive" @@ -13305,7 +13774,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -13314,25 +13783,24 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "itoa", ] [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -13353,12 +13821,11 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", - "num-bigint 0.4.4", + "num-bigint 0.4.6", "num-integer", "num-traits", ] @@ -13375,40 +13842,41 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi 0.5.2", "libc", ] [[package]] name = "num_enum" -version = "0.7.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" dependencies = [ "num_enum_derive", + "rustversion", ] [[package]] name = "num_enum_derive" -version = "0.7.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "num_threads" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ "libc", ] @@ -13425,42 +13893,63 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + [[package]] name = "object" -version = "0.32.2" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "open" -version = "5.3.2" +version = "5.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2483562e62ea94312f3576a7aca397306df7990b8d89033e18766744377ef95" +checksum = "2fbaa89d2ddc8473c78a3adf69eea8cffa28c483b8e02a971ef31527cd0fc92c" dependencies = [ "is-wsl", "libc", - "pathdiff", + "pathdiff 0.2.3", ] [[package]] @@ -13469,7 +13958,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "auto_impl", "bytes", "ethereum-types", @@ -13490,15 +13979,14 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.12.1", "cfg-if", "foreign-types 0.3.2", "libc", - "once_cell", "openssl-macros", "openssl-sys", ] @@ -13511,20 +13999,26 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-probe" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4" dependencies = [ "cc", "libc", @@ -13540,11 +14034,11 @@ checksum = "1e32339a5dc40459130b3bd269e9892439f55b33e772d2a9d402a789baaf4e8a" dependencies = [ "futures-core", "futures-sink", - "indexmap 2.7.0", + "indexmap 2.14.0", "js-sys", "once_cell", "pin-project-lite", - "thiserror", + "thiserror 1.0.69", "urlencoding", ] @@ -13575,7 +14069,7 @@ dependencies = [ "once_cell", "opentelemetry", "ordered-float 4.6.0", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -13640,12 +14134,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "owo-colors" version = "3.5.0" @@ -13658,10 +14146,10 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" dependencies = [ - "ecdsa", - "elliptic-curve", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", "primeorder", - "sha2 0.10.8", + "sha2 0.10.9", ] [[package]] @@ -13672,7 +14160,7 @@ dependencies = [ "aptos-framework", "aptos-transaction-workloads-lib", "bcs 0.1.4", - "clap 4.5.21", + "clap 4.6.1", "move-package", ] @@ -13682,7 +14170,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" dependencies = [ - "unicode-width 0.1.11", + "unicode-width 0.1.14", ] [[package]] @@ -13709,7 +14197,7 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "bitvec 0.20.4", "byte-slice-cast", "impl-trait-for-tuples", @@ -13719,15 +14207,17 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.12" +version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "bitvec 1.0.1", "byte-slice-cast", + "const_format", "impl-trait-for-tuples", - "parity-scale-codec-derive 3.6.12", + "parity-scale-codec-derive 3.7.5", + "rustversion", "serde", ] @@ -13745,21 +14235,21 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.12" +version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" @@ -13774,12 +14264,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", - "parking_lot_core 0.9.10", + "parking_lot_core 0.9.12", ] [[package]] @@ -13798,56 +14288,56 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.11", + "redox_syscall 0.5.18", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] name = "parquet" -version = "52.1.0" +version = "52.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f22ba0d95db56dde8685e3fadcb915cdaadda31ab8abbe3ff7f0ad1ef333267" +checksum = "e977b9066b4d3b03555c22bdc442f3fadebd96a39111249113087d0edb2691cd" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "bytes", "chrono", "futures", - "half 2.2.1", - "hashbrown 0.14.3", + "half 2.7.1", + "hashbrown 0.14.5", "lz4_flex", - "num 0.4.1", - "num-bigint 0.4.4", + "num 0.4.3", + "num-bigint 0.4.6", "paste", "seq-macro", "thrift", "tokio", - "twox-hash", + "twox-hash 1.6.3", ] [[package]] name = "parquet_derive" -version = "52.1.0" +version = "52.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbfe02f8b63a15a78398db242f9b1d2dcc201319075ea6222c7108ffd48b23c0" +checksum = "6e57262f900bc3e93755be67e0fc4e2fcdae416b563472528e413c6e0a52ee81" dependencies = [ "parquet", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "parse-zoneinfo" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" +checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" dependencies = [ "regex", ] @@ -13864,7 +14354,7 @@ dependencies = [ "mockall 0.11.4", "p256", "passkey-types", - "rand 0.8.5", + "rand 0.8.6", ] [[package]] @@ -13891,30 +14381,19 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "499cff8432e71c5f8784d9645aac0f9fca604d67f59b68a606170b5e229c6538" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.12.1", "ciborium", "coset", "data-encoding", - "indexmap 2.7.0", - "rand 0.8.5", + "indexmap 2.14.0", + "rand 0.8.6", "serde", "serde_json", - "sha2 0.10.8", + "sha2 0.10.9", "strum 0.25.0", "typeshare", ] -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "pasta_curves" version = "0.5.1" @@ -13922,11 +14401,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095" dependencies = [ "blake2b_simd", - "ff 0.13.0", + "ff 0.13.1", "group 0.13.0", "hex", "lazy_static", - "rand 0.8.5", + "rand 0.8.6", "serde", "static_assertions", "subtle", @@ -13934,21 +14413,21 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] -name = "path-slash" -version = "0.2.1" +name = "pathdiff" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" +checksum = "a3bf70094d203e07844da868b634207e71bfab254fe713171fae9a6e751ccf31" [[package]] name = "pathdiff" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" dependencies = [ "camino", ] @@ -13989,9 +14468,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ "digest 0.10.7", - "hmac 0.12.1", - "password-hash", - "sha2 0.10.8", ] [[package]] @@ -14012,7 +14488,7 @@ checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467" dependencies = [ "inlinable_string", "pear_codegen", - "yansi 1.0.0-rc.1", + "yansi", ] [[package]] @@ -14024,7 +14500,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -14049,12 +14525,12 @@ dependencies = [ [[package]] name = "pem" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ "base64 0.22.1", - "serde", + "serde_core", ] [[package]] @@ -14077,26 +14553,25 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.7.6" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f200d8d83c44a45b21764d1916299752ca035d15ecd46faca3e9a2a2bf6ad06" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" dependencies = [ "memchr", - "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.6" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcd6ab1236bbdb3a49027e920e693192ebfe8913f6d60e294de57463a493cfde" +checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" dependencies = [ "pest", "pest_generator", @@ -14104,26 +14579,25 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.6" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a31940305ffc96863a735bef7c7994a00b325a7138fdbc5bda0f1a0476d3275" +checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "pest_meta" -version = "2.7.6" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ff62f5259e53b78d1af898941cdcdccfae7385cf7d793a6e55de5d05bb4b7d" +checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" dependencies = [ - "once_cell", "pest", - "sha2 0.10.8", + "sha2 0.10.9", ] [[package]] @@ -14143,7 +14617,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset 0.4.2", - "indexmap 2.7.0", + "indexmap 2.14.0", +] + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset 0.5.7", + "hashbrown 0.15.5", + "indexmap 2.14.0", ] [[package]] @@ -14158,12 +14643,20 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_shared 0.11.3", +] + +[[package]] +name = "phf" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7" dependencies = [ - "phf_macros", - "phf_shared 0.11.2", + "phf_shared 0.12.1", ] [[package]] @@ -14178,53 +14671,40 @@ dependencies = [ [[package]] name = "phf_codegen" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ "phf_generator", - "phf_shared 0.11.2", + "phf_shared 0.11.3", ] [[package]] name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared 0.11.2", - "rand 0.8.5", -] - -[[package]] -name = "phf_macros" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "phf_generator", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.87", + "phf_shared 0.11.3", + "rand 0.8.6", ] [[package]] name = "phf_shared" -version = "0.10.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "siphasher 0.3.11", + "siphasher 1.0.3", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981" dependencies = [ - "siphasher 0.3.11", + "siphasher 1.0.3", ] [[package]] @@ -14233,9 +14713,15 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" dependencies = [ - "siphasher 1.0.1", + "siphasher 1.0.3", ] +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project" version = "0.4.30" @@ -14247,11 +14733,11 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" dependencies = [ - "pin-project-internal 1.1.3", + "pin-project-internal 1.1.13", ] [[package]] @@ -14267,20 +14753,20 @@ dependencies = [ [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pin-utils" @@ -14290,12 +14776,12 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.1" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" dependencies = [ "atomic-waker", - "fastrand 2.0.1", + "fastrand", "futures-io", ] @@ -14316,7 +14802,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ - "der 0.7.8", + "der 0.7.10", "pkcs8 0.10.2", "spki 0.7.3", ] @@ -14332,27 +14818,43 @@ dependencies = [ "zeroize", ] +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der 0.6.1", + "spki 0.6.0", +] + [[package]] name = "pkcs8" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.8", + "der 0.7.10", "spki 0.7.3", ] [[package]] name = "pkg-config" -version = "0.3.28" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "plain" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ "num-traits", "plotters-backend", @@ -14363,24 +14865,24 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] [[package]] name = "png" -version = "0.17.10" +version = "0.17.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -14391,72 +14893,70 @@ dependencies = [ [[package]] name = "poem" -version = "3.1.3" +version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef0e102c6b811e0e01928eed4872b3ff63917f37dc2dab39a93db55f25d314d" +checksum = "9f977080932c87287147dca052951c3e2696f8759863f6b4e4c0c9ffe7a4cc8b" dependencies = [ "anyhow", "async-compression", "bytes", - "chrono", - "cookie 0.18.1", "futures-util", - "headers 0.4.0", - "http 1.1.0", + "headers 0.4.1", + "http 1.4.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.10.1", "hyper-util", "mime", "multer 3.1.0", - "nix 0.29.0", - "parking_lot 0.12.1", + "nix 0.30.1", + "parking_lot 0.12.5", "percent-encoding", "pin-project-lite", "poem-derive", "quick-xml 0.36.2", "regex", "rfc7239", - "rustls-pemfile 2.1.1", + "rustls-pemfile 2.2.0", "serde", "serde_json", "serde_urlencoded", - "serde_yaml 0.9.30", + "serde_yaml 0.9.34+deprecated", "smallvec", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tempfile", - "thiserror", - "time", + "thiserror 2.0.18", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.4", "tokio-stream", - "tokio-util 0.7.10", + "tokio-util 0.7.18", "tracing", "wildmatch", ] [[package]] name = "poem-derive" -version = "3.1.0" +version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdfed15c1102d2a9a51b9f1aba945628c72ccb52fc5d3e4ad4ffbbd222e11821" +checksum = "056e2fea6de1cb240ffe23cfc4fc370b629f8be83b5f27e16b7acd5231a72de4" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "poem-openapi" -version = "5.1.2" +version = "5.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c354a706a81a17657da8441869c6ce3d486ef5e72705919d6035fb038a6f7b5" +checksum = "1ccbcc395bf4dd03df1da32da351b6b6732e4074ce27ddec315650e52a2be44c" dependencies = [ "base64 0.22.1", "bytes", - "derive_more 1.0.0", + "derive_more 2.1.1", "futures-util", - "indexmap 2.7.0", + "indexmap 2.14.0", + "itertools 0.14.0", "mime", "num-traits", "poem", @@ -14466,68 +14966,52 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "serde_yaml 0.9.30", - "thiserror", + "serde_yaml 0.9.34+deprecated", + "thiserror 2.0.18", "tokio", "url", ] [[package]] name = "poem-openapi-derive" -version = "5.1.1" +version = "5.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88e4cd0c926ab1d9a015ecc1077c950d5897577554691ff70efcd9c90ddeb614" +checksum = "41273b691a3d467a8c44d05506afba9f7b6bd56c9cdf80123de13fe52d7ec587" dependencies = [ - "darling 0.20.10", - "http 1.1.0", - "indexmap 2.7.0", + "darling 0.20.11", + "http 1.4.1", + "indexmap 2.14.0", "mime", - "proc-macro-crate 3.1.0", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", "regex", - "syn 2.0.87", - "thiserror", -] - -[[package]] -name = "polling" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys 0.48.0", + "syn 2.0.117", + "thiserror 2.0.18", ] [[package]] name = "polling" -version = "3.3.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf63fa624ab313c11656b4cda960bfc46c410187ad493c41f6ba2d8c1e991c9e" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", + "hermit-abi 0.5.2", "pin-project-lite", - "rustix 0.38.28", - "tracing", - "windows-sys 0.52.0", + "rustix 1.1.4", + "windows-sys 0.61.2", ] [[package]] name = "polyval" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "opaque-debug", "universal-hash", ] @@ -14554,9 +15038,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "poseidon-ark" @@ -14570,9 +15054,9 @@ dependencies = [ [[package]] name = "postgres-native-tls" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac73153d92e4bde922bd6f1dfba7f1ab8132266c031153b55e20a1521cd36d49" +checksum = "fef4de47bb81477e0c3deaf153a1b10ae176484713ff1640969f4cb96b653ebc" dependencies = [ "native-tls", "tokio", @@ -14582,33 +15066,42 @@ dependencies = [ [[package]] name = "postgres-protocol" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbef655056b916eb868048276cfd5d6a7dea4f81560dfd047f97c8c6fe3fcfd4" +checksum = "56201207dac53e2f38e848e31b4b91616a6bb6e0c7205b77718994a7f49e70fc" dependencies = [ "base64 0.22.1", "byteorder", "bytes", "fallible-iterator", - "hmac 0.12.1", + "hmac 0.13.0", "md-5", "memchr", - "rand 0.9.1", - "sha2 0.10.8", + "rand 0.10.1", + "sha2 0.11.0", "stringprep", ] [[package]] name = "postgres-types" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4605b7c057056dd35baeb6ac0c0338e4975b1f2bef0f65da953285eb007095" +checksum = "8dc729a129e682e8d24170cd30ae1aa01b336b096cbb56df6d534ffec133d186" dependencies = [ "bytes", "fallible-iterator", "postgres-protocol", ] +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -14629,26 +15122,29 @@ dependencies = [ "log", "nix 0.26.4", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "protobuf", "protobuf-codegen-pure", "smallvec", "symbolic-demangle", "tempfile", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] name = "pq-sys" -version = "0.4.8" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0052426df997c0cbd30789eb44ca097e3541717a7b8fa36b1c464ee7edebd" +checksum = "f6cc05d7ea95200187117196eee9edd0644424911821aeb28a18ce60ea0b8793" dependencies = [ "vcpkg", ] @@ -14675,9 +15171,9 @@ dependencies = [ [[package]] name = "predicates" -version = "3.1.3" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" +checksum = "ada8f2932f28a27ee7b70dd6c1c39ea0675c55a36879ab92f3a715eaa1e63cfe" dependencies = [ "anstyle", "predicates-core", @@ -14685,15 +15181,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.6" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" +checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144" [[package]] name = "predicates-tree" -version = "1.0.9" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2" dependencies = [ "predicates-core", "termtree", @@ -14711,12 +15207,12 @@ dependencies = [ [[package]] name = "pretty_assertions" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ "diff", - "yansi 0.5.1", + "yansi", ] [[package]] @@ -14733,12 +15229,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.25" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -14748,11 +15244,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" dependencies = [ "csv", - "encode_unicode 1.0.0", + "encode_unicode", "is-terminal", "lazy_static", - "term", - "unicode-width 0.1.11", + "term 0.7.0", + "unicode-width 0.1.14", ] [[package]] @@ -14761,7 +15257,7 @@ version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" dependencies = [ - "elliptic-curve", + "elliptic-curve 0.13.8", ] [[package]] @@ -14802,11 +15298,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.1.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.21.1", + "toml_edit 0.25.12+spec-1.1.0", ] [[package]] @@ -14847,9 +15343,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -14862,9 +15358,9 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", "version_check", - "yansi 1.0.0-rc.1", + "yansi", ] [[package]] @@ -14872,7 +15368,7 @@ name = "processor" version = "0.1.0" source = "git+https://github.com/aptos-labs/aptos-indexer-processors-v2.git?tag=aptos-indexer-processors-v2.1.5#a1a0cfeff7febc81dbe5a238ed5318f319aaef6c" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "allocative", "allocative_derive", "anyhow", @@ -14880,10 +15376,10 @@ dependencies = [ "async-trait", "bcs 0.1.4", "bigdecimal", - "bitflags 2.9.1", + "bitflags 2.12.1", "canonical_json", "chrono", - "clap 4.5.21", + "clap 4.6.1", "const_format", "diesel", "diesel-async", @@ -14896,7 +15392,7 @@ dependencies = [ "google-cloud-pubsub", "google-cloud-storage", "hex", - "hyper 0.14.28", + "hyper 0.14.32", "itertools 0.12.1", "jemallocator", "lazy_static", @@ -14908,13 +15404,13 @@ dependencies = [ "parquet_derive", "postgres-native-tls", "prometheus", - "prost 0.13.4", + "prost 0.13.5", "rayon", "regex", "serde", "serde_json", - "sha2 0.10.8", - "sha3 0.10.8", + "sha2 0.10.9", + "sha3 0.10.9", "strum 0.24.1", "tiny-keccak", "tokio", @@ -14948,17 +15444,17 @@ checksum = "8bccbff07d5ed689c4087d20d7307a52ab6141edeedf487c3876a55b86cf63df" [[package]] name = "prometheus" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" +checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" dependencies = [ "cfg-if", "fnv", "lazy_static", "memchr", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "protobuf", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -14969,7 +15465,7 @@ checksum = "504ee9ff529add891127c4827eb481bd69dc0ebc72e9a682e187db4caa60c3ca" dependencies = [ "dtoa", "itoa", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "prometheus-client-derive-encode", ] @@ -14981,7 +15477,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -14990,7 +15486,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ae2f6a3f14ff35c16b51ac796d1dc73c15ad6472c48836c6c467f6d52266648" dependencies = [ - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "time", @@ -15011,19 +15507,18 @@ dependencies = [ [[package]] name = "proptest" -version = "1.7.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fcdab19deb5195a31cf7726a210015ff1496ba1464fd42cb4f537b8b01b471f" +checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" dependencies = [ "bit-set 0.8.0", "bit-vec 0.8.0", - "bitflags 2.9.1", - "lazy_static", + "bitflags 2.12.1", "num-traits", - "rand 0.9.1", + "rand 0.9.4", "rand_chacha 0.9.0", "rand_xorshift 0.4.0", - "regex-syntax 0.8.2", + "regex-syntax", "rusty-fork", "tempfile", "unarray", @@ -15037,7 +15532,7 @@ checksum = "4ee1c9ac207483d5e7db4940700de86a9aae46ef90c48b57f99fe7edb8345e49" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -15052,22 +15547,32 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", - "prost-derive 0.12.3", + "prost-derive 0.12.6", ] [[package]] name = "prost" -version = "0.13.4" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +dependencies = [ + "bytes", + "prost-derive 0.13.5", +] + +[[package]] +name = "prost" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c0fef6c4230e4ccf618a35c59d7ede15dea37de8427500f50aff708806e42ec" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" dependencies = [ "bytes", - "prost-derive 0.13.4", + "prost-derive 0.14.3", ] [[package]] @@ -15085,28 +15590,41 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "prost-derive" -version = "0.13.4" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "157c5a9d7ea5c2ed2d9fb8f495b64759f7816c7eaea54ba3978f0d63000162e3" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.13.0", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "prost-derive" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +dependencies = [ + "anyhow", + "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -15120,20 +15638,29 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ - "prost 0.12.3", + "prost 0.12.6", ] [[package]] name = "prost-types" -version = "0.13.1" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" +dependencies = [ + "prost 0.13.5", +] + +[[package]] +name = "prost-types" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee5168b05f49d4b0ca581206eb14a7b22fafd963efe729ac48eb03266e25cc2" +checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" dependencies = [ - "prost 0.13.4", + "prost 0.14.3", ] [[package]] @@ -15169,27 +15696,27 @@ checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" [[package]] name = "public-suffix" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca346b8ff0739660876c8d96a6f9de5cd9b4cd87500bb0ce92485318c674afe" +checksum = "51315bca45305dd8aa64b831b33e71abac528ca8058c0651346a39b8d3009498" [[package]] name = "publicsuffix" -version = "2.2.3" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a8c1bda5ae1af7f99a2962e49df150414a43d62404644d98dd5c3a93d07457" +checksum = "6f42ea446cab60335f76979ec15e12619a2165b5ae2c12166bef27d283a9fadf" dependencies = [ - "idna 0.3.0", + "idna 1.1.0", "psl-types", ] [[package]] name = "pulldown-cmark" -version = "0.9.3" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.12.1", "memchr", "unicase", ] @@ -15223,7 +15750,7 @@ dependencies = [ "mach2", "once_cell", "raw-cpuid", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "web-sys", "winapi 0.3.9", ] @@ -15236,17 +15763,17 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quick-junit" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ffd2f9a162cfae131bed6d9d1ed60adced33be340a94f96952897d7cb0c240" +checksum = "6ee9342d671fae8d66b3ae9fd7a9714dfd089c04d2a8b1ec0436ef77aee15e5f" dependencies = [ "chrono", - "indexmap 2.7.0", + "indexmap 2.14.0", "newtype-uuid", - "quick-xml 0.36.2", + "quick-xml 0.38.4", "strip-ansi-escapes", - "thiserror", - "uuid 1.11.0", + "thiserror 2.0.18", + "uuid 1.23.2", ] [[package]] @@ -15277,78 +15804,102 @@ dependencies = [ "serde", ] +[[package]] +name = "quick-xml" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" +dependencies = [ + "memchr", +] + [[package]] name = "quick_cache" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "347e1a588d1de074eeb3c00eadff93db4db65aeb62aee852b1efd0949fe65b6c" +checksum = "eb55a1aa7668676bb93926cd4e9cdfe60f03bb866553bcca9112554911b6d3dc" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "equivalent", - "hashbrown 0.14.3", - "parking_lot 0.12.1", + "hashbrown 0.14.5", + "parking_lot 0.12.5", ] [[package]] name = "quinn" -version = "0.11.2" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ "bytes", + "cfg_aliases 0.2.1", "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash", - "rustls 0.23.7", - "thiserror", + "rustc-hash 2.1.2", + "rustls 0.23.40", + "socket2 0.6.4", + "thiserror 2.0.18", "tokio", "tracing", + "web-time", ] [[package]] name = "quinn-proto" -version = "0.11.3" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ "bytes", - "rand 0.8.5", - "ring 0.17.7", - "rustc-hash", - "rustls 0.23.7", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.4", + "ring 0.17.14", + "rustc-hash 2.1.2", + "rustls 0.23.40", + "rustls-pki-types", "slab", - "thiserror", + "thiserror 2.0.18", "tinyvec", "tracing", + "web-time", ] [[package]] name = "quinn-udp" -version = "0.5.4" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" dependencies = [ + "cfg_aliases 0.2.1", "libc", "once_cell", - "socket2 0.5.5", - "windows-sys 0.52.0", + "socket2 0.6.4", + "tracing", + "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "r2d2" @@ -15357,7 +15908,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" dependencies = [ "log", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "scheduled-thread-pool", ] @@ -15389,9 +15940,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -15400,12 +15951,23 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.1" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +dependencies = [ + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.1", ] [[package]] @@ -15435,7 +15997,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -15453,16 +16015,32 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_distr" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ - "getrandom 0.3.3", + "num-traits", + "rand 0.8.6", ] [[package]] @@ -15498,7 +16076,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" dependencies = [ - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -15517,7 +16095,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d0f7171155590e912ab907550240a5764c665388ab0a1e46d783a493e816ff3" dependencies = [ "once_cell", - "rand 0.8.5", + "rand 0.8.6", ] [[package]] @@ -15537,9 +16115,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "1.9.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -15547,9 +16125,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -15557,9 +16135,9 @@ dependencies = [ [[package]] name = "redis" -version = "0.22.3" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa8455fa3621f6b41c514946de66ea0531f57ca017b2e6c7cc368035ea5b46df" +checksum = "f8d5a2ed627935139b60bf35b4af4747cb2c657b5ac0567954d7a4b8300e3d21" dependencies = [ "arc-swap", "async-trait", @@ -15573,7 +16151,7 @@ dependencies = [ "ryu", "sha1_smol", "tokio", - "tokio-util 0.7.10", + "tokio-util 0.7.18", "url", ] @@ -15598,114 +16176,99 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.12.1", ] [[package]] name = "redox_syscall" -version = "0.5.11" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +checksum = "5b44b894f2a6e36457d665d1e08c3866add6ed5e70050c1b4ba8a8ddedb02ce7" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.12.1", ] [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.17", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "ref-cast" -version = "1.0.22" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4846d4c50d1721b1a3bef8af76924eef20d5e723647333798c1b519b3a9473f" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.22" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "regex" -version = "1.10.4" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.2", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", + "regex-automata", + "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.2" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" -version = "0.11.23" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64 0.21.7", "bytes", - "cookie 0.16.2", + "cookie", "cookie_store", "encoding_rs", "futures-core", "futures-util", - "h2 0.3.26", - "http 0.2.11", + "h2 0.3.27", + "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.32", "hyper-rustls 0.24.2", "hyper-tls", "ipnet", @@ -15717,85 +16280,82 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.10", + "rustls 0.21.12", "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper 0.1.2", "system-configuration", "tokio", "tokio-native-tls", "tokio-rustls 0.24.1", - "tokio-util 0.7.10", + "tokio-util 0.7.18", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams 0.3.0", + "wasm-streams", "web-sys", - "webpki-roots 0.25.3", - "winreg 0.50.0", + "webpki-roots 0.25.4", + "winreg", ] [[package]] name = "reqwest" -version = "0.12.5" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ - "async-compression", "base64 0.22.1", "bytes", "futures-core", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http 1.4.1", + "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", - "hyper-rustls 0.27.2", + "hyper 1.10.1", + "hyper-rustls 0.27.9", "hyper-util", - "ipnet", "js-sys", "log", - "mime", "mime_guess", - "once_cell", "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.7", - "rustls-native-certs 0.7.0", - "rustls-pemfile 2.1.1", + "rustls 0.23.40", + "rustls-native-certs 0.8.4", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tokio", - "tokio-rustls 0.26.0", - "tokio-util 0.7.10", + "tokio-rustls 0.26.4", + "tokio-util 0.7.18", + "tower 0.5.3", + "tower-http 0.6.11", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams 0.4.0", + "wasm-streams", "web-sys", - "winreg 0.52.0", ] [[package]] name = "reqwest-middleware" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a3e86aa6053e59030e7ce2d2a3b258dd08fc2d337d52f73f6cb480f5858690" +checksum = "5a735987236a8e238bf0296c7e351b999c188ccc11477f311b82b55c93984216" dependencies = [ "anyhow", "async-trait", - "http 0.2.11", - "reqwest 0.11.23", + "http 0.2.12", + "reqwest 0.11.27", "serde", "task-local-extensions", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -15808,11 +16368,11 @@ dependencies = [ "async-trait", "chrono", "futures", - "getrandom 0.2.11", - "http 0.2.11", - "hyper 0.14.28", + "getrandom 0.2.17", + "http 0.2.12", + "hyper 0.14.32", "parking_lot 0.11.2", - "reqwest 0.11.23", + "reqwest 0.11.27", "reqwest-middleware", "retry-policies", "task-local-extensions", @@ -15835,33 +16395,44 @@ checksum = "e09bbcb5003282bcb688f0bae741b278e9c7e8f378f561522c9806c58e075d9b" dependencies = [ "anyhow", "chrono", - "rand 0.8.5", + "rand 0.8.6", ] [[package]] name = "rfc6979" -version = "0.4.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" dependencies = [ + "crypto-bigint 0.4.9", "hmac 0.12.1", - "subtle", + "zeroize", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", ] [[package]] name = "rfc7239" -version = "0.1.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "087317b3cf7eb481f13bd9025d729324b7cd068d6f470e2d76d049e191f5ba47" +checksum = "4a82f1d1e38e9a85bb58ffcfadf22ed6f2c94e8cd8581ec2b0f80a2a6858350f" dependencies = [ "uncased", ] [[package]] name = "rgb" -version = "0.8.37" +version = "0.8.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" dependencies = [ "bytemuck", ] @@ -15883,16 +16454,16 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", - "getrandom 0.2.11", + "cfg-if", + "getrandom 0.2.17", "libc", - "spin 0.9.8", "untrusted 0.9.0", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -15904,6 +16475,40 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "ritual_build" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f86c36bf720176c6d573d0827cd5b2b9f1c6a3450dc237374a35ce0f2268835" +dependencies = [ + "log", + "ritual_common", +] + +[[package]] +name = "ritual_common" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d30de34c9683bedc6f0b1f5a3ef0bb613df7ff7e1833c767eeed45f1a9d2af" +dependencies = [ + "bincode", + "dunce", + "failure", + "itertools 0.8.2", + "lazy_static", + "log", + "num_cpus", + "pathdiff 0.1.0", + "regex", + "semver 0.9.0", + "serde", + "serde_derive", + "serde_json", + "shell-words 0.1.0", + "term-painter", + "toml 0.4.10", +] + [[package]] name = "rlimit" version = "0.10.2" @@ -15967,9 +16572,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.6" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" dependencies = [ "const-oid 0.9.6", "digest 0.10.7", @@ -16051,9 +16656,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" [[package]] name = "rustc-hash" @@ -16061,6 +16666,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + [[package]] name = "rustc-hex" version = "2.1.0" @@ -16069,11 +16680,11 @@ checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver", + "semver 1.0.28", ] [[package]] @@ -16092,29 +16703,28 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.27" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.12.1", "errno", - "io-lifetimes", "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", ] [[package]] name = "rustix" -version = "0.38.28" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.12.1", "errno", "libc", - "linux-raw-sys 0.4.12", - "windows-sys 0.52.0", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", ] [[package]] @@ -16131,12 +16741,12 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring 0.17.7", + "ring 0.17.14", "rustls-webpki 0.101.7", "sct", ] @@ -16148,24 +16758,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ "log", - "ring 0.17.7", + "ring 0.17.14", "rustls-pki-types", - "rustls-webpki 0.102.2", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] [[package]] name = "rustls" -version = "0.23.7" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebbbdb961df0ad3f2652da8f3fdc4b36122f568f968f45ad3316f26c025c677b" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ + "aws-lc-rs", "log", "once_cell", - "ring 0.17.7", + "ring 0.17.14", "rustls-pki-types", - "rustls-webpki 0.102.2", + "rustls-webpki 0.103.13", "subtle", "zeroize", ] @@ -16176,36 +16787,22 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ - "openssl-probe", + "openssl-probe 0.1.6", "rustls-pemfile 1.0.4", "schannel", - "security-framework", -] - -[[package]] -name = "rustls-native-certs" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" -dependencies = [ - "openssl-probe", - "rustls-pemfile 2.1.1", - "rustls-pki-types", - "schannel", - "security-framework", + "security-framework 2.11.1", ] [[package]] name = "rustls-native-certs" -version = "0.8.0" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" +checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" dependencies = [ - "openssl-probe", - "rustls-pemfile 2.1.1", + "openssl-probe 0.2.1", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 3.7.0", ] [[package]] @@ -16228,19 +16825,22 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.21.7", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.10.1" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +dependencies = [ + "web-time", + "zeroize", +] [[package]] name = "rustls-webpki" @@ -16258,32 +16858,44 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.7", + "ring 0.17.14", + "untrusted 0.9.0", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring 0.17.14", + "rustls-pki-types", "untrusted 0.9.0", ] [[package]] name = "rustls-webpki" -version = "0.102.2" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ - "ring 0.17.7", + "aws-lc-rs", + "ring 0.17.14", "rustls-pki-types", "untrusted 0.9.0", ] [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "rusty-fork" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" dependencies = [ "fnv", "quick-error", @@ -16313,15 +16925,15 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "safe_arch" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f398075ce1e6a179b46f51bd88d0598b92b00d3551f1a2d4ac49e771b56ac354" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" dependencies = [ "bytemuck", ] @@ -16360,7 +16972,7 @@ checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" dependencies = [ "cfg-if", "derive_more 1.0.0", - "parity-scale-codec 3.6.12", + "parity-scale-codec 3.7.5", "scale-info-derive", ] @@ -16370,19 +16982,19 @@ version = "2.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -16391,17 +17003,40 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" dependencies = [ - "parking_lot 0.12.1", + "parking_lot 0.12.5", +] + +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", ] [[package]] name = "scoped-futures" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1473e24c637950c9bd38763220bea91ec3e095a89f672bbd7a10d03e77ba467" +checksum = "1b24aae2d0636530f359e9d5ef0c04669d11c5e756699b27a6a6d845d8329091" dependencies = [ - "cfg-if", - "pin-utils", + "pin-project-lite", ] [[package]] @@ -16425,7 +17060,7 @@ dependencies = [ "hmac 0.12.1", "pbkdf2 0.11.0", "salsa20", - "sha2 0.10.8", + "sha2 0.10.9", ] [[package]] @@ -16434,7 +17069,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.7", + "ring 0.17.14", "untrusted 0.9.0", ] @@ -16444,14 +17079,28 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct 0.1.1", + "der 0.6.1", + "generic-array", + "pkcs8 0.9.0", + "subtle", + "zeroize", +] + [[package]] name = "sec1" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ - "base16ct", - "der 0.7.8", + "base16ct 0.2.0", + "der 0.7.10", "generic-array", "pkcs8 0.10.2", "serdect", @@ -16461,12 +17110,12 @@ dependencies = [ [[package]] name = "secret-vault-value" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5f8cfb86d2019f64a4cfb49e499f401f406fbec946c1ffeea9d0504284347de" +checksum = "662c7f8e99d46c9d3a87561d771a970c29efaccbab4bbdc6ab65d099d2358077" dependencies = [ - "prost 0.12.3", - "prost-types 0.12.3", + "prost 0.14.3", + "prost-types 0.14.3", "serde", "serde_json", "zeroize", @@ -16474,12 +17123,25 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", - "core-foundation", + "bitflags 2.12.1", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags 2.12.1", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -16487,9 +17149,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -16497,13 +17159,13 @@ dependencies = [ [[package]] name = "self-replace" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7828a58998685d8bf5a3c5e7a3379a5867289c20828c3ee436280b44b598515" +checksum = "03ec815b5eab420ab893f63393878d89c90fdd94c0bcc44c07abb8ad95552fb7" dependencies = [ - "fastrand 1.9.0", + "fastrand", "tempfile", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -16511,14 +17173,14 @@ name = "self_update" version = "0.39.0" source = "git+https://github.com/banool/self_update.git?rev=8306158ad0fd5b9d4766a3c6bf967e7ef0ea5c4b#8306158ad0fd5b9d4766a3c6bf967e7ef0ea5c4b" dependencies = [ - "hyper 0.14.28", + "hyper 0.14.32", "indicatif 0.17.11", "log", "quick-xml 0.23.1", "regex", - "reqwest 0.11.23", + "reqwest 0.11.27", "self-replace", - "semver", + "semver 1.0.28", "serde_json", "tempfile", "urlencoding", @@ -16528,18 +17190,28 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.21" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" dependencies = [ "serde", + "serde_core", ] [[package]] -name = "send_wrapper" -version = "0.4.0" +name = "semver-parser" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "send_wrapper" @@ -16549,16 +17221,17 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "seq-macro" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" +checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] @@ -16596,7 +17269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12c47087018ec281d1cdab673d36aea22d816b54d498264029c05d5fa1910da6" dependencies = [ "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -16606,7 +17279,7 @@ source = "git+https://github.com/aptos-labs/serde-reflection?rev=73b6bbf748334b7 dependencies = [ "once_cell", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -16621,11 +17294,12 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.14" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" dependencies = [ "serde", + "serde_core", ] [[package]] @@ -16634,31 +17308,42 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" dependencies = [ - "half 1.8.2", + "half 1.8.3", "serde", ] +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ - "indexmap 2.7.0", + "indexmap 2.14.0", "itoa", - "ryu", + "memchr", "serde", + "serde_core", + "zmij", ] [[package]] @@ -16669,24 +17354,38 @@ checksum = "606e91878516232ac3b16c12e063d4468d762f16d77e7aef14a1f2326c5f409b" dependencies = [ "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", +] + +[[package]] +name = "serde_norway" +version = "0.9.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e408f29489b5fd500fab51ff1484fc859bb655f32c671f307dcd733b72e8168c" +dependencies = [ + "indexmap 2.14.0", + "itoa", + "ryu", + "serde", + "unsafe-libyaml-norway", ] [[package]] name = "serde_path_to_error" -version = "0.1.16" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" dependencies = [ "itoa", "serde", + "serde_core", ] [[package]] name = "serde_regex" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8136f1a4ea815d7eac4101cfd0b16dc0cb5e1fe1b8609dfd728058656b7badf" +checksum = "bafc8d0c5330cecff10f16b459b479fd9acaa5b4acd7167301414e21b0057012" dependencies = [ "regex", "serde", @@ -16694,24 +17393,33 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.18" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -16726,16 +17434,19 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.4.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" +checksum = "e72c1c2cb7b223fafb600a619537a871c2818583d619401b785e7c0b746ccde2" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", + "bs58 0.5.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.7.0", - "serde", + "indexmap 2.14.0", + "schemars 0.9.0", + "schemars 1.2.1", + "serde_core", "serde_json", "serde_with_macros", "time", @@ -16743,14 +17454,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.4.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" +checksum = "b90c488738ecb4fb0262f41f43bc40efc5868d9fb744319ddf5f5317f417bfac" dependencies = [ - "darling 0.20.10", + "darling 0.23.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -16767,11 +17478,11 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.30" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1bf28c79a99f70ee1f1d83d10c875d2e70618417fda01ad1785e027579d9d38" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.7.0", + "indexmap 2.14.0", "itoa", "ryu", "serde", @@ -16784,7 +17495,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" dependencies = [ - "base16ct", + "base16ct 0.2.0", "serde", ] @@ -16814,15 +17525,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] [[package]] name = "sha1_smol" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" @@ -16832,32 +17543,43 @@ checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.9.0", "opaque-debug", ] [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] +[[package]] +name = "sha2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.3", +] + [[package]] name = "sha256" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18278f6a914fa3070aa316493f7d2ddfb9ac86ebc06fa3b83bffda487e9065b0" +checksum = "f880fc8562bdeb709793f00eb42a2ad0e672c4f883bbe59122b926eca935c8f6" dependencies = [ "async-trait", "bytes", "hex", - "sha2 0.10.8", + "sha2 0.10.9", "tokio", ] @@ -16875,9 +17597,9 @@ dependencies = [ [[package]] name = "sha3" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" dependencies = [ "digest 0.10.7", "keccak", @@ -16907,9 +17629,15 @@ dependencies = [ [[package]] name = "shell-words" -version = "1.1.0" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" +checksum = "39acde55a154c4cd3ae048ac78cc21c25f3a0145e44111b523279113dce0d94a" + +[[package]] +name = "shell-words" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" [[package]] name = "shlex" @@ -16917,11 +17645,17 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + [[package]] name = "signal-hook" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" dependencies = [ "libc", "signal-hook-registry", @@ -16929,9 +17663,9 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" dependencies = [ "libc", "mio 0.8.11", @@ -16940,10 +17674,11 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -16952,6 +17687,10 @@ name = "signature" version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] [[package]] name = "signature" @@ -16970,7 +17709,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae" dependencies = [ "approx", - "num-complex 0.4.4", + "num-complex 0.4.6", + "num-traits", + "paste", + "wide", +] + +[[package]] +name = "simba" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c99284beb21666094ba2b75bbceda012e610f5479dfcc2d6e2426f53197ffd95" +dependencies = [ + "approx", + "num-complex 0.4.6", "num-traits", "paste", "wide", @@ -16978,27 +17730,27 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "similar" -version = "2.4.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" dependencies = [ - "bstr 0.2.17", + "bstr", "unicode-segmentation", ] [[package]] name = "similar-asserts" -version = "1.5.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e041bb827d1bfca18f213411d51b665309f1afb37a04a5d1464530e13779fc0f" +checksum = "b5b441962c817e33508847a22bd82f03a30cff43642dc2fae8b050566121eb9a" dependencies = [ - "console", + "console 0.15.11", "similar", ] @@ -17015,13 +17767,13 @@ dependencies = [ [[package]] name = "simple_asn1" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" dependencies = [ - "num-bigint 0.4.4", + "num-bigint 0.4.6", "num-traits", - "thiserror", + "thiserror 2.0.18", "time", ] @@ -17044,9 +17796,9 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "sized-chunks" @@ -17081,18 +17833,15 @@ checksum = "85636c14b73d81f541e525f585c0a2109e6744e1565b5c1668e31c70c10ed65c" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "slug" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bd94acec9c8da640005f8e135a39fc0372e74535e6b368b7a04b875f784c8c4" +checksum = "882a80f72ee45de3cc9a5afeb2da0331d58df69e4e7d8eeb5d3c7784ae67e724" dependencies = [ "deunicode", "wasm-bindgen", @@ -17100,26 +17849,26 @@ dependencies = [ [[package]] name = "sluice" -version = "0.5.5" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7400c0eff44aa2fcb5e31a5f24ba9716ed90138769e4977a2ba6014ae63eb5" +checksum = "160b744a45e8261307bcfe03c98e2f8274502207d534c9a64b675c4db1b6bd58" dependencies = [ - "async-channel 1.9.0", + "async-channel 2.5.0", "futures-core", "futures-io", ] [[package]] name = "smallbitvec" -version = "2.5.1" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ce4f9dc4a41b4c3476cc925f1efb11b66df373a8fde5d4b8915fa91b5d995e" +checksum = "9b0e903ee191d8f7a8fbf0d712c3a1699d19e04ceba5ad1eb673053c7d938a09" [[package]] name = "smallvec" -version = "1.13.1" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "smawk" @@ -17177,7 +17926,7 @@ dependencies = [ "ethers", "futures", "hex", - "hyper 0.14.28", + "hyper 0.14.32", "itertools 0.13.0", "move-binary-format", "move-core-types", @@ -17185,7 +17934,7 @@ dependencies = [ "once_cell", "rand 0.7.3", "regex", - "reqwest 0.11.23", + "reqwest 0.11.27", "serde", "serde_json", "serde_yaml 0.8.26", @@ -17231,46 +17980,22 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.10" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", - "winapi 0.3.9", + "windows-sys 0.52.0", ] [[package]] name = "socket2" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" -dependencies = [ - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "socket2" -version = "0.6.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", - "windows-sys 0.60.2", -] - -[[package]] -name = "solang-parser" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c425ce1c59f4b154717592f0bdf4715c3a1d55058883622d3157e1f0908a5b26" -dependencies = [ - "itertools 0.11.0", - "lalrpop 0.20.2", - "lalrpop-util 0.20.2", - "phf 0.11.2", - "thiserror", - "unicode-xid", + "windows-sys 0.61.2", ] [[package]] @@ -17281,7 +18006,7 @@ checksum = "c87e960f4dca2788eeb86bbdde8dd246be8948790b7618d656e68f9b720a86e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -17295,9 +18020,6 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] [[package]] name = "spki" @@ -17309,6 +18031,16 @@ dependencies = [ "der 0.5.1", ] +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der 0.6.1", +] + [[package]] name = "spki" version = "0.7.3" @@ -17316,14 +18048,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der 0.7.8", + "der 0.7.10", ] [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -17331,6 +18063,18 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "statrs" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a3fe7c28c6512e766b0874335db33c94ad7b8f9054228ae1c2abd47ce7d335e" +dependencies = [ + "approx", + "nalgebra 0.33.3", + "num-traits", + "rand 0.8.6", +] + [[package]] name = "status-line" version = "0.2.0" @@ -17343,39 +18087,38 @@ dependencies = [ [[package]] name = "str_stack" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" +checksum = "7f446288b699d66d0fd2e30d1cfe7869194312524b3b9252594868ed26ef056a" [[package]] name = "string_cache" -version = "0.8.7" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" dependencies = [ "new_debug_unreachable", - "once_cell", - "parking_lot 0.12.1", - "phf_shared 0.10.0", + "parking_lot 0.12.5", + "phf_shared 0.11.3", "precomputed-hash", ] [[package]] name = "stringprep" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "finl_unicode", "unicode-bidi", "unicode-normalization", + "unicode-properties", ] [[package]] name = "strip-ansi-escapes" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa" +checksum = "2a8f8038e7e7969abb3f1b7c2a811225e9296da208539e0f79c5251d6cac0025" dependencies = [ "vte", ] @@ -17400,11 +18143,11 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "struct-path" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899edf28cf7320503eda593b4bbce1bc5e9533501a11d45537e2c5be90128fc7" +checksum = "3bb4afb8a683e3335fa737ad69e4338f1293debed26ec15c0cfab497e75ad3e3" dependencies = [ - "convert_case 0.6.0", + "convert_case 0.8.0", ] [[package]] @@ -17460,9 +18203,9 @@ dependencies = [ [[package]] name = "strum" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" [[package]] name = "strum_macros" @@ -17487,7 +18230,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -17500,27 +18243,26 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "strum_macros" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "rustversion", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "subtle-ng" @@ -17541,28 +18283,8 @@ dependencies = [ "anyhow", "aptos-types", "async-trait", - "clap 4.5.21", - "reqwest 0.11.23", -] - -[[package]] -name = "svm-rs" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11297baafe5fa0c99d5722458eac6a5e25c01eb1b8e5cd137f54079093daa7a4" -dependencies = [ - "dirs 5.0.1", - "fs2", - "hex", - "once_cell", - "reqwest 0.11.23", - "semver", - "serde", - "serde_json", - "sha2 0.10.8", - "thiserror", - "url", - "zip", + "clap 4.6.1", + "reqwest 0.11.27", ] [[package]] @@ -17574,7 +18296,7 @@ dependencies = [ "debugid", "memmap2", "stable_deref_trait", - "uuid 1.11.0", + "uuid 1.23.2", ] [[package]] @@ -17601,9 +18323,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -17618,13 +18340,36 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "sysinfo" version = "0.28.4" @@ -17647,7 +18392,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys", ] @@ -17675,9 +18420,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.40" +version = "0.4.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840" dependencies = [ "filetime", "libc", @@ -17686,23 +18431,28 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.13" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" [[package]] name = "target-spec" -version = "3.1.0" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36a8e795b1824524d13cdf04f73cf8b4f244ce86c96b4d2a83a6ca1a753d2752" +checksum = "b00e973676af5497c2a69cc9787e2205c00f3b6f4f70e7d7b0112e28aa84b501" dependencies = [ "cfg-expr", "guppy-workspace-hack", "serde", "target-lexicon", - "unicode-ident", ] +[[package]] +name = "target-triple" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "591ef38edfb78ca4771ee32cf494cb8771944bee237a9b91fc9c1424ac4b777b" + [[package]] name = "task-local-extensions" version = "0.1.4" @@ -17714,37 +18464,47 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.9.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ - "cfg-if", - "fastrand 2.0.1", - "redox_syscall 0.4.1", - "rustix 0.38.28", - "windows-sys 0.52.0", + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix 1.1.4", + "windows-sys 0.61.2", ] [[package]] name = "tera" -version = "1.19.1" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "970dff17c11e884a4a09bc76e3a17ef71e01bb13447a11e85226e254fe6d10b8" +checksum = "e8004bca281f2d32df3bacd59bc67b312cb4c70cea46cbd79dbe8ac5ed206722" dependencies = [ "chrono", - "chrono-tz 0.8.5", + "chrono-tz 0.9.0", "globwalk", "humansize", "lazy_static", "percent-encoding", "pest", "pest_derive", - "rand 0.8.5", + "rand 0.8.6", "regex", "serde", "serde_json", "slug", - "unic-segment", + "unicode-segmentation", +] + +[[package]] +name = "term" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" +dependencies = [ + "kernel32-sys", + "winapi 0.2.8", ] [[package]] @@ -17758,6 +18518,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "term-painter" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcaa948f0e3e38470cd8dc8dcfe561a75c9e43f28075bb183845be2b9b3c08cf" +dependencies = [ + "term 0.4.6", +] + [[package]] name = "termcolor" version = "1.1.3" @@ -17769,19 +18538,19 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.4.0" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef" +checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ - "rustix 0.38.28", - "windows-sys 0.59.0", + "rustix 1.1.4", + "windows-sys 0.61.2", ] [[package]] name = "termtree" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "test-case" @@ -17801,7 +18570,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -17812,7 +18581,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", "test-case-core", ] @@ -17822,7 +18591,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width 0.1.11", + "unicode-width 0.1.14", ] [[package]] @@ -17832,7 +18601,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd05616119e612a8041ef58f2b578906cc2531a6069047ae092cfb86a325d835" dependencies = [ "smawk", - "unicode-width 0.1.11", + "unicode-width 0.1.14", ] [[package]] @@ -17843,14 +18612,14 @@ checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" dependencies = [ "smawk", "unicode-linebreak", - "unicode-width 0.1.11", + "unicode-width 0.1.14", ] [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" [[package]] name = "thiserror" @@ -17858,7 +18627,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", ] [[package]] @@ -17869,17 +18647,27 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", ] [[package]] @@ -17904,9 +18692,9 @@ dependencies = [ [[package]] name = "tiff" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" dependencies = [ "flate2", "jpeg-decoder", @@ -17915,9 +18703,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.41" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", @@ -17925,22 +18713,22 @@ dependencies = [ "num-conv", "num_threads", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.22" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -17957,9 +18745,9 @@ dependencies = [ "once_cell", "pbkdf2 0.4.0", "rand 0.7.3", - "rustc-hash", + "rustc-hash 1.1.0", "sha2 0.9.9", - "thiserror", + "thiserror 1.0.69", "unicode-normalization", "wasm-bindgen", "zeroize", @@ -17974,6 +18762,16 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -17986,9 +18784,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -18001,28 +18799,27 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ - "backtrace", "bytes", "libc", - "mio 1.0.2", - "parking_lot 0.12.1", + "mio 1.2.1", + "parking_lot 0.12.5", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2 0.6.4", "tokio-macros", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-io-timeout" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +checksum = "0bd86198d9ee903fedd2f9a2e72014287c0d9167e4ae43b5853007205dda1b76" dependencies = [ "pin-project-lite", "tokio", @@ -18030,13 +18827,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -18051,9 +18848,9 @@ dependencies = [ [[package]] name = "tokio-postgres" -version = "0.7.15" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b40d66d9b2cfe04b628173409368e58247e8eddbbd3b0e6c6ba1d09f20f6c9e" +checksum = "4dd8df5ef180f6364759a6f00f7aadda4fbbac86cdee37480826a6ff9f3574ce" dependencies = [ "async-trait", "byteorder", @@ -18062,27 +18859,27 @@ dependencies = [ "futures-channel", "futures-util", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "percent-encoding", "phf 0.13.1", "pin-project-lite", "postgres-protocol", "postgres-types", - "rand 0.9.1", - "socket2 0.6.1", + "rand 0.10.1", + "socket2 0.6.4", "tokio", - "tokio-util 0.7.10", - "whoami", + "tokio-util 0.7.18", + "whoami 2.1.0", ] [[package]] name = "tokio-retry" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" +checksum = "40f644c762e9d396831ae2f8935c954b0d758c4532e924bead0f666d0c1c8640" dependencies = [ - "pin-project 1.1.3", - "rand 0.8.5", + "pin-project-lite", + "rand 0.10.1", "tokio", ] @@ -18103,7 +18900,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.10", + "rustls 0.21.12", "tokio", ] @@ -18120,12 +18917,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.7", - "rustls-pki-types", + "rustls 0.23.40", "tokio", ] @@ -18141,9 +18937,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -18152,12 +18948,10 @@ dependencies = [ [[package]] name = "tokio-test" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b3cbabd3ae862100094ae433e1def582cf86451b4e9bf83aa7ac1d8a7d719" +checksum = "3f6d24790a10a7af737693a3e8f1d03faef7e6ca0cc99aae5066f533766de545" dependencies = [ - "async-stream", - "bytes", "futures-core", "tokio", "tokio-stream", @@ -18165,17 +18959,14 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" dependencies = [ "futures-util", "log", - "rustls 0.21.10", "tokio", - "tokio-rustls 0.24.1", "tungstenite", - "webpki-roots 0.25.3", ] [[package]] @@ -18194,9 +18985,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -18204,7 +18995,15 @@ dependencies = [ "futures-sink", "pin-project-lite", "tokio", - "tracing", +] + +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +dependencies = [ + "serde", ] [[package]] @@ -18224,69 +19023,140 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ "serde", - "serde_spanned", - "toml_datetime", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", "toml_edit 0.19.15", ] [[package]] name = "toml" -version = "0.8.12" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.22.12", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", +] + +[[package]] +name = "toml" +version = "0.9.12+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" +dependencies = [ + "indexmap 2.14.0", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 0.7.5+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 0.7.15", +] + +[[package]] +name = "toml" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +dependencies = [ + "indexmap 2.14.0", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.3", ] [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.7.0", + "indexmap 2.14.0", "serde", - "serde_spanned", - "toml_datetime", - "winnow 0.5.33", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.21.1" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.7.0", - "toml_datetime", - "winnow 0.5.33", + "indexmap 2.14.0", + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_write", + "winnow 0.7.15", ] [[package]] name = "toml_edit" -version = "0.22.12" +version = "0.25.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" +checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" dependencies = [ - "indexmap 2.7.0", - "serde", - "serde_spanned", - "toml_datetime", - "winnow 0.6.26", + "indexmap 2.14.0", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.3", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.3", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + [[package]] name = "tonic" version = "0.9.2" @@ -18301,19 +19171,19 @@ dependencies = [ "flate2", "futures-core", "futures-util", - "h2 0.3.26", - "http 0.2.11", + "h2 0.3.27", + "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.32", "hyper-timeout 0.4.1", "percent-encoding", - "pin-project 1.1.3", + "pin-project 1.1.13", "prost 0.11.9", "rustls-pemfile 1.0.4", "tokio", "tokio-rustls 0.24.1", "tokio-stream", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", "tracing", @@ -18331,17 +19201,17 @@ dependencies = [ "axum 0.6.20", "base64 0.21.7", "bytes", - "h2 0.3.26", - "http 0.2.11", + "h2 0.3.27", + "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.32", "hyper-timeout 0.4.1", "percent-encoding", - "pin-project 1.1.3", - "prost 0.12.3", + "pin-project 1.1.13", + "prost 0.12.6", "tokio", "tokio-stream", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", "tracing", @@ -18355,31 +19225,31 @@ checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" dependencies = [ "async-stream", "async-trait", - "axum 0.7.5", + "axum 0.7.9", "base64 0.22.1", "bytes", "flate2", - "h2 0.4.5", - "http 1.1.0", - "http-body 1.0.0", + "h2 0.4.14", + "http 1.4.1", + "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", - "hyper-timeout 0.5.1", + "hyper 1.10.1", + "hyper-timeout 0.5.2", "hyper-util", "percent-encoding", - "pin-project 1.1.3", - "prost 0.13.4", - "rustls-native-certs 0.8.0", - "rustls-pemfile 2.1.1", - "socket2 0.5.5", + "pin-project 1.1.13", + "prost 0.13.5", + "rustls-native-certs 0.8.4", + "rustls-pemfile 2.2.0", + "socket2 0.5.10", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.4", "tokio-stream", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", "tracing", - "zstd 0.13.0", + "zstd", ] [[package]] @@ -18388,8 +19258,8 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "878d81f52e7fcfd80026b7fdb6a9b578b3c3653ba987f87f0dce4b64043cba27" dependencies = [ - "prost 0.13.4", - "prost-types 0.13.1", + "prost 0.13.5", + "prost-types 0.13.5", "tokio", "tokio-stream", "tonic 0.12.3", @@ -18410,12 +19280,28 @@ dependencies = [ "futures-core", "futures-util", "indexmap 1.9.3", - "pin-project 1.1.3", + "pin-project 1.1.13", "pin-project-lite", - "rand 0.8.5", + "rand 0.8.6", "slab", "tokio", - "tokio-util 0.7.10", + "tokio-util 0.7.18", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 1.0.2", + "tokio", "tower-layer", "tower-service", "tracing", @@ -18432,7 +19318,7 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "http 0.2.11", + "http 0.2.12", "http-body 0.4.6", "http-range-header", "pin-project-lite", @@ -18441,17 +19327,40 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-http" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +dependencies = [ + "async-compression", + "bitflags 2.12.1", + "bytes", + "futures-core", + "futures-util", + "http 1.4.1", + "http-body 1.0.1", + "http-body-util", + "pin-project-lite", + "tokio", + "tokio-util 0.7.18", + "tower 0.5.3", + "tower-layer", + "tower-service", + "url", +] + [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tower-util" @@ -18467,9 +19376,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -18479,20 +19388,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -18504,7 +19413,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ - "pin-project 1.1.3", + "pin-project 1.1.13", "tracing", ] @@ -18521,9 +19430,9 @@ dependencies = [ [[package]] name = "tracing-serde" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" dependencies = [ "serde", "tracing-core", @@ -18540,14 +19449,14 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", - "nu-ansi-term 0.46.0", + "nu-ansi-term 0.50.3", "once_cell", - "regex", + "regex-automata", "serde", "serde_json", "sharded-slab", @@ -18581,9 +19490,9 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.11" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" +checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39" dependencies = [ "serde", "stable_deref_trait", @@ -18612,22 +19521,22 @@ checksum = "b9c81686f7ab4065ccac3df7a910c4249f8c0f3fb70421d6ddec19b9311f63f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] name = "trybuild" -version = "1.0.88" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76de4f783e610194f6c98bfd53f9fc52bb2e0d02c947621e8a0f4ecc799b2880" +checksum = "47c635f0191bd3a2941013e5062667100969f8c4e9cd787c14f977265d73616e" dependencies = [ - "basic-toml", "glob", - "once_cell", "serde", "serde_derive", "serde_json", + "target-triple", "termcolor", + "toml 1.1.2+spec-1.1.0", ] [[package]] @@ -18640,25 +19549,24 @@ dependencies = [ "cassowary", "crossterm 0.25.0", "unicode-segmentation", - "unicode-width 0.1.11", + "unicode-width 0.1.14", ] [[package]] name = "tungstenite" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" dependencies = [ "byteorder", "bytes", "data-encoding", - "http 0.2.11", + "http 1.4.1", "httparse", "log", - "rand 0.8.5", - "rustls 0.21.10", + "rand 0.8.6", "sha1", - "thiserror", + "thiserror 1.0.69", "url", "utf-8", ] @@ -18673,6 +19581,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "twox-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" + [[package]] name = "typed-arena" version = "2.0.2" @@ -18681,15 +19595,15 @@ checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" [[package]] name = "typenum" -version = "1.17.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "typeshare" -version = "1.0.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f44d1a2f454cb35fbe05b218c410792697e76bd868f48d3a418f2cd1a7d527d6" +checksum = "da1bf9fe204f358ffea7f8f779b53923a20278b3ab8e8d97962c5e1b3a54edb7" dependencies = [ "chrono", "serde", @@ -18699,12 +19613,12 @@ dependencies = [ [[package]] name = "typeshare-annotation" -version = "1.0.2" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc670d0e358428857cc3b4bf504c691e572fccaec9542ff09212d3f13d74b7a9" +checksum = "621963e302416b389a1ec177397e9e62de849a78bd8205d428608553def75350" dependencies = [ "quote", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] @@ -18730,18 +19644,18 @@ dependencies = [ [[package]] name = "tzdb_data" -version = "0.1.1" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629555d2921f3f0dc0de98699415a8b2b61dfcd3a0b082a327f7ed748bbb2b76" +checksum = "e866b98f6ed570c3ef7bc92f15021a9f9be377b7e6f8b1f0161179fdf84a442c" dependencies = [ "tz-rs", ] [[package]] name = "ucd-trie" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "uint" @@ -18763,9 +19677,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "uncased" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b9bc53168a4be7402ab86c3aad243a84dd7381d09be0eddc81280c1da95ca68" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" dependencies = [ "version_check", ] @@ -18776,76 +19690,23 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccb97dac3243214f8d8507998906ca3e2e0b900bf9bf4870477f125b82e68f6e" -[[package]] -name = "unic-char-property" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" -dependencies = [ - "unic-char-range", -] - -[[package]] -name = "unic-char-range" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" - -[[package]] -name = "unic-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" - -[[package]] -name = "unic-segment" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23" -dependencies = [ - "unic-ucd-segment", -] - -[[package]] -name = "unic-ucd-segment" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-version" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" -dependencies = [ - "unic-common", -] - [[package]] name = "unicase" -version = "2.7.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-linebreak" @@ -18855,36 +19716,42 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-width" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" @@ -18892,15 +19759,21 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "subtle", ] [[package]] name = "unsafe-libyaml" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "unsafe-libyaml-norway" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39abd59bf32521c7f2301b52d05a6a2c975b6003521cbd0c6dc1582f0a22104" [[package]] name = "untrusted" @@ -18933,14 +19806,15 @@ dependencies = [ [[package]] name = "url" -version = "2.5.2" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna 1.1.0", "percent-encoding", "serde", + "serde_derive", ] [[package]] @@ -18951,17 +19825,17 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "utcnow" -version = "0.2.4" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b10d49a98e3bbd9b73084a7b15f96c5b2136d5a2e2799b99d19a2774d8519d1f" +checksum = "c3d1b903f7711bad0f9c1716c1497bf3db4289c53a2985ba42ac2f2e04047bd9" dependencies = [ - "autocfg", "const_fn", "errno", "js-sys", "libc", - "rustix 0.38.28", - "wasi 0.11.0+wasi-snapshot-preview1", + "rustix 0.38.44", + "rustversion", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", "winapi 0.3.9", ] @@ -18972,11 +19846,42 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "utoipa" +version = "5.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bde15df68e80b16c7d16b9616e80770ad158988daa56a27dccd1e55558b0160" +dependencies = [ + "indexmap 2.14.0", + "serde", + "serde_json", + "serde_norway", + "utoipa-gen", +] + +[[package]] +name = "utoipa-gen" +version = "5.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "6ba0b99ee52df3028635d93840c797102da61f8a7bb3cf751032455895b52ef8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "uuid 1.23.2", +] [[package]] name = "uuid" @@ -18984,40 +19889,43 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.17", "serde", ] [[package]] name = "uuid" -version = "1.11.0" +version = "1.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" dependencies = [ - "getrandom 0.2.11", - "serde", + "getrandom 0.4.2", + "js-sys", + "serde_core", + "wasm-bindgen", ] [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "value-bag" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" +checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" [[package]] name = "variant_count" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae2faf80ac463422992abf4de234731279c058aaf33171ca70277c98406b124" +checksum = "a1935e10c6f04d22688d07c0790f2fc0e1b1c5c2c55bc0cc87ed67656e587dd8" dependencies = [ + "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] @@ -19040,50 +19948,39 @@ checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vte" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" -dependencies = [ - "utf8parse", - "vte_generate_state_changes", -] - -[[package]] -name = "vte_generate_state_changes" -version = "0.1.2" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" +checksum = "231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077" dependencies = [ - "proc-macro2", - "quote", + "memchr", ] [[package]] name = "wait-timeout" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" dependencies = [ "libc", ] [[package]] name = "waker-fn" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -19100,32 +19997,31 @@ dependencies = [ [[package]] name = "warp" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e92e22e03ff1230c03a1a8ee37d2f89cd489e2e541b7550d6afad96faed169" +checksum = "4378d202ff965b011c64817db11d5829506d3404edeadb61f190d111da3f231c" dependencies = [ "bytes", "futures-channel", "futures-util", "headers 0.3.9", - "http 0.2.11", - "hyper 0.14.28", + "http 0.2.12", + "hyper 0.14.32", "log", "mime", "mime_guess", "multer 2.1.0", "percent-encoding", - "pin-project 1.1.3", - "rustls-pemfile 1.0.4", + "pin-project 1.1.13", + "rustls-pemfile 2.2.0", "scoped-tls", "serde", "serde_json", "serde_urlencoded", "tokio", - "tokio-rustls 0.24.1", - "tokio-stream", + "tokio-rustls 0.25.0", "tokio-tungstenite", - "tokio-util 0.7.10", + "tokio-util 0.7.18", "tower-service", "tracing", ] @@ -19136,10 +20032,10 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "948552bbb7a5fb4ba3169fd09b6c1ab53c1b2fdd82603295df550f7a1ec644c0" dependencies = [ - "hyper 0.14.28", + "hyper 0.14.32", "once_cell", - "reqwest 0.11.23", - "thiserror", + "reqwest 0.11.27", + "thiserror 1.0.69", "unicase", "warp", ] @@ -19152,17 +20048,35 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.14.2+wasi-0.2.4" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen 0.51.0", ] [[package]] @@ -19172,36 +20086,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] -name = "wasm-bindgen" -version = "0.2.100" +name = "wasite" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "66fe902b4a6b8028a753d5424909b764ccf79b7a209eac9bf97e59cda9f71a42" dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", + "wasi 0.14.7+wasi-0.2.4", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" +name = "wasm-bindgen" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.87", + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" dependencies = [ "cfg-if", "js-sys", @@ -19212,9 +20122,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -19222,44 +20132,53 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.87", - "wasm-bindgen-backend", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] [[package]] -name = "wasm-streams" -version = "0.3.0" +name = "wasm-encoder" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.14.0", + "wasm-encoder", + "wasmparser", ] [[package]] name = "wasm-streams" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" +checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" dependencies = [ "futures-util", "js-sys", @@ -19283,11 +20202,23 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.12.1", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "semver 1.0.28", +] + [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" dependencies = [ "js-sys", "wasm-bindgen", @@ -19309,7 +20240,7 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring 0.17.7", + "ring 0.17.14", "untrusted 0.9.0", ] @@ -19324,15 +20255,15 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.3" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "weezl" -version = "0.1.7" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" [[package]] name = "which" @@ -19343,25 +20274,36 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.28", + "rustix 0.38.44", ] [[package]] name = "whoami" -version = "1.5.0" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" +dependencies = [ + "libredox", + "wasite 0.1.0", + "web-sys", +] + +[[package]] +name = "whoami" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fec781d48b41f8163426ed18e8fc2864c12937df9ce54c88ede7bd47270893e" +checksum = "8fae98cf96deed1b7572272dfc777713c249ae40aa1cf8862e091e8b745f5361" dependencies = [ - "redox_syscall 0.4.1", - "wasite", + "libredox", + "wasite 1.0.2", "web-sys", ] [[package]] name = "wide" -version = "0.7.13" +version = "0.7.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68938b57b33da363195412cfc5fc37c9ed49aa9cfe2156fde64b8d2c9498242" +checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" dependencies = [ "bytemuck", "safe_arch", @@ -19375,9 +20317,9 @@ checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" [[package]] name = "wildmatch" -version = "2.3.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "495ec47bf3c1345005f40724f0269362c8556cbc43aed0526ed44cae1d35fceb" +checksum = "29333c3ea1ba8b17211763463ff24ee84e41c78224c16b001cd907e663a38c68" [[package]] name = "winapi" @@ -19395,6 +20337,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -19403,11 +20351,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "winapi 0.3.9", + "windows-sys 0.61.2", ] [[package]] @@ -19418,11 +20366,37 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.52.0" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ - "windows-targets 0.52.6", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] @@ -19431,6 +20405,24 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -19476,6 +20468,15 @@ dependencies = [ "windows-targets 0.53.5", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -19721,18 +20722,27 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.5.33" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7520bbdec7211caa7c4e682eb1fbe07abe20cee6756b6e00f537c82c11816aa" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ "memchr", ] [[package]] name = "winnow" -version = "0.6.26" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e90edd2ac1aa278a5c4599b1d89cf03074b610800f866d4026dc199d7929a28" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" dependencies = [ "memchr", ] @@ -19748,29 +20758,110 @@ dependencies = [ ] [[package]] -name = "winreg" -version = "0.52.0" +name = "wit-bindgen" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" dependencies = [ - "cfg-if", - "windows-sys 0.48.0", + "wit-bindgen-rust-macro", ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.14.0", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.12.1", + "indexmap 2.14.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ - "bitflags 2.9.1", + "anyhow", + "id-arena", + "indexmap 2.14.0", + "log", + "semver 1.0.28", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", ] +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + [[package]] name = "ws_stream_wasm" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" +checksum = "6c173014acad22e83f16403ee360115b38846fe754e735c5d9d3803fe70c6abc" dependencies = [ "async_io_stream", "futures", @@ -19778,8 +20869,8 @@ dependencies = [ "log", "pharos", "rustc_version", - "send_wrapper 0.6.0", - "thiserror", + "send_wrapper", + "thiserror 2.0.18", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -19812,13 +20903,12 @@ dependencies = [ [[package]] name = "xattr" -version = "1.2.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914566e6413e7fa959cc394fb30e563ba80f3541fbd40816d4c05a0fc3f2a0f1" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ "libc", - "linux-raw-sys 0.4.12", - "rustix 0.38.28", + "rustix 1.1.4", ] [[package]] @@ -19832,15 +20922,32 @@ dependencies = [ [[package]] name = "yansi" -version = "0.5.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] -name = "yansi" -version = "1.0.0-rc.1" +name = "yoke" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1367295b8f788d371ce2dbc842c7b709c73ee1364d30351dd300ec2203b12377" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure 0.13.2", +] [[package]] name = "yup-oauth2" @@ -19852,8 +20959,8 @@ dependencies = [ "async-trait", "base64 0.21.7", "futures", - "http 0.2.11", - "hyper 0.14.28", + "http 0.2.12", + "hyper 0.14.32", "hyper-rustls 0.24.2", "itertools 0.12.1", "log", @@ -19877,47 +20984,101 @@ checksum = "57b52f3d4b300ffa9400cd78caebaaa6ef5a0189d08ec134624e2b8f3890b6e0" dependencies = [ "smt2parser", "structopt", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerofrom" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", + "synstructure 0.13.2", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.117", ] [[package]] @@ -19926,72 +21087,58 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" dependencies = [ - "aes", "byteorder", - "bzip2", - "constant_time_eq 0.1.5", "crc32fast", "crossbeam-utils", "flate2", - "hmac 0.12.1", - "pbkdf2 0.11.0", - "sha1", "time", - "zstd 0.11.2+zstd.1.5.2", ] [[package]] name = "zipsign-api" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6413a546ada9dbcd0b9a3e0b0880581279e35047bce9797e523b3408e1df607c" +checksum = "dba6063ff82cdbd9a765add16d369abe81e520f836054e997c2db217ceca40c0" dependencies = [ - "ed25519-dalek 2.1.1", - "thiserror", + "ed25519-dalek 2.2.0", + "thiserror 2.0.18", ] [[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" +name = "zlib-rs" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" -dependencies = [ - "zstd-safe 5.0.2+zstd.1.5.2", -] +checksum = "3be3d40e40a133f9c916ee3f9f4fa2d9d63435b5fbe1bfc6d9dae0aa0ada1513" [[package]] -name = "zstd" -version = "0.13.0" +name = "zmij" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" -dependencies = [ - "zstd-safe 7.0.0", -] +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" [[package]] -name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" +name = "zstd" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" dependencies = [ - "libc", - "zstd-sys", + "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.0.0" +version = "7.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" +version = "2.0.16+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" dependencies = [ "cc", "pkg-config", @@ -20005,3 +21152,48 @@ checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" dependencies = [ "simd-adler32", ] + +[[patch.unused]] +name = "futures" +version = "0.3.30" +source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" + +[[patch.unused]] +name = "futures-channel" +version = "0.3.30" +source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" + +[[patch.unused]] +name = "futures-core" +version = "0.3.30" +source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" + +[[patch.unused]] +name = "futures-executor" +version = "0.3.30" +source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" + +[[patch.unused]] +name = "futures-io" +version = "0.3.30" +source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" + +[[patch.unused]] +name = "futures-macro" +version = "0.3.30" +source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" + +[[patch.unused]] +name = "futures-sink" +version = "0.3.30" +source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" + +[[patch.unused]] +name = "futures-task" +version = "0.3.30" +source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" + +[[patch.unused]] +name = "futures-util" +version = "0.3.30" +source = "git+https://github.com/aptos-labs/futures-rs?branch=backport#1845d7d36bc4bccbc0b57be68fbc05abd0b8bc68" diff --git a/Cargo.toml b/Cargo.toml index 1c824eaeda2..063d1397f63 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -562,6 +562,7 @@ criterion-cpu-time = "0.1.0" crossbeam = "0.8.1" crossbeam-channel = "0.5.4" crossterm = "0.26.1" +crypto = { git = "ssh://git@github.com/Entropy-Foundation/crypto", rev = "d045a68" } csv = "1.2.1" curve25519-dalek = "3" curve25519-dalek-ng = "4" @@ -573,7 +574,7 @@ derivation-path = "0.2.0" derive_builder = "0.20.0" derive-getters = "0.5.0" determinator = "0.12.0" -derive_more = { version = "2.0.1",features = ["full"] } +derive_more = { version = "2.0.1", features = ["full"] } diesel = { version = "2.2.0", features = ["uuid"] } # Use the crate version once this feature gets released on crates.io: # https://github.com/weiznich/diesel_async/commit/e165e8c96a6c540ebde2d6d7c52df5c5620a4bf1 @@ -611,10 +612,10 @@ firestore = "0.43.0" fixed = "1.25.1" flate2 = "1.0.24" flexi_logger = "0.27.4" -futures = "0.3.29" -futures-channel = "0.3.29" -futures-core = "0.3.29" -futures-util = "0.3.29" +futures = "0.3.32" +futures-channel = "0.3.32" +futures-core = "0.3.32" +futures-util = "0.3.32" fxhash = "0.2.1" getrandom = "0.2.2" gcp-bigquery-client = "0.16.8" @@ -769,7 +770,7 @@ shell-words = "1.0.0" siphasher = "0.3.10" serde = { version = "1.0.193", features = ["derive", "rc"] } serde-big-array = "0.5.1" -serde_bytes = "0.11.6" +serde_bytes = "0.11.19" serde_json = { version = "1.0.81", features = [ "preserve_order", "arbitrary_precision", @@ -836,6 +837,7 @@ ureq = { version = "1.5.4", features = [ "native-tls", ], default-features = false } url = { version = "2.4.0", features = ["serde"] } +utoipa = { version = "5.3.1", features = ["preserve_order", "yaml"] } uuid = { version = "1.0.0", features = ["v4", "serde"] } variant_count = "1.1.0" walkdir = "2.3.3" diff --git a/api/src/events.rs b/api/src/events.rs index 768ff684cb5..9c1c86df742 100644 --- a/api/src/events.rs +++ b/api/src/events.rs @@ -169,7 +169,7 @@ impl EventsApi { page.limit(&latest_ledger_info)?, ledger_version, ) - .context(format!("Failed to find events by key {}", event_key)) + .context(format!("Failed to find events by key {event_key}")) .map_err(|err| { BasicErrorWith404::internal_with_code( err, diff --git a/api/src/tests/multisig_transactions_test.rs b/api/src/tests/multisig_transactions_test.rs index 9ec9158ddec..e255f44b3de 100644 --- a/api/src/tests/multisig_transactions_test.rs +++ b/api/src/tests/multisig_transactions_test.rs @@ -149,6 +149,7 @@ async fn test_multisig_transaction_to_update_owners() { .await; // There should be 4 owners now. + assert_multisig_tx_executed(&mut context, multisig_account, add_owners_payload, 1).await; assert_owners(&context, multisig_account, vec![ owner_account_1.address(), owner_account_2.address(), @@ -182,6 +183,7 @@ async fn test_multisig_transaction_to_update_owners() { .execute_multisig_transaction(owner_account_1, multisig_account, 202) .await; // There should be 3 owners now that owner 4 has been kicked out. + assert_multisig_tx_executed(&mut context, multisig_account, remove_owners_payload, 2).await; assert_owners(&context, multisig_account, vec![ owner_account_1.address(), owner_account_2.address(), diff --git a/api/src/tests/transactions_test.rs b/api/src/tests/transactions_test.rs index 18cf2c6cee9..3f07b26b65f 100644 --- a/api/src/tests/transactions_test.rs +++ b/api/src/tests/transactions_test.rs @@ -19,7 +19,7 @@ use aptos_types::{ authenticator::{AuthenticationKey, TransactionAuthenticator}, EntryFunction, Script, SignedTransaction, }, - utility_coin::{SupraCoinType, CoinType}, + utility_coin::{CoinType, SupraCoinType}, }; use move_core_types::{ identifier::Identifier, diff --git a/api/src/transactions.rs b/api/src/transactions.rs index 9041e3b5561..7a5cdc0cd4a 100644 --- a/api/src/transactions.rs +++ b/api/src/transactions.rs @@ -41,7 +41,7 @@ use aptos_types::{ TransactionPayload, TransactionPayloadInner, }, vm_status::StatusCode, - SupraCoinType, CoinType, + CoinType, SupraCoinType, }; use aptos_vm::{AptosSimulationVM, AptosVM}; use move_core_types::{ident_str, language_storage::ModuleId, vm_status::VMStatus}; @@ -1227,8 +1227,7 @@ impl TransactionsApi { ledger_info, params.automated_function(), )?; - - } + }, } } }, @@ -1605,7 +1604,7 @@ impl TransactionsApi { auto_payload.module_id(), &auto_payload.function().into(), ) - } + }, } } else { "Multisig::unknown".to_string() diff --git a/api/test-context/move/Move.toml b/api/test-context/move/Move.toml index f1088a211f4..b7d3ccad136 100644 --- a/api/test-context/move/Move.toml +++ b/api/test-context/move/Move.toml @@ -3,7 +3,7 @@ name = "TransactationTests" version = "0.0.0" [addresses] -entry_func_failed= "0x1" +entry_func_failed = "0x1" [dependencies] SupraFramework = { local = "../../../aptos-move/framework/supra-framework" } diff --git a/api/types/Cargo.toml b/api/types/Cargo.toml index b0ac815b786..ad427f9b0da 100644 --- a/api/types/Cargo.toml +++ b/api/types/Cargo.toml @@ -35,6 +35,7 @@ poem-openapi = { workspace = true } poem-openapi-derive = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } +sha3 = { workspace = true } [package.metadata.cargo-machete] ignored = ["async-trait", "poem", "poem-openapi-derive"] diff --git a/api/types/src/convert.rs b/api/types/src/convert.rs index f082f4bcd50..2b26a46a945 100644 --- a/api/types/src/convert.rs +++ b/api/types/src/convert.rs @@ -3,18 +3,16 @@ // Parts of the project are originally copyright © Meta Platforms, Inc. // SPDX-License-Identifier: Apache-2.0 -use crate::transaction::{ - AutomationRegistrationParams, AutomationRegistrationParamsV1, AutomationRegistrationParamsV2, -}; use crate::{ transaction::{ - BlockEpilogueTransaction, BlockMetadataTransaction, DecodedTableData, DeleteModule, - DeleteResource, DeleteTableItem, DeletedTableData, MultisigPayload, - MultisigTransactionPayload, StateCheckpointTransaction, UserTransactionRequestInner, - WriteModule, WriteResource, WriteTableItem, + AutomationRegistrationParams, AutomationRegistrationParamsV1, + AutomationRegistrationParamsV2, BlockEpilogueTransaction, BlockMetadataTransaction, + DecodedTableData, DeleteModule, DeleteResource, DeleteTableItem, DeletedTableData, + MultisigPayload, MultisigTransactionPayload, StateCheckpointTransaction, + UserTransactionRequestInner, WriteModule, WriteResource, WriteTableItem, }, view::{ViewFunction, ViewRequest}, - Address, Bytecode, DirectWriteSet, EntryFunctionId, EntryFunctionPayload, Event, + Address, Bytecode, DirectWriteSet, EntryFunctionId, EntryFunctionPayload, EventV1, EventV2, HexEncodedBytes, MoveFunction, MoveModuleBytecode, MoveResource, MoveScriptBytecode, MoveType, MoveValue, PendingTransaction, ResourceGroup, ScriptPayload, ScriptWriteSet, SubmitTransactionRequest, Transaction, TransactionInfo, TransactionOnChainData, @@ -25,10 +23,6 @@ use aptos_crypto::{hash::CryptoHash, HashValue}; use aptos_logger::{sample, sample::SampleRate}; use aptos_resource_viewer::AptosValueAnnotator; use aptos_storage_interface::DbReader; -use aptos_types::transaction::automation::RegistrationParams; -use aptos_types::transaction::Transaction::{ - AutomationRegistryTransaction, SystemAutomatedTransaction, -}; use aptos_types::{ access_path::{AccessPath, Path}, chain_id::ChainId, @@ -40,8 +34,11 @@ use aptos_types::{ StateView, }, transaction::{ + automation::RegistrationParams, BlockEndInfo, EntryFunction, ExecutionStatus, Multisig, RawTransaction, Script, - SignedTransaction, TransactionAuxiliaryData, + SignedTransaction, + Transaction::{AutomationRegistryTransaction, SystemAutomatedTransaction}, + TransactionAuxiliaryData, }, vm::module_metadata::get_metadata, vm_status::AbortLocation, @@ -147,11 +144,7 @@ impl<'a, S: StateView> MoveConverter<'a, S> { bytes: &[u8], ) -> Result> { let resources_with_tag: Vec<(StructTag, Vec)> = bcs::from_bytes::(bytes) - .map(|map| { - map.into_iter() - .map(|(key, value)| (key, value)) - .collect::>() - })?; + .map(|map| map.into_iter().collect::>())?; resources_with_tag .iter() @@ -727,7 +720,18 @@ impl<'a, S: StateView> MoveConverter<'a, S> { })) } - pub fn try_into_events(&self, events: &[ContractEvent]) -> Result> { + pub fn try_into_events(&self, events: &[ContractEvent]) -> Result> { + let mut ret = vec![]; + for event in events { + let data = self + .inner + .view_value(event.type_tag(), event.event_data())?; + ret.push((event, MoveValue::try_from(data)?.json()?).into()); + } + Ok(ret) + } + + pub fn try_into_v2_events(&self, events: &[ContractEvent]) -> Result> { let mut ret = vec![]; for event in events { let data = self @@ -920,7 +924,9 @@ impl<'a, S: StateView> MoveConverter<'a, S> { entry_func_payload, )?), MultisigTransactionPayload::AutomationRegistrationPayload(params) => { - Executable::AutomationRegistration(self.try_into_automation_registration_parameters(params)?) + Executable::AutomationRegistration( + self.try_into_automation_registration_parameters(params)?, + ) }, } } else { diff --git a/api/types/src/lib.rs b/api/types/src/lib.rs index e1258f8b0ec..a19710d76df 100644 --- a/api/types/src/lib.rs +++ b/api/types/src/lib.rs @@ -47,7 +47,7 @@ pub use table::{RawTableItemRequest, TableItemRequest}; pub use transaction::{ AbstractionSignature, AccountSignature, BlockMetadataTransaction, DeleteModule, DeleteResource, DeleteTableItem, DirectWriteSet, Ed25519Signature, EncodeSubmissionRequest, - EntryFunctionPayload, Event, FeePayerSignature, GasEstimation, GasEstimationBcs, + EntryFunctionPayload, EventV1, EventV2, FeePayerSignature, GasEstimation, GasEstimationBcs, GenesisPayload, GenesisTransaction, MultiAgentSignature, MultiEd25519Signature, MultiKeySignature, MultisigPayload, MultisigTransactionPayload, NoAccountSignature, PendingTransaction, PublicKey, ScriptPayload, ScriptWriteSet, Signature, SingleKeySignature, diff --git a/api/types/src/transaction.rs b/api/types/src/transaction.rs index 379f57d9a34..96e34753693 100755 --- a/api/types/src/transaction.rs +++ b/api/types/src/transaction.rs @@ -8,7 +8,7 @@ use crate::{ MoveModuleBytecode, MoveModuleId, MoveResource, MoveScriptBytecode, MoveStructTag, MoveType, MoveValue, VerifyInput, VerifyInputWithRecursion, U64, }; -use anyhow::{bail, Context as AnyhowContext, Result}; +use anyhow::{anyhow, bail, Context as AnyhowContext, Error as AnyhowError, Result}; use aptos_crypto::{ ed25519::{self, Ed25519PublicKey, ED25519_PUBLIC_KEY_LENGTH, ED25519_SIGNATURE_LENGTH}, multi_ed25519::{self, MultiEd25519PublicKey, BITMAP_NUM_OF_BYTES, MAX_NUM_OF_KEYS}, @@ -22,7 +22,7 @@ use aptos_types::{ block_metadata::BlockMetadata, block_metadata_ext::BlockMetadataExt, contract_event::{ContractEvent, EventWithVersion}, - dkg::{DKGTranscript, DKGTranscriptMetadata}, + dkg::{transactions::DKGTransactionData, DKGTranscript, DKGTranscriptMetadata}, function_info::FunctionInfo, jwks::{jwk::JWK, ProviderJWKs, QuorumCertifiedUpdate}, keyless, @@ -41,6 +41,7 @@ use once_cell::sync::Lazy; use poem_openapi::{Object, Union}; use poem_openapi_derive::Enum; use serde::{Deserialize, Serialize}; +use sha3::{digest::FixedOutput, Digest, Keccak256}; use std::{ boxed::Box, convert::{From, Into, TryFrom, TryInto}, @@ -67,6 +68,7 @@ static DUMMY_SEQUENCE_NUMBER: Lazy = Lazy::new(|| U64::from(0)); /// This is a combination enum of an onchain transaction and a pending transaction. /// When the transaction is still in mempool, it will be pending. If it's been committed to the /// chain, it will show up as OnChain. +#[allow(clippy::large_enum_variant)] #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub enum TransactionData { /// A committed transaction @@ -319,7 +321,7 @@ impl &SignedTransaction, TransactionInfo, TransactionPayload, - Vec, + Vec, u64, )> for Transaction { @@ -328,7 +330,7 @@ impl &SignedTransaction, TransactionInfo, TransactionPayload, - Vec, + Vec, u64, ), ) -> Self { @@ -346,7 +348,7 @@ impl &UserAutomatedTransaction, TransactionInfo, TransactionPayload, - Vec, + Vec, u64, )> for Transaction { @@ -355,7 +357,7 @@ impl &UserAutomatedTransaction, TransactionInfo, TransactionPayload, - Vec, + Vec, u64, ), ) -> Self { @@ -381,8 +383,8 @@ impl } } -impl From<(TransactionInfo, WriteSetPayload, Vec)> for Transaction { - fn from((info, payload, events): (TransactionInfo, WriteSetPayload, Vec)) -> Self { +impl From<(TransactionInfo, WriteSetPayload, Vec)> for Transaction { + fn from((info, payload, events): (TransactionInfo, WriteSetPayload, Vec)) -> Self { Transaction::GenesisTransaction(GenesisTransaction { info, payload: GenesisPayload::WriteSetPayload(payload), @@ -479,7 +481,7 @@ pub struct UserTransaction { #[oai(flatten)] pub request: UserTransactionRequest, /// Events generated by the transaction - pub events: Vec, + pub events: Vec, pub timestamp: U64, } @@ -493,7 +495,7 @@ pub struct AutomatedTransaction { #[oai(flatten)] pub meta: AutomatedTaskMeta, /// Events generated by the transaction - pub events: Vec, + pub events: Vec, pub timestamp: U64, } @@ -659,7 +661,7 @@ pub struct GenesisTransaction { pub info: TransactionInfo, pub payload: GenesisPayload, /// Events emitted during genesis - pub events: Vec, + pub events: Vec, } /// A block metadata transaction @@ -675,7 +677,7 @@ pub struct BlockMetadataTransaction { pub epoch: U64, pub round: U64, /// The events emitted at the block creation - pub events: Vec, + pub events: Vec, /// Previous block votes pub previous_block_votes_bitvec: Vec, pub proposer: Address, @@ -729,7 +731,7 @@ impl BlockMetadataTransaction { pub fn from_internal( internal: BlockMetadata, info: TransactionInfo, - events: Vec, + events: Vec, ) -> Self { Self { info, @@ -748,7 +750,7 @@ impl BlockMetadataTransaction { pub fn from_internal_ext( internal: BlockMetadataExt, info: TransactionInfo, - events: Vec, + events: Vec, ) -> Self { Self { info, @@ -782,6 +784,7 @@ impl BlockMetadataTransaction { )] pub enum ValidatorTransaction { ObservedJwkUpdate(JWKUpdateTransaction), + Dkg(DKGTransaction), DkgResult(DKGResultTransaction), } @@ -792,6 +795,7 @@ impl ValidatorTransaction { "validator_transaction__observed_jwk_update" }, ValidatorTransaction::DkgResult(_) => "validator_transaction__dkg_result", + ValidatorTransaction::Dkg(_) => "validator_transaction__dkg", } } @@ -799,6 +803,7 @@ impl ValidatorTransaction { match self { ValidatorTransaction::ObservedJwkUpdate(t) => &t.info, ValidatorTransaction::DkgResult(t) => &t.info, + ValidatorTransaction::Dkg(t) => &t.info, } } @@ -806,6 +811,7 @@ impl ValidatorTransaction { match self { ValidatorTransaction::ObservedJwkUpdate(t) => &mut t.info, ValidatorTransaction::DkgResult(t) => &mut t.info, + ValidatorTransaction::Dkg(t) => &mut t.info, } } @@ -813,13 +819,15 @@ impl ValidatorTransaction { match self { ValidatorTransaction::ObservedJwkUpdate(t) => t.timestamp, ValidatorTransaction::DkgResult(t) => t.timestamp, + ValidatorTransaction::Dkg(t) => t.timestamp, } } - pub fn events(&self) -> &[Event] { + pub fn events(&self) -> &[EventV1] { match self { ValidatorTransaction::ObservedJwkUpdate(t) => &t.events, ValidatorTransaction::DkgResult(t) => &t.events, + ValidatorTransaction::Dkg(t) => &t.events, } } } @@ -828,7 +836,7 @@ impl From<( aptos_types::validator_txn::ValidatorTransaction, TransactionInfo, - Vec, + Vec, u64, )> for ValidatorTransaction { @@ -836,11 +844,19 @@ impl (txn, info, events, timestamp): ( aptos_types::validator_txn::ValidatorTransaction, TransactionInfo, - Vec, + Vec, u64, ), ) -> Self { match txn { + aptos_types::validator_txn::ValidatorTransaction::DKG(dkg_transaction_data) => { + Self::Dkg(DKGTransaction { + info, + events, + timestamp: U64::from(timestamp), + dkg_transaction_data: dkg_transaction_data.into(), + }) + }, aptos_types::validator_txn::ValidatorTransaction::DKGResult(dkg_transcript) => { Self::DkgResult(DKGResultTransaction { info, @@ -866,7 +882,7 @@ pub struct JWKUpdateTransaction { #[serde(flatten)] #[oai(flatten)] pub info: TransactionInfo, - pub events: Vec, + pub events: Vec, pub timestamp: U64, pub quorum_certified_update: ExportedQuorumCertifiedUpdate, } @@ -938,19 +954,19 @@ pub struct DKGResultTransaction { #[serde(flatten)] #[oai(flatten)] pub info: TransactionInfo, - pub events: Vec, + pub events: Vec, pub timestamp: U64, - pub dkg_transcript: ExportedDKGTranscript, + pub dkg_transcript: ExportedDKGResultTranscript, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Object)] -pub struct ExportedDKGTranscript { +pub struct ExportedDKGResultTranscript { pub epoch: U64, pub author: Address, pub payload: HexEncodedBytes, } -impl From for ExportedDKGTranscript { +impl From for ExportedDKGResultTranscript { fn from(value: DKGTranscript) -> Self { let DKGTranscript { metadata, @@ -965,9 +981,56 @@ impl From for ExportedDKGTranscript { } } +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Object)] +pub struct ExportedDKGTransactionData { + /// The epoch number for the dkg + pub epoch: U64, + /// The author of the dkg transaction + pub author: Address, + /// The bls multi signature of the clan committee certifying the payload of the transaction + pub bls_aggregate_signature: Vec, + /// indices of the clan committee nodes that signed the bls multisignature + pub signer_indices_clan_committee: Vec, + /// type of the dkg transaction: (DKGMeta = 0), (PublicKeyShares = 1) + pub transaction_type: u8, + /// raw serialized payload of the transaction + pub payload: HexEncodedBytes, +} + +impl From for ExportedDKGTransactionData { + fn from(value: DKGTransactionData) -> Self { + let epoch = *value.metadata().epoch(); + let author = *value.metadata().author(); + let bls_aggregate_signature = value.metadata().bls_aggregate_signature().clone(); + let signer_indices_clan_committee = + value.metadata().signer_indices_clan_committee().clone(); + let transaction_type = value.metadata().transaction_type().clone(); + let transcript_bytes = value.data_bytes().clone(); + + Self { + epoch: epoch.into(), + author: author.into(), + bls_aggregate_signature: bls_aggregate_signature.into(), + signer_indices_clan_committee: signer_indices_clan_committee.into(), + payload: HexEncodedBytes::from(transcript_bytes), + transaction_type: transaction_type as u8, + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Object)] +pub struct DKGTransaction { + #[serde(flatten)] + #[oai(flatten)] + info: TransactionInfo, + events: Vec, + timestamp: U64, + pub dkg_transaction_data: ExportedDKGTransactionData, +} + /// An event from a transaction #[derive(Clone, Debug, Deserialize, Eq, Object, PartialEq, Serialize)] -pub struct Event { +pub struct EventV1 { // The globally unique identifier of this event stream. pub guid: EventGuid, // The sequence number of the event @@ -977,27 +1040,117 @@ pub struct Event { pub typ: MoveType, /// The JSON representation of the event pub data: serde_json::Value, + /// The hash of the event, derived from `keccak256`. + /// + /// TODO: Yes, you are correct—this is a hack that saves us from making a large number of changes + /// in the `rpc_node` just to support `EventV2`. Please do not take this hack lightly; take a + /// moment to think about the amount of work it actually saves. + /// + /// After a clear-cut refactor in `api-types` in `smr-moonshot`, we should be in a position to + /// remove this hacky solution. + #[serde(skip)] + #[oai(skip)] + pub hash: Option, } -impl From<(&ContractEvent, serde_json::Value)> for Event { +impl From<(&ContractEvent, serde_json::Value)> for EventV1 { fn from((event, data): (&ContractEvent, serde_json::Value)) -> Self { + let mut hasher = Keccak256::new(); + hasher.update(event.as_bytes_for_hash()); + let mut hash_bytes: [u8; 32] = [0u8; 32]; + hasher.finalize_into((&mut hash_bytes).into()); + let hash = Some(HashValue(aptos_crypto::HashValue::new(hash_bytes))); + match event { ContractEvent::V1(v1) => Self { guid: (*v1.key()).into(), sequence_number: v1.sequence_number().into(), typ: v1.type_tag().into(), data, + hash, }, ContractEvent::V2(v2) => Self { guid: *DUMMY_GUID, sequence_number: *DUMMY_SEQUENCE_NUMBER, typ: v2.type_tag().into(), data, + hash, }, } } } +/// An event from a transaction with it's hash. +/// This type is a v2 of [EventV1] with the hash. +/// +/// The `hash` field is computed by: +/// 1. Encoding the `event` structure using `as_bytes_for_hash` method of [`ContractEvent`]. +/// 2. Hashing the resulting byte array using the `Keccak-256`. +// Note: For API types versioning, our team follows a full-clone approach over composition +// due to its flexibility. Therefore, a full clone is used here instead of composition. +#[derive(Clone, Debug, Deserialize, Eq, Object, PartialEq, Serialize)] +pub struct EventV2 { + // The globally unique identifier of this event stream. + pub guid: EventGuid, + // The sequence number of the event + pub sequence_number: U64, + #[serde(rename = "type")] + #[oai(rename = "type")] + pub typ: MoveType, + /// The JSON representation of the event + pub data: serde_json::Value, + /// The hash of the event, derived from `keccak256`. + pub hash: HashValue, +} + +impl From<(&ContractEvent, serde_json::Value)> for EventV2 { + fn from((event, data): (&ContractEvent, serde_json::Value)) -> Self { + let mut hasher = Keccak256::new(); + hasher.update(event.as_bytes_for_hash()); + let mut hash_bytes: [u8; 32] = [0u8; 32]; + hasher.finalize_into((&mut hash_bytes).into()); + let hash = HashValue(aptos_crypto::HashValue::new(hash_bytes)); + + match event { + ContractEvent::V1(v1) => Self { + guid: (*v1.key()).into(), + sequence_number: v1.sequence_number().into(), + typ: v1.type_tag().into(), + data, + hash, + }, + ContractEvent::V2(v2) => Self { + guid: *DUMMY_GUID, + sequence_number: *DUMMY_SEQUENCE_NUMBER, + typ: v2.type_tag().into(), + data, + hash, + }, + } + } +} + +impl TryFrom for EventV2 { + type Error = AnyhowError; + + fn try_from(event_v1: EventV1) -> Result { + let EventV1 { + guid, + sequence_number, + typ, + data, + hash, + } = event_v1; + Ok(Self { + guid, + sequence_number, + typ, + data, + hash: hash.ok_or(anyhow!("Event hash is missing in `EventV1`"))?, + }) + } +} + /// An event from a transaction with a version #[derive(Clone, Debug, Deserialize, Eq, Object, PartialEq, Serialize)] pub struct VersionedEvent { @@ -1187,6 +1340,7 @@ impl AutomationRegistrationParams { }; Some(params_v1) } + pub fn into_v2(self) -> Option { let AutomationRegistrationParams::V2(params_v2) = self else { return None; @@ -1306,7 +1460,7 @@ pub struct ScriptWriteSet { #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Object)] pub struct DirectWriteSet { pub changes: Vec, - pub events: Vec, + pub events: Vec, } /// A final state change of a transaction on a resource or module @@ -2581,8 +2735,8 @@ impl FromStr for TransactionId { impl fmt::Display for TransactionId { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Self::Hash(h) => write!(f, "hash({})", h), - Self::Version(v) => write!(f, "version({})", v), + Self::Hash(h) => write!(f, "hash({h})"), + Self::Version(v) => write!(f, "version({v})"), } } } diff --git a/aptos-move/aptos-debugger/src/aptos_debugger.rs b/aptos-move/aptos-debugger/src/aptos_debugger.rs index f396db16023..6f270f45c36 100644 --- a/aptos-move/aptos-debugger/src/aptos_debugger.rs +++ b/aptos-move/aptos-debugger/src/aptos_debugger.rs @@ -163,7 +163,7 @@ impl AptosDebugger { }, TransactionExecutableRef::AutomationRegistration(_) => { unimplemented!("not supported yet") - } + }, }; gas_profiler }, @@ -399,7 +399,9 @@ fn print_transaction_stats(sig_verified_txns: &[SignatureVerifiedTransaction], v ), Ok(TransactionExecutableRef::Script(_)) => "script".to_string(), Ok(TransactionExecutableRef::Empty) => "empty".to_string(), - Ok(TransactionExecutableRef::AutomationRegistration(_)) => "automation_registration".to_string(), + Ok(TransactionExecutableRef::AutomationRegistration(_)) => { + "automation_registration".to_string() + }, Err(e) => { panic!("deprecated transaction payload: {}", e) }, diff --git a/aptos-move/aptos-debugger/src/execute_pending_block.rs b/aptos-move/aptos-debugger/src/execute_pending_block.rs index 7eb8698c538..67a6ab28baf 100644 --- a/aptos-move/aptos-debugger/src/execute_pending_block.rs +++ b/aptos-move/aptos-debugger/src/execute_pending_block.rs @@ -70,13 +70,13 @@ impl Command { // "Getting block {:?} from {consensus_db_path:?}.", // self.block_id // ); - // let cmd = aptos_consensus::util::db_tool::Command { - // db_dir: consensus_db_path, - // block_id: self.block_id, - // }; - // cmd.dump_pending_txns()? + // let cmd = aptos_consensus::util::db_tool::Command { + // db_dir: consensus_db_path, + // block_id: self.block_id, + // }; + // cmd.dump_pending_txns()? // } - else { + else { unreachable!("Must provide one target."); }; diff --git a/aptos-move/aptos-gas-algebra/src/algebra.rs b/aptos-move/aptos-gas-algebra/src/algebra.rs index 2a317eb79ec..3a27496c0c4 100644 --- a/aptos-move/aptos-gas-algebra/src/algebra.rs +++ b/aptos-move/aptos-gas-algebra/src/algebra.rs @@ -20,7 +20,7 @@ pub type AbstractValueSizePerArg = GasQuantity>; pub enum GasUnit {} /// Unit of the Aptos network's native coin. -pub enum SUPRA {} +pub enum SUPRA {} /// Alternative unit of the Aptos network's native coin. 1 quant = 10^-8 Supra coins. pub enum Quant {} diff --git a/aptos-move/aptos-gas-calibration/src/measurements_helpers.rs b/aptos-move/aptos-gas-calibration/src/measurements_helpers.rs index 987cf91799d..85a0ff098b9 100644 --- a/aptos-move/aptos-gas-calibration/src/measurements_helpers.rs +++ b/aptos-move/aptos-gas-calibration/src/measurements_helpers.rs @@ -59,7 +59,7 @@ pub fn execute_module_txn( let sign_tx = account .transaction() .sequence_number(sequence_number) - .max_gas_amount(2_000_000) + .max_gas_amount(2_000_000_000) .gas_unit_price(200) .payload(payload) .sign(); diff --git a/aptos-move/aptos-gas-profiling/src/erased.rs b/aptos-move/aptos-gas-profiling/src/erased.rs index 2b3b58aa9fd..e9016658c08 100644 --- a/aptos-move/aptos-gas-profiling/src/erased.rs +++ b/aptos-move/aptos-gas-profiling/src/erased.rs @@ -297,7 +297,11 @@ impl StorageFees { TypeErasedStorageFees { total: self.total, - tree: Node::new_with_children("storage fees (SUPRA)", (Fee::zero(), Fee::zero()), nodes), + tree: Node::new_with_children( + "storage fees (SUPRA)", + (Fee::zero(), Fee::zero()), + nodes, + ), } } } diff --git a/aptos-move/aptos-gas-schedule-updator/src/lib.rs b/aptos-move/aptos-gas-schedule-updator/src/lib.rs index ea4184315f9..8d528243368 100644 --- a/aptos-move/aptos-gas-schedule-updator/src/lib.rs +++ b/aptos-move/aptos-gas-schedule-updator/src/lib.rs @@ -14,7 +14,6 @@ use aptos_gas_schedule::{ use aptos_package_builder::PackageBuilder; use aptos_types::on_chain_config::GasScheduleV2; use clap::Parser; -use move_core_types::account_address::AccountAddress; use move_model::{code_writer::CodeWriter, emit, emitln, model::Loc}; use std::path::{Path, PathBuf}; @@ -66,6 +65,7 @@ fn generate_script(gas_schedule: &GasScheduleV2) -> Result { emitln!(writer, "use supra_framework::supra_governance;"); emitln!(writer, "use supra_framework::gas_schedule;"); + emitln!(writer, "use std::vector;"); emitln!(writer); emitln!(writer, "fun main(proposal_id: u64) {"); @@ -73,8 +73,11 @@ fn generate_script(gas_schedule: &GasScheduleV2) -> Result { emitln!( writer, - "let framework_signer = supra_governance::supra_resolve(proposal_id, @{});\n", - AccountAddress::ONE, + "let framework_signer = supra_governance::resolve_supra_multi_step_proposal( + proposal_id, + @supra_framework, + vector::empty() + );\n" ); emit!(writer, "let gas_schedule_blob: vector = "); diff --git a/aptos-move/aptos-gas-schedule/src/gas_schedule/aptos_framework.rs b/aptos-move/aptos-gas-schedule/src/gas_schedule/aptos_framework.rs index bfb2b11796e..9d752dc45e2 100644 --- a/aptos-move/aptos-gas-schedule/src/gas_schedule/aptos_framework.rs +++ b/aptos-move/aptos-gas-schedule/src/gas_schedule/aptos_framework.rs @@ -8,7 +8,8 @@ use crate::{ gas_feature_versions::{RELEASE_V1_14, RELEASE_V1_8, RELEASE_V1_9_SKIPPED}, gas_schedule::NativeGasParameters, ver::gas_feature_versions::{ - RELEASE_V1_12, RELEASE_V1_13, RELEASE_V1_16_SUPRA_V1_6_0, RELEASE_V1_23, RELEASE_V1_26, RELEASE_V1_28, RELEASE_V1_16_SUPRA_V1_7_14 + RELEASE_V1_12, RELEASE_V1_13, RELEASE_V1_16_SUPRA_V1_6_0, RELEASE_V1_16_SUPRA_V1_7_14, + RELEASE_V1_16_SUPRA_V1_9_0, RELEASE_V1_23, RELEASE_V1_26, RELEASE_V1_28, }, }; use aptos_gas_algebra::{ @@ -324,6 +325,8 @@ crate::gas_schedule::macros::define_gas_parameters!( [transaction_context_entry_function_payload_per_byte_in_str: InternalGasPerByte, {RELEASE_V1_12.. => "transaction_context.entry_function_payload.per_abstract_memory_unit"}, 18], [transaction_context_multisig_payload_base: InternalGas, {RELEASE_V1_12.. => "transaction_context.multisig_payload.base"}, 735], [transaction_context_multisig_payload_per_byte_in_str: InternalGasPerByte, {RELEASE_V1_12.. => "transaction_context.multisig_payload.per_abstract_memory_unit"}, 18], + // Cost matches other fixed-size hash-return natives (get_txn_hash, sender, fee_payer, etc.) + [transaction_context_get_txn_consensus_hash_base: InternalGas, {RELEASE_V1_16_SUPRA_V1_9_0 .. => "transaction_context.get_transaction_consensus_hash.base"}, 735], [code_request_publish_base: InternalGas, "code.request_publish.base", 1838], [code_request_publish_per_byte: InternalGasPerByte, "code.request_publish.per_byte", 7], diff --git a/aptos-move/aptos-gas-schedule/src/gas_schedule/mod.rs b/aptos-move/aptos-gas-schedule/src/gas_schedule/mod.rs index e38b7e0878e..d5a69f786b3 100644 --- a/aptos-move/aptos-gas-schedule/src/gas_schedule/mod.rs +++ b/aptos-move/aptos-gas-schedule/src/gas_schedule/mod.rs @@ -9,6 +9,7 @@ mod instr; mod macros; mod misc; mod move_stdlib; +mod supra_stdlib; mod table; mod transaction; @@ -16,6 +17,7 @@ pub use aptos_framework::AptosFrameworkGasParameters; pub use instr::InstructionGasParameters; pub use misc::{AbstractValueSizeGasParameters, MiscGasParameters}; pub use move_stdlib::MoveStdlibGasParameters; +pub use supra_stdlib::SupraStdlibGasParameters; pub use table::TableGasParameters; pub use transaction::TransactionGasParameters; @@ -29,6 +31,7 @@ pub mod gas_params { use super::*; pub use aptos_framework::gas_params as aptos_framework; pub use move_stdlib::gas_params as move_stdlib; + pub use supra_stdlib::gas_params as supra_stdlib; pub use table::gas_params as table; } } @@ -140,6 +143,7 @@ impl InitialGasSchedule for VMGasParameters { #[derive(Debug, Clone)] pub struct NativeGasParameters { pub move_stdlib: MoveStdlibGasParameters, + pub supra_stdlib: SupraStdlibGasParameters, pub table: TableGasParameters, pub aptos_framework: AptosFrameworkGasParameters, } @@ -154,6 +158,10 @@ impl FromOnChainGasSchedule for NativeGasParameters { gas_schedule, feature_version, )?, + supra_stdlib: FromOnChainGasSchedule::from_on_chain_gas_schedule( + gas_schedule, + feature_version, + )?, table: FromOnChainGasSchedule::from_on_chain_gas_schedule( gas_schedule, feature_version, @@ -170,6 +178,7 @@ impl ToOnChainGasSchedule for NativeGasParameters { fn to_on_chain_gas_schedule(&self, feature_version: u64) -> Vec<(String, u64)> { let mut entries = self.move_stdlib.to_on_chain_gas_schedule(feature_version); entries.extend(self.table.to_on_chain_gas_schedule(feature_version)); + entries.extend(self.supra_stdlib.to_on_chain_gas_schedule(feature_version)); entries.extend( self.aptos_framework .to_on_chain_gas_schedule(feature_version), @@ -182,6 +191,7 @@ impl NativeGasParameters { pub fn zeros() -> Self { Self { move_stdlib: MoveStdlibGasParameters::zeros(), + supra_stdlib: SupraStdlibGasParameters::zeros(), table: TableGasParameters::zeros(), aptos_framework: AptosFrameworkGasParameters::zeros(), } @@ -192,6 +202,7 @@ impl InitialGasSchedule for NativeGasParameters { fn initial() -> Self { Self { move_stdlib: InitialGasSchedule::initial(), + supra_stdlib: InitialGasSchedule::initial(), table: InitialGasSchedule::initial(), aptos_framework: InitialGasSchedule::initial(), } diff --git a/aptos-move/aptos-gas-schedule/src/gas_schedule/supra_stdlib.rs b/aptos-move/aptos-gas-schedule/src/gas_schedule/supra_stdlib.rs new file mode 100644 index 00000000000..2c1423e801d --- /dev/null +++ b/aptos-move/aptos-gas-schedule/src/gas_schedule/supra_stdlib.rs @@ -0,0 +1,21 @@ +// Copyright (c) 2025 Supra. + +//! This module defines the gas parameters for Supra Stdlib. + +use crate::{ + gas_schedule::NativeGasParameters, ver::gas_feature_versions::RELEASE_V1_16_SUPRA_V1_8_0, +}; +use aptos_gas_algebra::{InternalGas, InternalGasPerArg}; + +crate::gas_schedule::macros::define_gas_parameters!( + SupraStdlibGasParameters, + "supra_stdlib", + NativeGasParameters => .supra_stdlib, + [ + // Note(Gas): this initial value is guesswork. + [class_groups_per_pubkey_deserialize: InternalGasPerArg, { RELEASE_V1_16_SUPRA_V1_8_0.. => "class.groups.per_pubkey_deserialize" }, 400684], + // Note(Gas): this initial value is guesswork. + [class_groups_pop: InternalGas, { RELEASE_V1_16_SUPRA_V1_8_0.. => "class.groups.pop" }, 206000000], + + ] +); diff --git a/aptos-move/aptos-gas-schedule/src/gas_schedule/transaction.rs b/aptos-move/aptos-gas-schedule/src/gas_schedule/transaction.rs index 5845c26e171..9e564518464 100644 --- a/aptos-move/aptos-gas-schedule/src/gas_schedule/transaction.rs +++ b/aptos-move/aptos-gas-schedule/src/gas_schedule/transaction.rs @@ -66,7 +66,7 @@ crate::gas_schedule::macros::define_gas_parameters!( [ max_price_per_gas_unit: FeePerGasUnit, "max_price_per_gas_unit", - 10_000_000_000 + 1_000_000_000 ], [ max_transaction_size_in_bytes: NumBytes, @@ -177,34 +177,34 @@ crate::gas_schedule::macros::define_gas_parameters!( [ legacy_storage_fee_per_state_slot_create: FeePerSlot, { 7..=13 => "storage_fee_per_state_slot_create", 14.. => "legacy_storage_fee_per_state_slot_create" }, - 50000, + 50000000, ], [ storage_fee_per_state_slot: FeePerSlot, { 14.. => "storage_fee_per_state_slot" }, - // 0.8 million SUPRA for 2 billion state slots - 40_000, + // 800 million SUPRA for 2 billion state slots + 40_000_000, ], [ legacy_storage_fee_per_excess_state_byte: FeePerByte, { 7..=13 => "storage_fee_per_excess_state_byte", 14.. => "legacy_storage_fee_per_excess_state_byte" }, - 50, + 50_000, ], [ storage_fee_per_state_byte: FeePerByte, { 14.. => "storage_fee_per_state_byte" }, - // 0.8 million SUPRA for 2 TB state bytes - 40, + // 800 million SUPRA for 2 TB state bytes + 40_000, ], [ legacy_storage_fee_per_event_byte: FeePerByte, { 7..=13 => "storage_fee_per_event_byte", 14.. => "legacy_storage_fee_per_event_byte" }, - 20, + 20_000, ], [ legacy_storage_fee_per_transaction_byte: FeePerByte, { 7..=13 => "storage_fee_per_transaction_byte", 14.. => "legacy_storage_fee_per_transaction_byte" }, - 20, + 20_000, ], [ max_execution_gas: InternalGas, @@ -229,12 +229,12 @@ crate::gas_schedule::macros::define_gas_parameters!( [ max_storage_fee: Fee, { 7.. => "max_storage_fee" }, - 2_0000_0000, // 2 SUPRA + 2_000_0000_0000, // 2000 SUPRA ], [ max_storage_fee_gov: Fee, { RELEASE_V1_13.. => "max_storage_fee.gov" }, - 2_0000_0000, + 2_000_0000_0000, ], [ dependency_per_module: InternalGas, diff --git a/aptos-move/aptos-gas-schedule/src/ver.rs b/aptos-move/aptos-gas-schedule/src/ver.rs index 8e22bd1b3f2..5599663790a 100644 --- a/aptos-move/aptos-gas-schedule/src/ver.rs +++ b/aptos-move/aptos-gas-schedule/src/ver.rs @@ -79,7 +79,7 @@ /// global operations. /// - V1 /// - TBA -pub const LATEST_GAS_FEATURE_VERSION: u64 = gas_feature_versions::RELEASE_V1_16_SUPRA_V1_7_14; +pub const LATEST_GAS_FEATURE_VERSION: u64 = gas_feature_versions::RELEASE_V1_34; pub mod gas_feature_versions { pub const RELEASE_V1_8: u64 = 11; @@ -95,20 +95,22 @@ pub mod gas_feature_versions { pub const RELEASE_V1_16_SUPRA_V1_5_1: u64 = 22; pub const RELEASE_V1_16_SUPRA_V1_6_0: u64 = 23; pub const RELEASE_V1_16_SUPRA_V1_7_14: u64 = 24; - pub const RELEASE_V1_18: u64 = 25; - pub const RELEASE_V1_19: u64 = 26; - pub const RELEASE_V1_20: u64 = 27; - pub const RELEASE_V1_21: u64 = 28; - pub const RELEASE_V1_22: u64 = 29; - pub const RELEASE_V1_23: u64 = 30; - pub const RELEASE_V1_24: u64 = 31; - pub const RELEASE_V1_26: u64 = 32; - pub const RELEASE_V1_27: u64 = 33; - pub const RELEASE_V1_28: u64 = 34; - pub const RELEASE_V1_29: u64 = 35; - pub const RELEASE_V1_30: u64 = 36; - pub const RELEASE_V1_31: u64 = 37; - pub const RELEASE_V1_32: u64 = 38; - pub const RELEASE_V1_33: u64 = 39; - pub const RELEASE_V1_34: u64 = 40; + pub const RELEASE_V1_16_SUPRA_V1_8_0: u64 = 25; + pub const RELEASE_V1_16_SUPRA_V1_9_0: u64 = 26; + pub const RELEASE_V1_18: u64 = 27; + pub const RELEASE_V1_19: u64 = 28; + pub const RELEASE_V1_20: u64 = 29; + pub const RELEASE_V1_21: u64 = 30; + pub const RELEASE_V1_22: u64 = 31; + pub const RELEASE_V1_23: u64 = 32; + pub const RELEASE_V1_24: u64 = 33; + pub const RELEASE_V1_26: u64 = 34; + pub const RELEASE_V1_27: u64 = 35; + pub const RELEASE_V1_28: u64 = 36; + pub const RELEASE_V1_29: u64 = 37; + pub const RELEASE_V1_30: u64 = 38; + pub const RELEASE_V1_31: u64 = 39; + pub const RELEASE_V1_32: u64 = 40; + pub const RELEASE_V1_33: u64 = 41; + pub const RELEASE_V1_34: u64 = 42; } diff --git a/aptos-move/aptos-release-builder/src/components/feature_flags.rs b/aptos-move/aptos-release-builder/src/components/feature_flags.rs index dc3dfdb4664..a7046e83d81 100644 --- a/aptos-move/aptos-release-builder/src/components/feature_flags.rs +++ b/aptos-move/aptos-release-builder/src/components/feature_flags.rs @@ -158,6 +158,10 @@ pub enum FeatureFlag { SupraRLPEncode, SupraDelegationPoolIdentity, SupraAutomationV2, + SupraBlsKeys, + SupraBcftCertificates, + SUPRA_DKG, + SupraTransactionInclusionProofs, } fn generate_features_blob(writer: &CodeWriter, data: &[u64]) { @@ -404,7 +408,7 @@ impl From for AptosFeatureFlag { AptosFeatureFlag::CALCULATE_TRANSACTION_FEE_FOR_DISTRIBUTION }, FeatureFlag::DistributeTransactionFee => AptosFeatureFlag::DISTRIBUTE_TRANSACTION_FEE, - FeatureFlag::SupraNativeAutomation => AptosFeatureFlag::SUPRA_NATIVE_AUTOMATION, + FeatureFlag::SupraNativeAutomation => AptosFeatureFlag::SUPRA_NATIVE_AUTOMATION, FeatureFlag::SupraEthTrie => AptosFeatureFlag::SUPRA_ETH_TRIE, FeatureFlag::SupraAutomationPayloadGasCheck => { AptosFeatureFlag::SUPRA_AUTOMATION_PAYLOAD_GAS_CHECK @@ -419,6 +423,12 @@ impl From for AptosFeatureFlag { AptosFeatureFlag::SUPRA_DELEGATION_POOL_IDENTITY }, FeatureFlag::SupraAutomationV2 => AptosFeatureFlag::SUPRA_AUTOMATION_V2, + FeatureFlag::SupraBlsKeys => AptosFeatureFlag::SUPRA_BLS_KEYS, + FeatureFlag::SupraBcftCertificates => AptosFeatureFlag::SUPRA_BCFT_CERTIFICATES, + FeatureFlag::SUPRA_DKG => AptosFeatureFlag::SUPRA_DKG, + FeatureFlag::SupraTransactionInclusionProofs => { + AptosFeatureFlag::SUPRA_TRANSACTIONS_INCLUSION_PROOFS + }, } } } @@ -592,7 +602,7 @@ impl From for FeatureFlag { FeatureFlag::CalculateTransactionFeeForDistribution }, AptosFeatureFlag::DISTRIBUTE_TRANSACTION_FEE => FeatureFlag::DistributeTransactionFee, - AptosFeatureFlag::SUPRA_NATIVE_AUTOMATION => FeatureFlag::SupraNativeAutomation, + AptosFeatureFlag::SUPRA_NATIVE_AUTOMATION => FeatureFlag::SupraNativeAutomation, AptosFeatureFlag::SUPRA_ETH_TRIE => FeatureFlag::SupraEthTrie, AptosFeatureFlag::SUPRA_AUTOMATION_PAYLOAD_GAS_CHECK => { FeatureFlag::SupraAutomationPayloadGasCheck @@ -607,6 +617,12 @@ impl From for FeatureFlag { FeatureFlag::SupraDelegationPoolIdentity }, AptosFeatureFlag::SUPRA_AUTOMATION_V2 => FeatureFlag::SupraAutomationV2, + AptosFeatureFlag::SUPRA_BLS_KEYS => FeatureFlag::SupraBlsKeys, + AptosFeatureFlag::SUPRA_BCFT_CERTIFICATES => FeatureFlag::SupraBcftCertificates, + AptosFeatureFlag::SUPRA_DKG => FeatureFlag::SUPRA_DKG, + AptosFeatureFlag::SUPRA_TRANSACTIONS_INCLUSION_PROOFS => { + FeatureFlag::SupraTransactionInclusionProofs + }, } } } diff --git a/aptos-move/aptos-release-builder/src/components/framework.rs b/aptos-move/aptos-release-builder/src/components/framework.rs index d4eb88ce466..55a9ec0124d 100644 --- a/aptos-move/aptos-release-builder/src/components/framework.rs +++ b/aptos-move/aptos-release-builder/src/components/framework.rs @@ -123,6 +123,7 @@ pub fn generate_upgrade_proposals( account, move_script_path.clone(), next_execution_hash_bytes, + todo!("function_name"), )?; } else if is_testnet { // If we're generating a single-step proposal on testnet diff --git a/aptos-move/aptos-release-builder/src/components/mod.rs b/aptos-move/aptos-release-builder/src/components/mod.rs index ff1f5769ccc..8b3ceac40c6 100644 --- a/aptos-move/aptos-release-builder/src/components/mod.rs +++ b/aptos-move/aptos-release-builder/src/components/mod.rs @@ -3,11 +3,12 @@ use self::framework::FrameworkReleaseConfig; use crate::{ - aptos_core_path, supra_framework_path, + aptos_core_path, components::{ feature_flags::Features, oidc_providers::OidcProviderOp, randomness_config::ReleaseFriendlyRandomnessConfig, }, + supra_framework_path, }; use anyhow::{anyhow, bail, Context, Result}; use aptos::governance::GenerateExecutionHash; diff --git a/aptos-move/aptos-release-builder/src/validate.rs b/aptos-move/aptos-release-builder/src/validate.rs index 9be2ef64176..daa6fc9662a 100644 --- a/aptos-move/aptos-release-builder/src/validate.rs +++ b/aptos-move/aptos-release-builder/src/validate.rs @@ -1,7 +1,7 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::{supra_framework_path, components::ProposalMetadata, ExecutionMode, ReleaseConfig}; +use crate::{components::ProposalMetadata, supra_framework_path, ExecutionMode, ReleaseConfig}; use anyhow::Result; use aptos::{ common::types::CliCommand, @@ -374,7 +374,7 @@ impl NetworkConfig { self.endpoint.as_str(), // Use the max gas unit for now. The simulate API sometimes cannot get the right gas estimate for proposals. "--max-gas", - "2000000", + "2000000000", ]; if let Some(api_key) = node_api_key.as_ref() { diff --git a/aptos-move/aptos-transaction-benchmarks/Cargo.toml b/aptos-move/aptos-transaction-benchmarks/Cargo.toml index f998721ce4d..8213e541add 100644 --- a/aptos-move/aptos-transaction-benchmarks/Cargo.toml +++ b/aptos-move/aptos-transaction-benchmarks/Cargo.toml @@ -21,7 +21,7 @@ aptos-language-e2e-tests = { workspace = true } aptos-logger = { workspace = true } aptos-metrics-core = { workspace = true } aptos-node-resource-metrics = { workspace = true } -aptos-push-metrics = { workspace = true } +aptos-push-metrics = { workspace = true } aptos-transaction-simulation = { workspace = true } aptos-types = { workspace = true } aptos-vm = { workspace = true } diff --git a/aptos-move/aptos-transactional-test-harness/src/aptos_test_harness.rs b/aptos-move/aptos-transactional-test-harness/src/aptos_test_harness.rs index f3508115f42..99fcf523c42 100644 --- a/aptos-move/aptos-transactional-test-harness/src/aptos_test_harness.rs +++ b/aptos-move/aptos-transactional-test-harness/src/aptos_test_harness.rs @@ -539,7 +539,7 @@ impl AptosTestAdapter<'_> { let txn = RawTransaction::new( aptos_test_root_address(), parameters.sequence_number, - aptos_cached_packages::aptos_stdlib::aptos_account_create_account(account_addr), + aptos_cached_packages::aptos_stdlib::supra_account_create_account(account_addr), parameters.max_gas_amount, parameters.gas_unit_price, parameters.expiration_timestamp_secs, diff --git a/aptos-move/aptos-vm-benchmarks/samples/do-nothing/Move.toml b/aptos-move/aptos-vm-benchmarks/samples/do-nothing/Move.toml index 6195bbabe73..3c407bc6e72 100644 --- a/aptos-move/aptos-vm-benchmarks/samples/do-nothing/Move.toml +++ b/aptos-move/aptos-vm-benchmarks/samples/do-nothing/Move.toml @@ -3,4 +3,4 @@ name = 'do-nothing' version = '1.0.0' [dependencies] SupraFramework = { local = "../../../framework/supra-framework" } -AptosStdlib = { local = "../../../framework/aptos-stdlib" } \ No newline at end of file +AptosStdlib = { local = "../../../framework/aptos-stdlib" } diff --git a/aptos-move/aptos-vm-benchmarks/src/helper.rs b/aptos-move/aptos-vm-benchmarks/src/helper.rs index de4f8d8c06f..34064eed7df 100644 --- a/aptos-move/aptos-vm-benchmarks/src/helper.rs +++ b/aptos-move/aptos-vm-benchmarks/src/helper.rs @@ -41,7 +41,7 @@ pub fn execute_module_txn( let sign_tx = account .transaction() .sequence_number(sequence_number) - .max_gas_amount(2_000_000) + .max_gas_amount(2_000_000_000) .gas_unit_price(200) .payload(payload) .sign(); diff --git a/aptos-move/aptos-vm-profiling/Cargo.toml b/aptos-move/aptos-vm-profiling/Cargo.toml index da05e3763f4..f4bcbae72f3 100644 --- a/aptos-move/aptos-vm-profiling/Cargo.toml +++ b/aptos-move/aptos-vm-profiling/Cargo.toml @@ -36,7 +36,7 @@ move-vm-types = { workspace = true } [[bin]] name = "main" -path = "src/main.rs" +path = "src/main.rs" [[bin]] name = "run-move" diff --git a/aptos-move/aptos-vm/Cargo.toml b/aptos-move/aptos-vm/Cargo.toml index 0d105d54c7b..7c632698b6c 100644 --- a/aptos-move/aptos-vm/Cargo.toml +++ b/aptos-move/aptos-vm/Cargo.toml @@ -20,7 +20,7 @@ aptos-block-partitioner = { workspace = true } aptos-crypto = { workspace = true } aptos-crypto-derive = { workspace = true } aptos-experimental-runtimes = { workspace = true } -aptos-framework = { workspace = true } +aptos-framework = { workspace = true } aptos-gas-algebra = { workspace = true } aptos-gas-meter = { workspace = true } aptos-gas-schedule = { workspace = true } @@ -41,6 +41,7 @@ bcs = { workspace = true } bytes = { workspace = true } claims = { workspace = true } crossbeam-channel = { workspace = true } +crypto = { workspace = true } derive_more = { workspace = true } fail = { workspace = true } futures = { workspace = true } @@ -74,6 +75,12 @@ test-case = { workspace = true } [features] default = [] -fuzzing = ["move-core-types/fuzzing", "move-binary-format/fuzzing", "move-vm-types/fuzzing", "aptos-framework/fuzzing", "aptos-types/fuzzing"] +fuzzing = [ + "move-core-types/fuzzing", + "move-binary-format/fuzzing", + "move-vm-types/fuzzing", + "aptos-framework/fuzzing", + "aptos-types/fuzzing", +] failpoints = ["fail/failpoints", "move-vm-runtime/failpoints"] testing = ["move-unit-test", "aptos-framework/testing"] diff --git a/aptos-move/aptos-vm/src/aptos_vm.rs b/aptos-move/aptos-vm/src/aptos_vm.rs index 0a7ae047efa..f2e7a7837c7 100644 --- a/aptos-move/aptos-vm/src/aptos_vm.rs +++ b/aptos-move/aptos-vm/src/aptos_vm.rs @@ -3,13 +3,14 @@ // Parts of the project are originally copyright © Meta Platforms, Inc. // SPDX-License-Identifier: Apache-2.0 -use crate::automated_transaction_processor::AutomatedTransactionProcessor; use crate::{ + automated_transaction_processor::AutomatedTransactionProcessor, + automation_registry_transaction_processor::AutomationRegistryTransactionProcessor, block_executor::{AptosTransactionOutput, AptosVMBlockExecutorWrapper}, counters::*, data_cache::{AsMoveResolver, StorageAdapter}, errors::{discarded_output, expect_only_successful_execution}, - gas::{check_gas, make_prod_gas_meter, ProdGasMeter}, + gas::{check_automation_task_gas, check_gas, make_prod_gas_meter, ProdGasMeter}, keyless_validation, move_vm_ext::{ session::user_transaction_sessions::{ @@ -36,8 +37,11 @@ use aptos_block_executor::{ txn_commit_hook::NoOpTransactionCommitHook, txn_provider::{default::DefaultTxnProvider, TxnProvider}, }; -use aptos_crypto::HashValue; -use aptos_framework::natives::code::PublishRequest; +use aptos_crypto::{ + bls12381::{PublicKey, Signature}, + HashValue, +}; +use aptos_framework::natives::{code::PublishRequest, randomness::RandomnessContext}; use aptos_gas_algebra::{Gas, GasQuantity, NumBytes, Quant}; use aptos_gas_meter::{AptosGasMeter, GasAlgebra}; use aptos_gas_schedule::{ @@ -48,7 +52,6 @@ use aptos_gas_schedule::{ use aptos_logger::{enabled, prelude::*, Level}; #[cfg(any(test, feature = "testing"))] use aptos_types::state_store::StateViewId; -use aptos_types::transaction::automation::{AutomationTaskType, RegistrationParams}; use aptos_types::{ account_config::{self, new_block_event_key, AccountResource}, block_executor::{ @@ -63,17 +66,22 @@ use aptos_types::{ block_metadata_ext::{BlockMetadataExt, BlockMetadataWithRandomness}, chain_id::ChainId, contract_event::ContractEvent, + dkg::{ + state::DKGState, + transactions::{DKGTransactionData, DKGTransactionType}, + }, fee_statement::FeeStatement, function_info::FunctionInfo, move_utils::as_move_value::AsMoveValue, on_chain_config::{ - ApprovedExecutionHashes, ConfigStorage, FeatureFlag, Features, OnChainConfig, - TimedFeatureFlag, TimedFeatures, + new_epoch_event_key, ApprovedExecutionHashes, ConfigStorage, ConfigurationResource, + FeatureFlag, Features, OnChainConfig, TimedFeatureFlag, TimedFeatures, }, randomness::Randomness, state_store::{state_key::StateKey, StateView, TStateView}, transaction::{ authenticator::{AbstractionAuthData, AnySignature, AuthenticationProof}, + automation::{AutomationTaskType, RegistrationParams}, block_epilogue::{BlockEpiloguePayload, FeeDistribution}, signature_verified_transaction::SignatureVerifiedTransaction, BlockOutput, EntryFunction, ExecutionError, ExecutionStatus, ModuleBundle, @@ -140,7 +148,7 @@ use move_vm_runtime::{ check_type_tag_dependencies_and_charge_gas, logging::expect_no_verification_errors, module_traversal::{TraversalContext, TraversalStorage}, - ModuleStorage, RuntimeEnvironment, WithRuntimeEnvironment, + LoadedFunction, ModuleStorage, RuntimeEnvironment, WithRuntimeEnvironment, }; use move_vm_types::gas::{GasMeter, UnmeteredGasMeter}; use num_cpus; @@ -152,8 +160,6 @@ use std::{ sync::Arc, }; -use crate::gas::check_automation_task_gas; - static EXECUTION_CONCURRENCY_LEVEL: OnceCell = OnceCell::new(); static NUM_EXECUTION_SHARD: OnceCell = OnceCell::new(); static NUM_PROOF_READING_THREADS: OnceCell = OnceCell::new(); @@ -184,7 +190,6 @@ macro_rules! unwrap_or_discard { }; } -use crate::automation_registry_transaction_processor::AutomationRegistryTransactionProcessor; pub(crate) use unwrap_or_discard; pub(crate) struct SerializedSigners { @@ -819,6 +824,7 @@ impl AptosVM { gas_meter: &mut impl GasMeter, traversal_context: &mut TraversalContext<'a>, serialized_script: &'a Script, + is_approved_gov_script: bool, ) -> Result<(), VMStatus> { if !self .features() @@ -870,11 +876,28 @@ impl AptosVM { self.features().is_enabled(FeatureFlag::STRUCT_CONSTRUCTORS), )?; + if is_approved_gov_script { + // If governance is honest then it will not attempt test-and-abort attacks to abuse + // randomness. + self.mark_unbiasable(session); + } + + if is_approved_gov_script { + // If governance is honest then it will not attempt test-and-abort attacks to abuse + // randomness. + self.mark_unbiasable(session); + } + session.execute_loaded_function(func, args, gas_meter, traversal_context, code_storage)?; Ok(()) } - pub(crate) fn validate_and_execute_entry_function( + // Loads the entry function from the module store and validates its arguments, + // returning the resolved function handle and the serialized validated args. + // Separated from execution so callers can apply different error handling to + // pre-execution failures (e.g. the automation path tags them distinctly from + // transient execution failures). + pub(crate) fn load_and_validate_entry_function( &self, module_storage: &impl AptosModuleStorage, session: &mut SessionExt, @@ -882,7 +905,7 @@ impl AptosVM { gas_meter: &mut impl AptosGasMeter, traversal_context: &mut TraversalContext, entry_fn: &EntryFunction, - ) -> Result<(), VMStatus> { + ) -> Result<(LoadedFunction, Vec>), VMStatus> { // Note: Feature gating is needed here because the traversal of the dependencies could // result in shallow-loading of the modules and therefore subtle changes in // the error semantics. @@ -945,6 +968,27 @@ impl AptosVM { struct_constructors_enabled, )?; + Ok((function, args)) + } + + pub(crate) fn validate_and_execute_entry_function( + &self, + module_storage: &impl AptosModuleStorage, + session: &mut SessionExt, + serialized_signers: &SerializedSigners, + gas_meter: &mut impl AptosGasMeter, + traversal_context: &mut TraversalContext, + entry_fn: &EntryFunction, + ) -> Result<(), VMStatus> { + let (function, args) = self.load_and_validate_entry_function( + module_storage, + session, + serialized_signers, + gas_meter, + traversal_context, + entry_fn, + )?; + // Execute the function. The function also must be an entry function! function.is_entry_or_err()?; session.execute_loaded_function( @@ -969,6 +1013,7 @@ impl AptosVM { executable: TransactionExecutableRef<'a>, // TODO[Orderless]: Check what's the right lifetime to use here. log_context: &AdapterLogSchema, change_set_configs: &ChangeSetConfigs, + is_approved_gov_script: bool, ) -> Result<(VMStatus, VMOutput), VMStatus> { fail_point!("aptos_vm::execute_script_or_entry_function", |_| { Err(VMStatus::Error { @@ -993,6 +1038,7 @@ impl AptosVM { gas_meter, traversal_context, script, + is_approved_gov_script, ) })?; }, @@ -1007,7 +1053,7 @@ impl AptosVM { entry_fn, ) })?; - } + }, TransactionExecutableRef::AutomationRegistration(registration_params) => { session.execute(|session| { self.validate_and_execute_automation_registration( @@ -1070,22 +1116,22 @@ impl AptosVM { sender: AccountAddress, registration_params: &RegistrationParams, ) -> Result<(), VMStatus> { - self.validate_automated_function( - session, - code_storage, - serialized_signers, - registration_params.automated_function(), - )?; + self.validate_automated_function( + session, + code_storage, + serialized_signers, + registration_params.automated_function(), + )?; - self.execute_automation_registration( - session, - code_storage, - gas_meter, - traversal_context, - sender, - registration_params, - txn_data, - )?; + self.execute_automation_registration( + session, + code_storage, + gas_meter, + traversal_context, + sender, + registration_params, + txn_data, + )?; Ok(()) } @@ -1111,10 +1157,11 @@ impl AptosVM { module_id.name(), )])?; } - - - let args = registration_params - .serialized_args_with_sender_and_parent_hash(sender, txn_metadata.txn_app_hash.clone(), self.features()); + let args = registration_params.serialized_args_with_sender_and_parent_hash( + sender, + txn_metadata.txn_consensus_hash.clone(), + self.features(), + ); session.execute_function_bypass_visibility( registration_params.module_id(), @@ -1123,13 +1170,16 @@ impl AptosVM { args, gas_meter, traversal_context, - module_storage + module_storage, )?; Ok(()) } /// Checks inner payload/entry function of automation registration transaction to be valid. - fn validate_automated_function( + /// + /// Exposed as `pub(crate)` so that `AptosVMViewer` can call it for pre-flight validation of + /// automation tasks that were registered without type-checking (e.g. `register_without_validation`). + pub(crate) fn validate_automated_function( &self, session: &mut SessionExt, module_storage: &impl AptosModuleStorage, @@ -1221,7 +1271,6 @@ impl AptosVM { )) } - // Execute a multisig transaction: // 1. Obtain the payload of the transaction to execute. This could have been stored on chain // when the multisig transaction was created. @@ -1289,10 +1338,10 @@ impl AptosVM { ); return Ok((s, discarded_output(StatusCode::FEATURE_UNDER_GATING))); }, - TransactionExecutableRef::AutomationRegistration(registration_params) => { - bcs::to_bytes(&MultisigTransactionPayload::AutomationRegistration(registration_params.clone())) - .map_err(|_| invariant_violation_error())? - } + TransactionExecutableRef::AutomationRegistration(registration_params) => bcs::to_bytes( + &MultisigTransactionPayload::AutomationRegistration(registration_params.clone()), + ) + .map_err(|_| invariant_violation_error())?, }; // Failures here will be propagated back. let payload_bytes: Vec> = session @@ -1426,10 +1475,10 @@ impl AptosVM { payload: &MultisigTransactionPayload, change_set_configs: &ChangeSetConfigs, ) -> Result { - - let multisig_serialized_signer = SerializedSigners::new(vec![serialized_signer(&multisig_address)], None); + let multisig_serialized_signer = + SerializedSigners::new(vec![serialized_signer(&multisig_address)], None); match payload { - MultisigTransactionPayload::EntryFunction(entry_function) =>{ + MultisigTransactionPayload::EntryFunction(entry_function) => { session.execute(|session| { self.validate_and_execute_entry_function( module_storage, @@ -1934,6 +1983,12 @@ impl AptosVM { } } + if is_approved_gov_script { + // If governance is honest then it will not attempt test-and-abort attacks to abuse + // randomness. + self.mark_unbiasable(session); + } + // The prologue MUST be run AFTER any validation. Otherwise you may run prologue and hit // SEQUENCE_NUMBER_TOO_NEW if there is more than one transaction from the same sender and // end up skipping validation. @@ -2060,7 +2115,6 @@ impl AptosVM { let payload_timer = VM_TIMER.timer_with_label("AptosVM::execute_user_transaction_impl [payload]"); - // `validate_signed_transaction` function already discards the transactions with `TransactionPayloadInner` type payload if the // corresponding feature flag (`TransactionPayloadV2`) is disabled. Therefore, we don't need to check the feature flag here again. let executable = match txn.executable_ref() { @@ -2083,7 +2137,7 @@ impl AptosVM { log_context, change_set_configs, ) - } else { + } else { self.execute_script_or_entry_function( resolver, code_storage, @@ -2095,6 +2149,7 @@ impl AptosVM { executable, log_context, change_set_configs, + is_approved_gov_script, ) }; drop(payload_timer); @@ -2284,6 +2339,10 @@ impl AptosVM { &mut UnmeteredGasMeter, &mut traversal_context, script, + // This function is currently only used for genesis, so this could be set to + // true, but we don't access randomness during genesis at the moment so there + // is no benefit in doing so. + false, )?; let change_set_configs = @@ -2438,6 +2497,21 @@ impl AptosVM { Ok((VMStatus::Executed, output)) } + fn mark_unbiasable(&self, session: &mut SessionExt<'_, impl AptosMoveResolver>) { + // During the first epoch in which the feature is activated, threshold keys have not yet + // been established (they are produced at the end of that epoch via DKG), so the randomness + // seed can be biased to some degree (although with great difficulty) by Byzantine proposers. + // However, the randomness usages within the metadata transaction itself (e.g. by the DKG + // during epoch change) remain unaffected by test-and-abort attacks, which the bias-ability + // check is intended to protect against. Similarly, governance is expected not to attempt to + // bias randomness results. This allows us to continue to manually force epoch changes via + // governance when necessary, which would otherwise be impossible due to + // reconfiguration_with_dkg::try_start relying on access to randomness, + if self.features().is_enabled(FeatureFlag::SUPRA_DKG) { + session.mark_unbiasable(); + } + } + fn process_block_prologue_ext( &self, resolver: &impl AptosMoveResolver, @@ -2491,12 +2565,16 @@ impl AptosVM { randomness .as_ref() .map(Randomness::randomness_cloned) + .unwrap_or_default() .as_move_value(), ]; let traversal_storage = TraversalStorage::new(); let mut traversal_context = TraversalContext::new(&traversal_storage); + // The block metadata transaction seeds randomness so is immune to test-and-abort attacks. + self.mark_unbiasable(&mut session); + session .execute_function_bypass_visibility( &BLOCK_MODULE, @@ -2661,18 +2739,23 @@ impl AptosVM { let gas_used = Self::gas_used(max_gas_amount.into(), &gas_meter); match execution_result { Ok(result) => ViewFunctionOutput::new(Ok(result), gas_used), - Err(e) => { - vm.view_function_output_from_error(e, gas_used, &module_storage, &traversal_context, &log_context) - }, + Err(e) => vm.view_function_output_from_error( + e, + gas_used, + &module_storage, + &traversal_context, + &log_context, + ), } } - pub(crate) fn view_function_output_from_error(&self, - e: VMError, - gas_used: u64, - module_storage: &impl AptosModuleStorage, - traversal_context: &TraversalContext, - log_context: &AdapterLogSchema, + pub(crate) fn view_function_output_from_error( + &self, + e: VMError, + gas_used: u64, + module_storage: &impl AptosModuleStorage, + traversal_context: &TraversalContext, + log_context: &AdapterLogSchema, ) -> ViewFunctionOutput { let vm_status = e.clone().into_vm_status(); match vm_status { @@ -2689,8 +2772,7 @@ impl AptosVM { ); }, } - let txn_status = - TransactionStatus::from_vm_status(vm_status.clone(), self.features()); + let txn_status = TransactionStatus::from_vm_status(vm_status.clone(), self.features()); let execution_status = match txn_status { TransactionStatus::Keep(status) => status, _ => ExecutionStatus::MiscellaneousError(Some(vm_status.status_code())), @@ -2706,7 +2788,6 @@ impl AptosVM { Some(vm_status.status_code()), gas_used, ) - } pub(crate) fn gas_used(max_gas_amount: Gas, gas_meter: &impl AptosGasMeter) -> u64 { @@ -2804,7 +2885,6 @@ impl AptosVM { self.is_simulation, )?; - if let Some(task_registration_params) = executable.as_automation_registration_params() { check_automation_task_gas( self.gas_params(log_context)?, @@ -2986,14 +3066,14 @@ impl AptosVM { )?; (vm_status, output) }, - Transaction::AutomatedTransaction(txn) => AutomatedTransactionProcessor::new( - self, AutomationTaskType::User, - ) - .execute_transaction(resolver, code_storage, txn, log_context), - Transaction::SystemAutomatedTransaction(txn) => AutomatedTransactionProcessor::new( - self, AutomationTaskType::System, - ) - .execute_transaction(resolver, code_storage, txn, log_context), + Transaction::AutomatedTransaction(txn) => { + AutomatedTransactionProcessor::new(self, AutomationTaskType::User) + .execute_transaction(resolver, code_storage, txn, log_context) + }, + Transaction::SystemAutomatedTransaction(txn) => { + AutomatedTransactionProcessor::new(self, AutomationTaskType::System) + .execute_transaction(resolver, code_storage, txn, log_context) + }, Transaction::AutomationRegistryTransaction(txn) => { AutomationRegistryTransactionProcessor::new(self).execute_transaction( resolver, @@ -3010,10 +3090,7 @@ impl AptosVM { } fn check_multisig_task_registration_support(&self) -> Result<(), VMStatus> { - if !self - .features() - .is_enabled(FeatureFlag::SUPRA_AUTOMATION_V2) - { + if !self.features().is_enabled(FeatureFlag::SUPRA_AUTOMATION_V2) { return Err(VMStatus::Error { status_code: StatusCode::FEATURE_UNDER_GATING, sub_status: None, @@ -3273,6 +3350,111 @@ impl VMValidator for AptosVM { result } + + fn validate_dkg_validator_transaction( + &self, + dkg_transaction: DKGTransactionData, + resolver: &impl AptosMoveResolver, + ) -> VMValidatorResult { + if !self.features().is_enabled(FeatureFlag::SUPRA_DKG) { + return VMValidatorResult::error(StatusCode::FEATURE_UNDER_GATING); + } + + let dkg_state = match OnChainConfig::fetch_config(resolver) { + Some(state) => state, + None => return VMValidatorResult::error(StatusCode::RESOURCE_DOES_NOT_EXIST), + }; + + let config_resource = match ConfigurationResource::fetch_config(resolver) { + Some(cfg) => cfg, + None => return VMValidatorResult::error(StatusCode::RESOURCE_DOES_NOT_EXIST), + }; + + let DKGState { in_progress, .. } = dkg_state; + let in_progress_session_state = match in_progress { + Some(session) => session, + None => return VMValidatorResult::error(StatusCode::DKG_SESSION_NOT_IN_PROGRESS), + }; + + // Check epoch number. + if *dkg_transaction.metadata().epoch() > config_resource.epoch() { + return VMValidatorResult::error(StatusCode::DKG_TRANSACTION_FUTURE_EPOCH_NUM); + } + if *dkg_transaction.metadata().epoch() < config_resource.epoch() { + return VMValidatorResult::error(StatusCode::DKG_TRANSACTION_PAST_EPOCH_NUM); + } + + match dkg_transaction.metadata().transaction_type() { + DKGTransactionType::DKGMeta => { + // dkg meta should not be already set + if in_progress_session_state.dkg_meta_transcript.len() != 0 { + return VMValidatorResult::error(StatusCode::DKG_META_ALREADY_SET); + } + }, + DKGTransactionType::PublicKeyShares => { + // for public shares trasaction, dkg meta should be already set + // but it is possible due to network asynchrony, that public shares transaction is processed before dkg meta transaction + // in which case, dkg meta is not set yet + // so we cannot impose this condition + }, + } + + let dealer_committee = &in_progress_session_state.metadata.dealer_committee; + let randomness_seed = &in_progress_session_state.metadata.randomness_seed; + + if dkg_transaction.data_bytes().is_empty() + || dkg_transaction + .metadata() + .bls_aggregate_signature() + .is_empty() + || dkg_transaction + .metadata() + .signer_indices_clan_committee() + .is_empty() + { + return VMValidatorResult::error(StatusCode::DKG_TRANSACTION_NOT_VALID); + } + + // verify clan committee multi-signature on the transaction data + let signer_bls_pubkeys = match aptos_types::dkg::get_clan_nodes_bls_keys_from_indices( + dealer_committee, + &dkg_transaction.metadata().signer_indices_clan_committee(), + randomness_seed, + ) { + Ok(bls_keys) => bls_keys, + Err(_) => { + return VMValidatorResult::error(StatusCode::DKG_FAILED_TO_GET_CLAN_NODE_PUBKEYS); + }, + }; + + let agg_sig = match Signature::try_from( + dkg_transaction + .metadata() + .bls_aggregate_signature() + .as_slice(), + ) { + Ok(sig) => sig, + Err(_) => { + return VMValidatorResult::error(StatusCode::DKG_FAILED_TO_DESER_AGG_SIG); + }, + }; + + let agg_pk = match PublicKey::aggregate(signer_bls_pubkeys.iter().collect()) { + Ok(pk) => pk, + Err(_) => { + return VMValidatorResult::error(StatusCode::DKG_FAILED_TO_AGGREGATE_PUBLIC_KEYS); + }, + }; + + if agg_sig + .verify_aggregate_arbitrary_msg(&[dkg_transaction.data_bytes().as_slice()], &[&agg_pk]) + .is_err() + { + return VMValidatorResult::error(StatusCode::DKG_AGG_SIG_VERIFICATION_FAILED); + } + + VMValidatorResult::new(None, 0) + } } // Ensure encapsulation of AptosVM APIs by using a wrapper. @@ -3307,7 +3489,6 @@ impl AptosSimulationVM { .expect("Materializing aggregator V1 deltas should never fail"); (vm_status, txn_output) } - } fn create_account_if_does_not_exist( diff --git a/aptos-move/aptos-vm/src/aptos_vm_viewer.rs b/aptos-move/aptos-vm/src/aptos_vm_viewer.rs index b985b2e4263..61a7c6cba91 100644 --- a/aptos-move/aptos-vm/src/aptos_vm_viewer.rs +++ b/aptos-move/aptos-vm/src/aptos_vm_viewer.rs @@ -1,19 +1,22 @@ -// Copyright (c) Aptos Foundation +// Copyright (c) 2024 Supra. // SPDX-License-Identifier: Apache-2.0 -// // Copyright (c) 2024 Supra. -// // SPDX-License-Identifier: Apache-2.0 - -use crate::gas::{make_prod_gas_meter, ProdGasMeter}; -use crate::AptosVM; -use aptos_types::state_store::StateView; -use aptos_types::transaction::{ViewFunction, ViewFunctionOutput}; +use crate::{ + gas::{make_prod_gas_meter, ProdGasMeter}, + move_vm_ext::SessionId::Void, + AptosVM, +}; +use aptos_types::{ + state_store::StateView, + transaction::{EntryFunction, ViewFunction, ViewFunctionOutput}, +}; use aptos_vm_environment::environment::AptosEnvironment; use aptos_vm_logging::log_schema::AdapterLogSchema; -use aptos_vm_types::module_and_script_storage::AsAptosCodeStorage; -use aptos_vm_types::resolver::NoopBlockSynchronizationKillSwitch; +use aptos_vm_types::{ + module_and_script_storage::AsAptosCodeStorage, resolver::NoopBlockSynchronizationKillSwitch, +}; +use move_core_types::account_address::AccountAddress; use move_vm_runtime::module_traversal::{TraversalContext, TraversalStorage}; -use crate::move_vm_ext::SessionId::Void; /// Move VM with only view function API. /// Convenient to use when more than one view function needs to be executed on the same state-view, @@ -37,10 +40,20 @@ impl<'t, SV: StateView> AptosVMViewer<'t, SV> { } } - fn create_gas_meter(&self, max_gas_amount: u64) -> anyhow::Result> { - let vm_gas_params = self.vm.gas_params(&self.log_context).map_err(|err| anyhow::Error::msg(err.to_string()))?.vm.clone(); - let storage_gas_params = - self.vm.storage_gas_params(&self.log_context).map_err(|err| anyhow::Error::msg(err.to_string()))?; + fn create_gas_meter( + &self, + max_gas_amount: u64, + ) -> anyhow::Result> { + let vm_gas_params = self + .vm + .gas_params(&self.log_context) + .map_err(|err| anyhow::Error::msg(err.to_string()))? + .vm + .clone(); + let storage_gas_params = self + .vm + .storage_gas_params(&self.log_context) + .map_err(|err| anyhow::Error::msg(err.to_string()))?; let gas_meter = make_prod_gas_meter( self.vm.gas_feature_version(), @@ -68,7 +81,9 @@ impl<'t, SV: StateView> AptosVMViewer<'t, SV> { let traversal_storage = TraversalStorage::new(); let mut traversal_context = TraversalContext::new(&traversal_storage); - let module_storage = self.state_view.as_aptos_code_storage(self.vm.environment_ref()); + let module_storage = self + .state_view + .as_aptos_code_storage(self.vm.environment_ref()); let execution_result = AptosVM::execute_view_function_in_vm( &mut session, &self.vm, @@ -78,12 +93,18 @@ impl<'t, SV: StateView> AptosVMViewer<'t, SV> { arguments, &mut gas_meter, &mut traversal_context, - &module_storage + &module_storage, ); let gas_used = AptosVM::gas_used(max_gas_amount.into(), &gas_meter); match execution_result { Ok(result) => ViewFunctionOutput::new(Ok(result), gas_used), - Err(e) => self.vm.view_function_output_from_error(e, gas_used, &module_storage, &traversal_context, &self.log_context), + Err(e) => self.vm.view_function_output_from_error( + e, + gas_used, + &module_storage, + &traversal_context, + &self.log_context, + ), } } } diff --git a/aptos-move/aptos-vm/src/automated_transaction_processor.rs b/aptos-move/aptos-vm/src/automated_transaction_processor.rs index 1c0cf959574..f59713de82f 100644 --- a/aptos-move/aptos-vm/src/automated_transaction_processor.rs +++ b/aptos-move/aptos-vm/src/automated_transaction_processor.rs @@ -1,43 +1,50 @@ -// Copyright (c) Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - // Copyright (c) 2024 Supra. // SPDX-License-Identifier: Apache-2.0 -use crate::aptos_vm::{unwrap_or_discard, SerializedSigners}; -use crate::counters::TXN_GAS_USAGE; -use crate::errors::discarded_output; -use crate::gas::{check_gas, make_prod_gas_meter}; -use crate::move_vm_ext::session::user_transaction_sessions::epilogue::EpilogueSession; -use crate::move_vm_ext::session::user_transaction_sessions::prologue::PrologueSession; -use crate::move_vm_ext::session::user_transaction_sessions::user::UserSession; -use crate::move_vm_ext::{AptosMoveResolver, SessionExt}; -use crate::transaction_metadata::TransactionMetadata; -use crate::{transaction_validation, AptosVM}; +use crate::{ + aptos_vm::{unwrap_or_discard, SerializedSigners}, + counters::TXN_GAS_USAGE, + errors::discarded_output, + gas::{check_gas, make_prod_gas_meter}, + move_vm_ext::{ + session::user_transaction_sessions::{ + epilogue::EpilogueSession, prologue::PrologueSession, + session_change_sets::SystemSessionChangeSet, user::UserSession, + }, + AptosMoveResolver, SessionExt, + }, + transaction_metadata::TransactionMetadata, + transaction_validation, AptosVM, +}; use aptos_gas_algebra::Gas; use aptos_gas_meter::{AptosGasMeter, GasAlgebra}; use aptos_gas_schedule::VMGasParameters; -use aptos_types::fee_statement::FeeStatement; -use aptos_types::on_chain_config::FeatureFlag; -use aptos_types::transaction::automated_transaction::AutomatedTransaction; -use aptos_types::transaction::automation::AutomationTaskType; -use aptos_types::transaction::{ - EntryFunction, ExecutionStatus, TransactionPayload, TransactionStatus, +use aptos_types::{ + fee_statement::FeeStatement, + on_chain_config::FeatureFlag, + transaction::{ + automated_transaction::AutomatedTransaction, automation::AutomationTaskType, EntryFunction, + ExecutionStatus, TransactionPayload, TransactionStatus, + }, }; use aptos_vm_logging::log_schema::AdapterLogSchema; -use aptos_vm_types::output::VMOutput; -use aptos_vm_types::storage::change_set_configs::ChangeSetConfigs; -use aptos_vm_types::storage::StorageGasParameters; +use aptos_vm_types::{ + change_set::VMChangeSet, + module_and_script_storage::{ + code_storage::AptosCodeStorage, module_storage::AptosModuleStorage, + }, + output::VMOutput, + resolver::BlockSynchronizationKillSwitch, + storage::{change_set_configs::ChangeSetConfigs, StorageGasParameters}, +}; use fail::fail_point; use move_binary_format::errors::Location; use move_core_types::vm_status::{StatusCode, VMStatus}; -use move_vm_runtime::module_traversal::{TraversalContext, TraversalStorage}; +use move_vm_runtime::{ + module_traversal::{TraversalContext, TraversalStorage}, + LoadedFunction, ModuleStorage, +}; use std::ops::Deref; -use aptos_vm_types::module_and_script_storage::code_storage::AptosCodeStorage; -use aptos_vm_types::module_and_script_storage::module_storage::AptosModuleStorage; -use aptos_vm_types::resolver::BlockSynchronizationKillSwitch; -use move_vm_runtime::ModuleStorage; -use crate::move_vm_ext::session::user_transaction_sessions::session_change_sets::SystemSessionChangeSet; pub struct AutomatedTransactionProcessor<'m> { aptos_vm: &'m AptosVM, @@ -82,10 +89,7 @@ impl<'m> AutomatedTransactionProcessor<'m> { false, log_context, )?; - if self - .features() - .is_enabled(FeatureFlag::SUPRA_AUTOMATION_V2) - { + if self.features().is_enabled(FeatureFlag::SUPRA_AUTOMATION_V2) { transaction_validation::run_automated_transaction_prologue_v2( session, module_storage, @@ -183,8 +187,15 @@ impl<'m> AutomatedTransactionProcessor<'m> { ); gas_meter.charge_intrinsic_gas_for_transaction(txn_data.transaction_size())?; - session.execute(|session| { - self.validate_and_execute_entry_function( + + // Phase 1: load the function and validate arguments. + // Failures here mean the registered payload became permanently invalid after + // registration (e.g., module removed, function renamed, or signature changed + // by an upgrade). Tagged as INVALID_AUTOMATION_INNER_PAYLOAD so that + // execute_transaction_impl can distinguish pre-execution failures from transient + // execution failures and discard without charging any gas. + let (function, args) = session.execute(|session| { + self.load_and_validate_entry_function( code_storage, session, serialized_signers, @@ -192,6 +203,24 @@ impl<'m> AutomatedTransactionProcessor<'m> { traversal_context, entry_function, ) + .map_err(|e| { + VMStatus::error( + StatusCode::INVALID_AUTOMATION_INNER_PAYLOAD, + Some(format!( + "Automated task inner payload became invalid at execution time: {e:?}" + )), + ) + }) + })?; + + // Phase 2: execute the entry function body. + // Failures here (ABORTED, OUT_OF_GAS, etc.) are transient execution errors + // and flow through the normal failure-epilogue path with gas charged. + session.execute(|session| { + session + .execute_loaded_function(function, args, gas_meter, traversal_context, code_storage) + .map(|_| ()) + .map_err(|e| e.into_vm_status()) })?; let user_session_change_set = self.resolve_pending_code_publish_and_finish_user_session( @@ -238,7 +267,6 @@ impl<'m> AutomatedTransactionProcessor<'m> { change_set_configs: &ChangeSetConfigs, traversal_context: &mut TraversalContext, ) -> (VMStatus, VMOutput) { - self.failed_transaction_cleanup( prologue_change_set, err, @@ -251,6 +279,7 @@ impl<'m> AutomatedTransactionProcessor<'m> { traversal_context, ) } + pub(crate) fn execute_transaction_impl<'a>( &self, resolver: &impl AptosMoveResolver, @@ -264,8 +293,7 @@ impl<'m> AutomatedTransactionProcessor<'m> { let mut traversal_context = TraversalContext::new(&traversal_storage); // Revalidate the transaction. - let mut prologue_session = - PrologueSession::new(self.aptos_vm, &txn_data, resolver); + let mut prologue_session = PrologueSession::new(self.aptos_vm, &txn_data, resolver); let exec_result = prologue_session.execute(|session| { self.validate_automated_transaction( @@ -281,13 +309,7 @@ impl<'m> AutomatedTransactionProcessor<'m> { let storage_gas_params = unwrap_or_discard!(self.storage_gas_params(log_context)); let change_set_configs = &storage_gas_params.change_set_configs; let (prologue_change_set, user_session) = unwrap_or_discard!(prologue_session - .into_user_session( - self, - &txn_data, - resolver, - change_set_configs, - code_storage, - )); + .into_user_session(self, &txn_data, resolver, change_set_configs, code_storage,)); let TransactionPayload::EntryFunction(automated_entry_function) = txn.payload() else { return ( VMStatus::error(StatusCode::INVALID_AUTOMATED_PAYLOAD, None), @@ -320,6 +342,27 @@ impl<'m> AutomatedTransactionProcessor<'m> { TXN_GAS_USAGE.observe(u64::from(gas_usage) as f64); result.unwrap_or_else(|err| { + // True only [FeatureFlag::SUPRA_AUTOMATION_V2_1] is enabled: which enables task registration without validation + // Pre-execution failure: the task's registered payload is permanently invalid + // (function signature is invalid, function is missing or arguments do not match expected ones). + // The entry function body never ran so no execution gas was consumed. Skip the failure epilogue + // entirely — discarded_output produces FeeStatement::zero() and an empty + // change set so no fees are charged and no state is committed. + // + // Note: Before [FeatureFlag::SUPRA_AUTOMATION_V2_1] during task registration inner payload is always verified + // and in case of failure task will never be actually registered. + // So potentially this error should never be registered for a task which is registered with validation flow. + // And if for some reason it is registered, then user will be charged with whatever gas was used so far. + if err.status_code() == StatusCode::INVALID_AUTOMATION_INNER_PAYLOAD + && self + .features() + .is_enabled(FeatureFlag::SUPRA_AUTOMATION_V2_1) + { + return ( + err, + discarded_output(StatusCode::INVALID_AUTOMATION_INNER_PAYLOAD), + ); + } self.on_transaction_execution_failure( prologue_change_set, err, @@ -360,8 +403,14 @@ impl<'m> AutomatedTransactionProcessor<'m> { balance, code_storage, ); - let (status, output) = - self.execute_transaction_impl(resolver, code_storage, txn, txn_metadata, &mut gas_meter, log_context); + let (status, output) = self.execute_transaction_impl( + resolver, + code_storage, + txn, + txn_metadata, + &mut gas_meter, + log_context, + ); Ok((status, output, gas_meter)) } @@ -423,10 +472,8 @@ impl<'m> AutomatedTransactionProcessor<'m> { } } - let txn_status = TransactionStatus::from_vm_status( - error_vm_status.clone(), - self.features(), - ); + let txn_status = + TransactionStatus::from_vm_status(error_vm_status.clone(), self.features()); match txn_status { TransactionStatus::Keep(status) => { @@ -436,17 +483,19 @@ impl<'m> AutomatedTransactionProcessor<'m> { // gas). Even if the previous failure occurred while running the epilogue, it // should not fail now. If it somehow fails here, there is no choice but to // discard the transaction. - let txn_output = self.finish_aborted_transaction( - prologue_change_set, - gas_meter, - txn_data, - resolver, - module_storage, - status, - log_context, - change_set_configs, - traversal_context, - ).unwrap_or_else(|status| discarded_output(status.status_code())); + let txn_output = self + .finish_aborted_transaction( + prologue_change_set, + gas_meter, + txn_data, + resolver, + module_storage, + status, + log_context, + change_set_configs, + traversal_context, + ) + .unwrap_or_else(|status| discarded_output(status.status_code())); (error_vm_status, txn_output) }, TransactionStatus::Discard(status_code) => { @@ -483,7 +532,8 @@ impl<'m> AutomatedTransactionProcessor<'m> { module_storage, traversal_context, log_context, - status); + status, + ); let fee_statement = AptosVM::fee_statement_from_gas_meter(txn_data, gas_meter, ZERO_STORAGE_REFUND); @@ -500,8 +550,12 @@ impl<'m> AutomatedTransactionProcessor<'m> { traversal_context, ) })?; - epilogue_session - .finish(self.get_fee_statement_for_output(fee_statement), status, change_set_configs, module_storage) + epilogue_session.finish( + self.get_fee_statement_for_output(fee_statement), + status, + change_set_configs, + module_storage, + ) } /// The actual charged fee statement for executed automated transaction. @@ -511,12 +565,8 @@ impl<'m> AutomatedTransactionProcessor<'m> { /// This function is utilized to define fee-statement of VMOutput. fn get_fee_statement_for_output(&self, fee_statement: FeeStatement) -> FeeStatement { match self.task_type { - AutomationTaskType::User => { - fee_statement - } - AutomationTaskType::System => { - FeeStatement::zero() - } + AutomationTaskType::User => fee_statement, + AutomationTaskType::System => FeeStatement::zero(), } } } diff --git a/aptos-move/aptos-vm/src/automation_registry_transaction_processor.rs b/aptos-move/aptos-vm/src/automation_registry_transaction_processor.rs index 835c890ac04..d2fa4ea387e 100644 --- a/aptos-move/aptos-vm/src/automation_registry_transaction_processor.rs +++ b/aptos-move/aptos-vm/src/automation_registry_transaction_processor.rs @@ -1,28 +1,37 @@ // Copyright (c) 2025 Supra. // SPDX-License-Identifier: Apache-2.0 -use crate::aptos_vm::get_system_transaction_output; -use crate::counters::SYSTEM_TRANSACTIONS_EXECUTED; -use crate::errors::discarded_output; -use crate::gas::make_prod_gas_meter; -use crate::move_vm_ext::{AptosMoveResolver, SessionExt, SessionId}; -use crate::AptosVM; -use aptos_types::account_config; -use aptos_types::fee_statement::FeeStatement; -use aptos_types::on_chain_config::FeatureFlag; -use aptos_types::transaction::automation::AutomationRegistryRecord; -use aptos_types::transaction::TransactionStatus; +use crate::{ + aptos_vm::get_system_transaction_output, + counters::SYSTEM_TRANSACTIONS_EXECUTED, + errors::discarded_output, + gas::make_prod_gas_meter, + move_vm_ext::{AptosMoveResolver, SessionExt, SessionId}, + AptosVM, +}; +use aptos_types::{ + account_config, + fee_statement::FeeStatement, + on_chain_config::FeatureFlag, + transaction::{ + automation::{AutomationRegistryAction, AutomationRegistryRecord}, + ExecutionStatus, TransactionStatus, + }, +}; use aptos_vm_logging::log_schema::AdapterLogSchema; -use aptos_vm_types::module_and_script_storage::code_storage::AptosCodeStorage; -use aptos_vm_types::module_write_set::ModuleWriteSet; -use aptos_vm_types::output::VMOutput; -use aptos_vm_types::resolver::BlockSynchronizationKillSwitch; -use aptos_vm_types::storage::change_set_configs::ChangeSetConfigs; +use aptos_vm_types::{ + module_and_script_storage::{ + code_storage::AptosCodeStorage, module_storage::AptosModuleStorage, + }, + module_write_set::ModuleWriteSet, + output::VMOutput, + resolver::BlockSynchronizationKillSwitch, + storage::change_set_configs::ChangeSetConfigs, +}; use move_binary_format::errors::VMError; use move_core_types::vm_status::{StatusCode, VMStatus}; use move_vm_runtime::module_traversal::{TraversalContext, TraversalStorage}; use std::ops::Deref; -use aptos_vm_types::module_and_script_storage::module_storage::AptosModuleStorage; pub struct AutomationRegistryTransactionProcessor<'m> { aptos_vm: &'m AptosVM, @@ -62,13 +71,34 @@ impl<'m> AutomationRegistryTransactionProcessor<'m> { discarded_output(StatusCode::FEATURE_UNDER_GATING), )); } + // CancelInvalidTask is part of SUPRA_AUTOMATION_V2_1: ensure the feature is live + // before executing cancellations generated by the consensus layer. + if matches!( + action_record.action(), + AutomationRegistryAction::CancelInvalidTask { .. } + ) && !self + .features() + .is_enabled(FeatureFlag::SUPRA_AUTOMATION_V2_1) + { + return Ok(( + VMStatus::Error { + status_code: StatusCode::FEATURE_UNDER_GATING, + sub_status: None, + message: Some( + "SUPRA_AUTOMATION_V2_1 is not enabled; CancelInvalidTask is unavailable." + .to_string(), + ), + }, + discarded_output(StatusCode::FEATURE_UNDER_GATING), + )); + } let gas_params = self.gas_params(log_context)?.vm.clone(); - let storage_gas_params = self.storage_gas_params(log_context)?; + let max_gas_amount = gas_params.txn.maximum_number_of_gas_units; let mut gas_meter = make_prod_gas_meter( self.gas_feature_version(), gas_params, - storage_gas_params.clone(), + self.storage_gas_params(log_context)?.clone(), false, max_gas_amount, code_storage, @@ -100,14 +130,14 @@ impl<'m> AutomationRegistryTransactionProcessor<'m> { let output = get_system_transaction_output( session, code_storage, - &storage_gas_params.change_set_configs, + &self.storage_gas_params(log_context)?.change_set_configs, )?; Ok((VMStatus::Executed, output)) }, Err(vm_err) => self.get_transaction_error_output( session, code_storage, - &storage_gas_params.change_set_configs, + &self.storage_gas_params(log_context)?.change_set_configs, vm_err, ), } diff --git a/aptos-move/aptos-vm/src/gas.rs b/aptos-move/aptos-vm/src/gas.rs index 8cffda6772b..0253118cb40 100644 --- a/aptos-move/aptos-vm/src/gas.rs +++ b/aptos-move/aptos-vm/src/gas.rs @@ -11,17 +11,20 @@ use aptos_gas_schedule::{ }; use aptos_logger::{enabled, Level}; use aptos_memory_usage_tracker::MemoryTrackedGasMeter; -use aptos_types::on_chain_config::{FeatureFlag, Features}; -use aptos_types::transaction::{RawTransaction, TransactionPayload}; -use aptos_types::transaction::automation::RegistrationParams; +use aptos_types::{ + on_chain_config::{FeatureFlag, Features}, + transaction::{automation::RegistrationParams, RawTransaction, TransactionPayload}, +}; use aptos_vm_logging::{log_schema::AdapterLogSchema, speculative_log, speculative_warn}; use aptos_vm_types::{ resolver::BlockSynchronizationKillSwitch, storage::{space_pricing::DiskSpacePricing, StorageGasParameters}, }; -use move_core_types::vm_status::{StatusCode, VMStatus}; +use move_core_types::{ + gas_algebra::{NumArgs, NumBytes}, + vm_status::{StatusCode, VMStatus}, +}; use move_vm_runtime::ModuleStorage; -use move_core_types::gas_algebra::NumBytes; /// This is used until gas version 18, which introduces a configurable entry for this. const MAXIMUM_APPROVED_TRANSACTION_SIZE_LEGACY: u64 = 1024 * 1024; @@ -51,7 +54,7 @@ pub fn make_prod_gas_meter( } /// Invariants facilitating gas checks of the transactions. -pub (crate) struct TransactionGasCheckInvariants { +pub(crate) struct TransactionGasCheckInvariants { pub(crate) gas_unit_price: FeePerGasUnit, pub(crate) max_gas_amount: Gas, pub(crate) transaction_size: NumBytes, @@ -76,7 +79,13 @@ pub(crate) fn check_gas( script_size: txn_metadata.script_size, is_keyless: txn_metadata.is_keyless(), }; - check_gas_for_parameters(gas_params, gas_feature_version, txn_gas_metadata, is_approved_gov_script, log_context)?; + check_gas_for_parameters( + gas_params, + gas_feature_version, + txn_gas_metadata, + is_approved_gov_script, + log_context, + )?; let txn_gas_params = &gas_params.vm.txn; // If this is for a potentially new account, ensure there's enough gas to cover storage, execution, and IO costs. // TODO: This isn't the cleaning code, thus we localize it just here and will remove it @@ -132,11 +141,11 @@ pub(crate) fn check_automation_task_gas( log_context: &AdapterLogSchema, ) -> Result<(), VMStatus> { if !features.is_enabled(FeatureFlag::SUPRA_AUTOMATION_PAYLOAD_GAS_CHECK) { - return Ok(()) + return Ok(()); } - let size_in_bytes = RawTransaction::estimate_size_in_bytes( - TransactionPayload::EntryFunction(registration_params.automated_function().clone()), - ); + let size_in_bytes = RawTransaction::estimate_size_in_bytes(TransactionPayload::EntryFunction( + registration_params.automated_function().clone(), + )); let gas_check_invariants = TransactionGasCheckInvariants { gas_unit_price: registration_params.gas_price_cap().into(), max_gas_amount: registration_params.max_gas_amount().into(), @@ -154,33 +163,35 @@ pub(crate) fn check_automation_task_gas( match results { Ok(_) => Ok(()), Err(VMStatus::Error { - status_code, sub_status, message - } )=> { + status_code, + sub_status, + message, + }) => { let mapped_status = match status_code { StatusCode::EXCEEDED_MAX_TRANSACTION_SIZE => { StatusCode::AUTOMATION_PAYLOAD_EXCEEDED_MAX_TRANSACTION_SIZE - } + }, StatusCode::MAX_GAS_UNITS_EXCEEDS_MAX_GAS_UNITS_BOUND => { StatusCode::AUTOMATION_TASK_MAX_GAS_UNITS_EXCEEDS_MAX_GAS_UNITS_BOUND - } + }, StatusCode::MAX_GAS_UNITS_BELOW_MIN_TRANSACTION_GAS_UNITS => { StatusCode::AUTOMATION_TASK_MAX_GAS_UNITS_BELOW_MIN_TRANSACTION_GAS_UNITS - } + }, StatusCode::GAS_UNIT_PRICE_BELOW_MIN_BOUND => { StatusCode::AUTOMATION_TASK_GAS_PRICE_CAP_BELOW_MIN_BOUND - } + }, StatusCode::GAS_UNIT_PRICE_ABOVE_MAX_BOUND => { StatusCode::AUTOMATION_TASK_GAS_PRICE_CAP_ABOVE_MAX_BOUND - } - _ => status_code + }, + _ => status_code, }; Err(VMStatus::Error { status_code: mapped_status, sub_status, message, }) - } - Err(v) => Err(v), + }, + Err(v) => Err(v), } } @@ -242,8 +253,7 @@ pub(crate) fn check_gas_for_parameters( log_context, format!( "[VM] Gas unit error; max {}, submitted {}", - txn_gas_params.maximum_number_of_gas_units, - txn_gas_metadata.max_gas_amount + txn_gas_params.maximum_number_of_gas_units, txn_gas_metadata.max_gas_amount ), ); return Err(VMStatus::error( @@ -269,8 +279,7 @@ pub(crate) fn check_gas_for_parameters( log_context, format!( "[VM] Gas unit error; min {}, submitted {}", - total_rounded, - txn_gas_metadata.max_gas_amount + total_rounded, txn_gas_metadata.max_gas_amount ), ); return Err(VMStatus::error( @@ -289,8 +298,7 @@ pub(crate) fn check_gas_for_parameters( log_context, format!( "[VM] Gas unit error; min {}, submitted {}", - txn_gas_params.min_price_per_gas_unit, - txn_gas_metadata.gas_unit_price + txn_gas_params.min_price_per_gas_unit, txn_gas_metadata.gas_unit_price ), ); return Err(VMStatus::error( @@ -305,8 +313,7 @@ pub(crate) fn check_gas_for_parameters( log_context, format!( "[VM] Gas unit error; max {}, submitted {}", - txn_gas_params.max_price_per_gas_unit, - txn_gas_metadata.gas_unit_price + txn_gas_params.max_price_per_gas_unit, txn_gas_metadata.gas_unit_price ), ); return Err(VMStatus::error( diff --git a/aptos-move/aptos-vm/src/lib.rs b/aptos-move/aptos-vm/src/lib.rs index 56c7b45c913..dfb761b4d6d 100644 --- a/aptos-move/aptos-vm/src/lib.rs +++ b/aptos-move/aptos-vm/src/lib.rs @@ -107,6 +107,9 @@ pub mod counters; pub mod data_cache; pub mod aptos_vm; +pub mod aptos_vm_viewer; +mod automated_transaction_processor; +mod automation_registry_transaction_processor; pub mod block_executor; mod errors; pub mod gas; @@ -123,18 +126,19 @@ pub mod transaction_metadata; mod transaction_validation; pub mod validator_txns; pub mod verifier; -mod automated_transaction_processor; -pub mod aptos_vm_viewer; -mod automation_registry_transaction_processor; pub use crate::aptos_vm::{AptosSimulationVM, AptosVM}; -use crate::sharded_block_executor::{executor_client::ExecutorClient, ShardedBlockExecutor}; +use crate::{ + move_vm_ext::AptosMoveResolver, + sharded_block_executor::{executor_client::ExecutorClient, ShardedBlockExecutor}, +}; use aptos_block_executor::txn_provider::default::DefaultTxnProvider; use aptos_types::{ block_executor::{ config::BlockExecutorConfigFromOnchain, partitioner::PartitionedTransactions, transaction_slice_metadata::TransactionSliceMetadata, }, + dkg::transactions::DKGTransactionData, state_store::{state_key::StateKey, StateView}, transaction::{ signature_verified_transaction::SignatureVerifiedTransaction, BlockOutput, @@ -155,6 +159,13 @@ pub trait VMValidator { state_view: &impl StateView, module_storage: &impl ModuleStorage, ) -> VMValidatorResult; + + // TODO: pass state view and module storage here. + fn validate_dkg_validator_transaction( + &self, + dkg_transaction: DKGTransactionData, + resolver: &impl AptosMoveResolver, + ) -> VMValidatorResult; } /// This trait describes the block executor interface which is responsible for executing a block of diff --git a/aptos-move/aptos-vm/src/move_vm_ext/session/session_id.rs b/aptos-move/aptos-vm/src/move_vm_ext/session/session_id.rs index 92bbf9a40fa..0f8acd2a72e 100644 --- a/aptos-move/aptos-vm/src/move_vm_ext/session/session_id.rs +++ b/aptos-move/aptos-vm/src/move_vm_ext/session/session_id.rs @@ -5,12 +5,13 @@ use crate::transaction_metadata::TransactionMetadata; use aptos_crypto::{hash::CryptoHash, HashValue}; use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; use aptos_types::{ - block_metadata::BlockMetadata, block_metadata_ext::BlockMetadataExt, - transaction::ReplayProtector, validator_txn::ValidatorTransaction, + block_metadata::BlockMetadata, + block_metadata_ext::BlockMetadataExt, + transaction::{automation::AutomationRegistryRecord, ReplayProtector}, + validator_txn::ValidatorTransaction, }; use move_core_types::account_address::AccountAddress; use serde::{Deserialize, Serialize}; -use aptos_types::transaction::automation::AutomationRegistryRecord; #[derive(BCSCryptoHash, Clone, CryptoHasher, Deserialize, Serialize)] pub enum SessionId { @@ -138,9 +139,7 @@ impl SessionId { } pub fn automation_registry_action(record: &AutomationRegistryRecord) -> Self { - Self::AutomationRegistryTxn { - id: record.hash() - } + Self::AutomationRegistryTxn { id: record.hash() } } pub fn run_on_abort(txn_metadata: &TransactionMetadata) -> Self { diff --git a/aptos-move/aptos-vm/src/system_module_names.rs b/aptos-move/aptos-vm/src/system_module_names.rs index d72ba3edd14..d21b9e1bfa1 100644 --- a/aptos-move/aptos-vm/src/system_module_names.rs +++ b/aptos-move/aptos-vm/src/system_module_names.rs @@ -48,6 +48,7 @@ pub static RECONFIGURATION_WITH_DKG_MODULE: Lazy = Lazy::new(|| { }); pub const FINISH_WITH_DKG_RESULT: &IdentStr = ident_str!("finish_with_dkg_result"); +pub const SET_DKG_META: &IdentStr = ident_str!("set_dkg_meta"); pub static JWKS_MODULE: Lazy = Lazy::new(|| { ModuleId::new( diff --git a/aptos-move/aptos-vm/src/transaction_metadata.rs b/aptos-move/aptos-vm/src/transaction_metadata.rs index f1e323e34ff..927d85fd6da 100644 --- a/aptos-move/aptos-vm/src/transaction_metadata.rs +++ b/aptos-move/aptos-vm/src/transaction_metadata.rs @@ -5,28 +5,30 @@ use aptos_crypto::HashValue; use aptos_gas_algebra::{FeePerGasUnit, Gas, NumBytes}; -use aptos_types::transaction::automated_transaction::AutomatedTransaction; use aptos_types::{ account_address::AccountAddress, chain_id::ChainId, transaction::{ - authenticator::AuthenticationProof, user_transaction_context::UserTransactionContext, + authenticator::AuthenticationProof, + automated_transaction::AutomatedTransaction, + user_transaction_context::{ + PayloadTypeReference, PayloadTypeReferenceContext, UserTransactionContext, + }, EntryFunction, Multisig, MultisigTransactionPayload, ReplayProtector, SignedTransaction, TransactionExecutable, TransactionExecutableRef, TransactionExtraConfig, TransactionPayload, TransactionPayloadInner, }, }; -use aptos_types::transaction::user_transaction_context::{PayloadTypeReference, PayloadTypeReferenceContext}; pub type PayloadTypeReferenceMeta = PayloadTypeReference; -fn convert_to_payload_type_reference_meta(payload: &TransactionPayloadInner) -> PayloadTypeReferenceMeta { +fn convert_to_payload_type_reference_meta( + payload: &TransactionPayloadInner, +) -> PayloadTypeReferenceMeta { let TransactionPayloadInner::V1 { executable, - extra_config: - TransactionExtraConfig::V1 { - multisig_address, - .. + extra_config: TransactionExtraConfig::V1 { + multisig_address, .. }, } = payload; match multisig_address { @@ -39,19 +41,15 @@ fn convert_to_payload_type_reference_meta(payload: &TransactionPayloadInner) -> Some(MultisigTransactionPayload::EntryFunction(e.clone())) }, _ => None, - } + }, }) }, - None => { - match executable { - TransactionExecutable::EntryFunction(e) => { - PayloadTypeReferenceMeta::UserEntryFunction(e.clone()) - } - _ => { - PayloadTypeReferenceMeta::Other - } - } - } + None => match executable { + TransactionExecutable::EntryFunction(e) => { + PayloadTypeReferenceMeta::UserEntryFunction(e.clone()) + }, + _ => PayloadTypeReferenceMeta::Other, + }, } } @@ -74,18 +72,25 @@ pub struct TransactionMetadata { pub script_size: NumBytes, pub is_keyless: bool, pub payload_type_reference: PayloadTypeReferenceMeta, - pub txn_app_hash: Vec, + pub txn_consensus_hash: Vec, } impl TransactionMetadata { pub fn new(txn: &SignedTransaction) -> Self { let payload_type_reference = match txn.payload() { - TransactionPayload::Script(_) | - TransactionPayload::ModuleBundle(_) => PayloadTypeReferenceMeta::Other, - TransactionPayload::EntryFunction(e) => PayloadTypeReferenceMeta::UserEntryFunction(e.clone()), + TransactionPayload::Script(_) | TransactionPayload::ModuleBundle(_) => { + PayloadTypeReferenceMeta::Other + }, + TransactionPayload::EntryFunction(e) => { + PayloadTypeReferenceMeta::UserEntryFunction(e.clone()) + }, TransactionPayload::Multisig(m) => PayloadTypeReferenceMeta::Multisig(m.clone()), - TransactionPayload::AutomationRegistration(_) => PayloadTypeReferenceMeta::AutomationRegistration, - TransactionPayload::Payload(payload_inner) => convert_to_payload_type_reference_meta(payload_inner), + TransactionPayload::AutomationRegistration(_) => { + PayloadTypeReferenceMeta::AutomationRegistration + }, + TransactionPayload::Payload(payload_inner) => { + convert_to_payload_type_reference_meta(payload_inner) + }, }; Self { sender: txn.sender(), @@ -126,7 +131,7 @@ impl TransactionMetadata { .map(|res| !res.is_empty()) .unwrap_or(false), payload_type_reference, - txn_app_hash: HashValue::keccak_256_of( + txn_consensus_hash: HashValue::keccak_256_of( &bcs::to_bytes(&txn).expect("Unable to serialize SignedTransaction"), ) .to_vec(), @@ -215,10 +220,23 @@ impl TransactionMetadata { pub fn as_user_transaction_context(&self) -> UserTransactionContext { let payload_type_reference = match &self.payload_type_reference { PayloadTypeReferenceMeta::Other => PayloadTypeReferenceContext::Other, - PayloadTypeReferenceMeta::UserEntryFunction(e) => PayloadTypeReferenceContext::UserEntryFunction(e.as_entry_function_payload()), - PayloadTypeReferenceMeta::Multisig(m) => PayloadTypeReferenceContext::Multisig(m.as_multisig_payload()), - PayloadTypeReferenceMeta::AutomationRegistration => PayloadTypeReferenceContext::AutomationRegistration, + PayloadTypeReferenceMeta::UserEntryFunction(e) => { + PayloadTypeReferenceContext::UserEntryFunction(e.as_entry_function_payload()) + }, + PayloadTypeReferenceMeta::Multisig(m) => { + PayloadTypeReferenceContext::Multisig(m.as_multisig_payload()) + }, + PayloadTypeReferenceMeta::AutomationRegistration => { + PayloadTypeReferenceContext::AutomationRegistration + }, }; + // Safe: txn_consensus_hash is always populated from HashValue::keccak_256_of or txn.hash(), + // both of which produce exactly 32 bytes. + let txn_consensus_hash: [u8; 32] = self + .txn_consensus_hash + .as_slice() + .try_into() + .expect("txn_consensus_hash is always a 32-byte Keccak-256 hash"); UserTransactionContext::new( self.sender, self.secondary_signers.clone(), @@ -227,6 +245,7 @@ impl TransactionMetadata { self.gas_unit_price.into(), self.chain_id.id(), payload_type_reference, + txn_consensus_hash, ) } } @@ -249,8 +268,10 @@ impl From<&AutomatedTransaction> for TransactionMetadata { script_hash: vec![], script_size: NumBytes::zero(), is_keyless: false, - payload_type_reference: PayloadTypeReferenceMeta::UserEntryFunction(txn.payload().clone().into_entry_function()), - txn_app_hash: txn.hash().to_vec(), + payload_type_reference: PayloadTypeReferenceMeta::UserEntryFunction( + txn.payload().clone().into_entry_function(), + ), + txn_consensus_hash: txn.hash().to_vec(), } } } diff --git a/aptos-move/aptos-vm/src/transaction_validation.rs b/aptos-move/aptos-vm/src/transaction_validation.rs index 4c64ed68999..97eff2af79f 100644 --- a/aptos-move/aptos-vm/src/transaction_validation.rs +++ b/aptos-move/aptos-vm/src/transaction_validation.rs @@ -6,7 +6,7 @@ use crate::{ errors::{convert_epilogue_error, convert_prologue_error, expect_only_successful_execution}, move_vm_ext::{AptosMoveResolver, SessionExt}, system_module_names::{ - EMIT_FEE_STATEMENT, MULTISIG_ACCOUNT_MODULE, TRANSACTION_FEE_MODULE, + EMIT_FEE_STATEMENT, EMIT_GAS_ASSESSMENT, MULTISIG_ACCOUNT_MODULE, TRANSACTION_FEE_MODULE, VALIDATE_MULTISIG_TRANSACTION, }, testing::{maybe_raise_injected_error, InjectedError}, @@ -18,9 +18,13 @@ use aptos_types::{ fee_statement::FeeStatement, move_utils::as_move_value::AsMoveValue, on_chain_config::Features, - transaction::{MultisigTransactionPayload, ReplayProtector, TransactionExecutableRef}, + transaction::{ + automation::AutomationTaskType, MultisigTransactionPayload, ReplayProtector, + TransactionExecutableRef, + }, }; use aptos_vm_logging::log_schema::AdapterLogSchema; +use aptos_vm_types::module_and_script_storage::module_storage::AptosModuleStorage; use fail::fail_point; use move_binary_format::errors::VMResult; use move_core_types::{ @@ -36,9 +40,6 @@ use move_vm_runtime::{ }; use move_vm_types::gas::UnmeteredGasMeter; use once_cell::sync::Lazy; -use aptos_types::transaction::automation::AutomationTaskType; -use aptos_vm_types::module_and_script_storage::module_storage::AptosModuleStorage; -use crate::system_module_names::EMIT_GAS_ASSESSMENT; pub static APTOS_TRANSACTION_VALIDATION: Lazy = Lazy::new(|| TransactionValidation { @@ -48,7 +49,8 @@ pub static APTOS_TRANSACTION_VALIDATION: Lazy = script_prologue_name: Identifier::new("script_prologue").unwrap(), multi_agent_prologue_name: Identifier::new("multi_agent_script_prologue").unwrap(), automated_txn_prologue_name: Identifier::new("automated_transaction_prologue").unwrap(), - automated_txn_prologue_v2_name: Identifier::new("automated_transaction_prologue_v2").unwrap(), + automated_txn_prologue_v2_name: Identifier::new("automated_transaction_prologue_v2") + .unwrap(), user_epilogue_name: Identifier::new("epilogue").unwrap(), user_epilogue_gas_payer_name: Identifier::new("epilogue_gas_payer").unwrap(), automated_txn_epilogue_name: Identifier::new("automated_transaction_epilogue").unwrap(), @@ -435,12 +437,10 @@ pub(crate) fn run_multisig_prologue( Some("Script payload not supported for multisig transactions".to_string()), )); }, - TransactionExecutableRef::AutomationRegistration(params) => { - bcs::to_bytes( - &MultisigTransactionPayload::AutomationRegistration(params.clone()), - ) - .map_err(|_| unreachable_error.clone())? - } + TransactionExecutableRef::AutomationRegistration(params) => bcs::to_bytes( + &MultisigTransactionPayload::AutomationRegistration(params.clone()), + ) + .map_err(|_| unreachable_error.clone())?, }; session @@ -475,9 +475,7 @@ pub(crate) fn run_automated_transaction_prologue( traversal_context: &mut TraversalContext, ) -> Result<(), VMStatus> { let txn_task_id = match txn_data.replay_protector { - ReplayProtector::SequenceNumber(seq_num) => { - seq_num - }, + ReplayProtector::SequenceNumber(seq_num) => seq_num, ReplayProtector::Nonce(_) => { unreachable!("AutomatedTransaction cannot have nonce") }, @@ -521,9 +519,7 @@ pub(crate) fn run_automated_transaction_prologue_v2( traversal_context: &mut TraversalContext, ) -> Result<(), VMStatus> { let txn_task_id = match txn_data.replay_protector { - ReplayProtector::SequenceNumber(seq_num) => { - seq_num - }, + ReplayProtector::SequenceNumber(seq_num) => seq_num, ReplayProtector::Nonce(_) => { unreachable!("AutomatedTransaction cannot have nonce") }, @@ -741,7 +737,7 @@ fn run_automated_txn_epilogue( serialize_values(&args), &mut UnmeteredGasMeter, traversal_context, - module_storage + module_storage, ) .map(|_return_vals| ()) .map_err(expect_no_verification_errors)?; @@ -752,10 +748,10 @@ fn run_automated_txn_epilogue( match task_type { AutomationTaskType::User => { emit_fee_statement(session, module_storage, fee_statement, traversal_context)?; - } + }, AutomationTaskType::System => { emit_as_gas_assessment(session, module_storage, fee_statement, traversal_context)?; - } + }, } } @@ -796,7 +792,7 @@ fn emit_as_gas_assessment( vec![bcs::to_bytes(&fee_statement).expect("Failed to serialize fee statement")], &mut UnmeteredGasMeter, traversal_context, - module_storage + module_storage, ) .map(|_return_vals| ()) } @@ -907,7 +903,7 @@ pub(crate) fn run_failure_epilogue( /// stored in the `TRANSACTION_VALIDATION_MODULE` on chain. pub(crate) fn run_automated_txn_failure_epilogue( session: &mut SessionExt, - module_storage: & impl AptosModuleStorage, + module_storage: &impl AptosModuleStorage, gas_remaining: Gas, fee_statement: FeeStatement, features: &Features, @@ -924,7 +920,7 @@ pub(crate) fn run_automated_txn_failure_epilogue( txn_data, task_type, features, - traversal_context + traversal_context, ) .or_else(|err| { expect_only_successful_execution( diff --git a/aptos-move/aptos-vm/src/validator_txns/dkg.rs b/aptos-move/aptos-vm/src/validator_txns/dkg.rs index 0de8b0e43ff..96489408b8d 100644 --- a/aptos-move/aptos-vm/src/validator_txns/dkg.rs +++ b/aptos-move/aptos-vm/src/validator_txns/dkg.rs @@ -5,18 +5,18 @@ use crate::{ aptos_vm::get_system_transaction_output, errors::expect_only_successful_execution, move_vm_ext::{AptosMoveResolver, SessionId}, - system_module_names::{FINISH_WITH_DKG_RESULT, RECONFIGURATION_WITH_DKG_MODULE}, - validator_txns::dkg::{ - ExecutionFailure::{Expected, Unexpected}, - ExpectedFailure::*, - }, - AptosVM, + system_module_names::{FINISH_WITH_DKG_RESULT, RECONFIGURATION_WITH_DKG_MODULE, SET_DKG_META}, + validator_txns::dkg::ExecutionFailure::{Expected, Unexpected}, + AptosVM, VMValidator, }; use aptos_types::{ - dkg::{DKGState, DKGTrait, DKGTranscript, DefaultDKG}, + dkg::{ + transactions::{DKGTransactionData, DKGTransactionType}, + DKGState, DKGTrait, DKGTranscript, DefaultDKG, + }, move_utils::as_move_value::AsMoveValue, - on_chain_config::{ConfigurationResource, OnChainConfig}, - transaction::TransactionStatus, + transaction::{ExecutionStatus, TransactionStatus}, + vm_status::DiscardedVMStatus, }; use aptos_vm_logging::log_schema::AdapterLogSchema; use aptos_vm_types::{ @@ -25,111 +25,87 @@ use aptos_vm_types::{ use move_core_types::{ account_address::AccountAddress, value::{serialize_values, MoveValue}, - vm_status::{AbortLocation, StatusCode, VMStatus}, + vm_status::VMStatus, }; use move_vm_runtime::module_traversal::{TraversalContext, TraversalStorage}; use move_vm_types::gas::UnmeteredGasMeter; -#[derive(Debug)] -enum ExpectedFailure { - // Move equivalent: `errors::invalid_argument(*)` - EpochNotCurrent = 0x10001, - TranscriptDeserializationFailed = 0x10002, - TranscriptVerificationFailed = 0x10003, - - // Move equivalent: `errors::invalid_state(*)` - MissingResourceDKGState = 0x30001, - MissingResourceInprogressDKGSession = 0x30002, - MissingResourceConfiguration = 0x30003, -} - enum ExecutionFailure { - Expected(ExpectedFailure), + Expected(DiscardedVMStatus), Unexpected(VMStatus), } impl AptosVM { - pub(crate) fn process_dkg_result( + pub(crate) fn process_dkg_transaction( &self, resolver: &impl AptosMoveResolver, module_storage: &impl AptosModuleStorage, log_context: &AdapterLogSchema, session_id: SessionId, - dkg_transcript: DKGTranscript, + dkg_transaction_data: DKGTransactionData, ) -> Result<(VMStatus, VMOutput), VMStatus> { - match self.process_dkg_result_inner( + match self.process_dkg_transaction_inner( resolver, module_storage, log_context, session_id, - dkg_transcript, + dkg_transaction_data, ) { Ok((vm_status, vm_output)) => Ok((vm_status, vm_output)), - Err(Expected(failure)) => { + Err(ExecutionFailure::Expected(status)) => { // Pretend we are inside Move, and expected failures are like Move aborts. Ok(( - VMStatus::MoveAbort(AbortLocation::Script, failure as u64), - VMOutput::empty_with_status(TransactionStatus::Discard(StatusCode::ABORTED)), + VMStatus::error(status, None), + VMOutput::empty_with_status(TransactionStatus::Discard(status)), )) }, - Err(Unexpected(vm_status)) => Err(vm_status), + Err(ExecutionFailure::Unexpected(vm_status)) => Err(vm_status), } } - fn process_dkg_result_inner( + fn process_dkg_transaction_inner( &self, resolver: &impl AptosMoveResolver, module_storage: &impl AptosModuleStorage, log_context: &AdapterLogSchema, session_id: SessionId, - dkg_node: DKGTranscript, + dkg_transaction: DKGTransactionData, ) -> Result<(VMStatus, VMOutput), ExecutionFailure> { - let dkg_state = - OnChainConfig::fetch_config(resolver).ok_or(Expected(MissingResourceDKGState))?; - let config_resource = ConfigurationResource::fetch_config(resolver) - .ok_or(Expected(MissingResourceConfiguration))?; - let DKGState { in_progress, .. } = dkg_state; - let in_progress_session_state = - in_progress.ok_or(Expected(MissingResourceInprogressDKGSession))?; - - // Check epoch number. - if dkg_node.metadata.epoch != config_resource.epoch() { - return Err(Expected(EpochNotCurrent)); + // Verify the dkg transaction before execution + if let Some(status) = self + .validate_dkg_validator_transaction(dkg_transaction.clone(), resolver) + .status() + { + return Err(ExecutionFailure::Expected(status)); } - // Deserialize transcript and verify it. - let pub_params = DefaultDKG::new_public_params(&in_progress_session_state.metadata); - let transcript = bcs::from_bytes::<::Transcript>( - dkg_node.transcript_bytes.as_slice(), - ) - .map_err(|_| Expected(TranscriptDeserializationFailed))?; - - DefaultDKG::verify_transcript(&pub_params, &transcript) - .map_err(|_| Expected(TranscriptVerificationFailed))?; + let (function_name, args) = match dkg_transaction.metadata().transaction_type() { + DKGTransactionType::DKGMeta => (SET_DKG_META, vec![dkg_transaction + .data_bytes() + .as_move_value()]), + DKGTransactionType::PublicKeyShares => (FINISH_WITH_DKG_RESULT, vec![ + MoveValue::Signer(AccountAddress::ONE), + dkg_transaction.data_bytes().as_move_value(), + ]), + }; // All check passed, invoke VM to publish DKG result on chain. let mut gas_meter = UnmeteredGasMeter; let mut session = self.new_session(resolver, session_id, None); - let args = vec![ - MoveValue::Signer(AccountAddress::ONE), - dkg_node.transcript_bytes.as_move_value(), - ]; let traversal_storage = TraversalStorage::new(); session .execute_function_bypass_visibility( &RECONFIGURATION_WITH_DKG_MODULE, - FINISH_WITH_DKG_RESULT, + function_name, vec![], serialize_values(&args), &mut gas_meter, &mut TraversalContext::new(&traversal_storage), module_storage, ) - .map_err(|e| { - expect_only_successful_execution(e, FINISH_WITH_DKG_RESULT.as_str(), log_context) - }) - .map_err(|r| Unexpected(r.unwrap_err()))?; + .map_err(|e| expect_only_successful_execution(e, function_name.as_str(), log_context)) + .map_err(|r| ExecutionFailure::Unexpected(r.unwrap_err()))?; let output = get_system_transaction_output( session, @@ -139,7 +115,7 @@ impl AptosVM { .map_err(Unexpected)? .change_set_configs, ) - .map_err(Unexpected)?; + .map_err(ExecutionFailure::Unexpected)?; Ok((VMStatus::Executed, output)) } diff --git a/aptos-move/aptos-vm/src/validator_txns/mod.rs b/aptos-move/aptos-vm/src/validator_txns/mod.rs index 483d1ae3349..388dbb4de6d 100644 --- a/aptos-move/aptos-vm/src/validator_txns/mod.rs +++ b/aptos-move/aptos-vm/src/validator_txns/mod.rs @@ -5,12 +5,12 @@ use crate::{ move_vm_ext::{AptosMoveResolver, SessionId}, AptosVM, }; -use aptos_types::validator_txn::ValidatorTransaction; +use aptos_types::{on_chain_config::FeatureFlag, validator_txn::ValidatorTransaction}; use aptos_vm_logging::log_schema::AdapterLogSchema; use aptos_vm_types::{ module_and_script_storage::module_storage::AptosModuleStorage, output::VMOutput, }; -use move_core_types::vm_status::VMStatus; +use move_core_types::vm_status::{StatusCode, VMStatus}; impl AptosVM { pub(crate) fn process_validator_transaction( @@ -22,8 +22,18 @@ impl AptosVM { ) -> Result<(VMStatus, VMOutput), VMStatus> { let session_id = SessionId::validator_txn(&txn); match txn { - ValidatorTransaction::DKGResult(dkg_node) => { - self.process_dkg_result(resolver, module_storage, log_context, session_id, dkg_node) + ValidatorTransaction::DKG(dkg_node) => { + if !self.features().is_enabled(FeatureFlag::SUPRA_DKG) { + return Err(VMStatus::error(StatusCode::FEATURE_UNDER_GATING, None)); + } + + self.process_dkg_transaction( + resolver, + module_storage, + log_context, + session_id, + dkg_node, + ) }, ValidatorTransaction::ObservedJWKUpdate(jwk_update) => self.process_jwk_update( resolver, @@ -32,6 +42,11 @@ impl AptosVM { session_id, jwk_update, ), + ValidatorTransaction::DKGResult(_) => Err(VMStatus::Error { + status_code: StatusCode::UNREACHABLE, + sub_status: None, + message: Some("Unsupported ValidatorTransaction variant".to_string()), + }), } } } diff --git a/aptos-move/aptos-vm/src/verifier/transaction_arg_validation.rs b/aptos-move/aptos-vm/src/verifier/transaction_arg_validation.rs index e9b18ed77ee..801e9bea3f1 100644 --- a/aptos-move/aptos-vm/src/verifier/transaction_arg_validation.rs +++ b/aptos-move/aptos-vm/src/verifier/transaction_arg_validation.rs @@ -46,13 +46,10 @@ pub(crate) struct FunctionId { type ConstructorMap = Lazy>; static OLD_ALLOWED_STRUCTS: ConstructorMap = Lazy::new(|| { - [( - "0x1::string::String", - FunctionId { - module_id: ModuleId::new(AccountAddress::ONE, Identifier::from(ident_str!("string"))), - func_name: ident_str!("utf8"), - }, - )] + [("0x1::string::String", FunctionId { + module_id: ModuleId::new(AccountAddress::ONE, Identifier::from(ident_str!("string"))), + func_name: ident_str!("utf8"), + })] .into_iter() .map(|(s, validator)| (s.to_string(), validator)) .collect() @@ -60,56 +57,32 @@ static OLD_ALLOWED_STRUCTS: ConstructorMap = Lazy::new(|| { static NEW_ALLOWED_STRUCTS: ConstructorMap = Lazy::new(|| { [ - ( - "0x1::string::String", - FunctionId { - module_id: ModuleId::new( - AccountAddress::ONE, - Identifier::from(ident_str!("string")), - ), - func_name: ident_str!("utf8"), - }, - ), - ( - "0x1::object::Object", - FunctionId { - module_id: ModuleId::new( - AccountAddress::ONE, - Identifier::from(ident_str!("object")), - ), - func_name: ident_str!("address_to_object"), - }, - ), - ( - "0x1::option::Option", - FunctionId { - module_id: ModuleId::new( - AccountAddress::ONE, - Identifier::from(ident_str!("option")), - ), - func_name: ident_str!("from_vec"), - }, - ), - ( - "0x1::fixed_point32::FixedPoint32", - FunctionId { - module_id: ModuleId::new( - AccountAddress::ONE, - Identifier::from(ident_str!("fixed_point32")), - ), - func_name: ident_str!("create_from_raw_value"), - }, - ), - ( - "0x1::fixed_point64::FixedPoint64", - FunctionId { - module_id: ModuleId::new( - AccountAddress::ONE, - Identifier::from(ident_str!("fixed_point64")), - ), - func_name: ident_str!("create_from_raw_value"), - }, - ), + ("0x1::string::String", FunctionId { + module_id: ModuleId::new(AccountAddress::ONE, Identifier::from(ident_str!("string"))), + func_name: ident_str!("utf8"), + }), + ("0x1::object::Object", FunctionId { + module_id: ModuleId::new(AccountAddress::ONE, Identifier::from(ident_str!("object"))), + func_name: ident_str!("address_to_object"), + }), + ("0x1::option::Option", FunctionId { + module_id: ModuleId::new(AccountAddress::ONE, Identifier::from(ident_str!("option"))), + func_name: ident_str!("from_vec"), + }), + ("0x1::fixed_point32::FixedPoint32", FunctionId { + module_id: ModuleId::new( + AccountAddress::ONE, + Identifier::from(ident_str!("fixed_point32")), + ), + func_name: ident_str!("create_from_raw_value"), + }), + ("0x1::fixed_point64::FixedPoint64", FunctionId { + module_id: ModuleId::new( + AccountAddress::ONE, + Identifier::from(ident_str!("fixed_point64")), + ), + func_name: ident_str!("create_from_raw_value"), + }), ] .into_iter() .map(|(s, validator)| (s.to_string(), validator)) diff --git a/aptos-move/e2e-benchmark/src/main.rs b/aptos-move/e2e-benchmark/src/main.rs index 58875a40b8c..85ba8a6a323 100644 --- a/aptos-move/e2e-benchmark/src/main.rs +++ b/aptos-move/e2e-benchmark/src/main.rs @@ -31,7 +31,7 @@ pub fn execute_txn( let sign_tx = account .transaction() .sequence_number(sequence_number) - .max_gas_amount(2_000_000) + .max_gas_amount(2_000_000_000) .gas_unit_price(200) .payload(payload) .sign(); diff --git a/aptos-move/e2e-move-tests/Cargo.toml b/aptos-move/e2e-move-tests/Cargo.toml index b7f49974f51..b827274dffd 100644 --- a/aptos-move/e2e-move-tests/Cargo.toml +++ b/aptos-move/e2e-move-tests/Cargo.toml @@ -31,6 +31,7 @@ aptos-vm = { workspace = true, features = ["testing"] } aptos-vm-environment = { workspace = true } bcs = { workspace = true } claims = { workspace = true } +crypto = { workspace = true } hex = { workspace = true } move-binary-format = { workspace = true } move-core-types = { workspace = true } diff --git a/aptos-move/e2e-move-tests/src/harness.rs b/aptos-move/e2e-move-tests/src/harness.rs index 63793ea7c4b..aec25ec2a71 100644 --- a/aptos-move/e2e-move-tests/src/harness.rs +++ b/aptos-move/e2e-move-tests/src/harness.rs @@ -40,7 +40,8 @@ use claims::assert_ok; use move_core_types::{ language_storage::{StructTag, TypeTag}, move_resource::MoveStructType, - value::MoveValue,vm_status::VMStatus + value::MoveValue, + vm_status::VMStatus, }; use move_package::package_hooks::register_package_hooks; use once_cell::sync::Lazy; @@ -56,7 +57,7 @@ use std::{ // Code representing successful transaction, used for run_block_in_parts_and_check pub const SUCCESS: u64 = 0; -const DEFAULT_GAS_UNIT_PRICE: u64 = 100; +const DEFAULT_GAS_UNIT_PRICE: u64 = 100000; static CACHED_BUILT_PACKAGES: Lazy>>>> = Lazy::new(|| Mutex::new(HashMap::new())); @@ -94,7 +95,7 @@ pub enum BlockSplit { } impl MoveHarness { - const DEFAULT_MAX_GAS_PER_TXN: u64 = 2_000_000; + const DEFAULT_MAX_GAS_PER_TXN: u64 = 100_000_000; /// Creates a new harness. pub fn new() -> Self { diff --git a/aptos-move/e2e-move-tests/src/lib.rs b/aptos-move/e2e-move-tests/src/lib.rs index f21cb3485b3..6037d857471 100644 --- a/aptos-move/e2e-move-tests/src/lib.rs +++ b/aptos-move/e2e-move-tests/src/lib.rs @@ -3,10 +3,11 @@ pub mod aggregator; pub mod aggregator_v2; -pub mod supra_governance; pub mod harness; pub mod resource_groups; pub mod stake; +pub mod supra_governance; +// pub mod transaction_fee; use anyhow::bail; use aptos_framework::UPGRADE_POLICY_CUSTOM_FIELD; @@ -24,7 +25,8 @@ impl PackageHooks for AptosPackageHooks { fn custom_package_info_fields(&self) -> Vec { vec![UPGRADE_POLICY_CUSTOM_FIELD.to_string()] } -// sbjoshi changed + + // sbjoshi changed fn custom_dependency_key(&self) -> Option { Some("supra".to_string()) } diff --git a/aptos-move/e2e-move-tests/src/stake.rs b/aptos-move/e2e-move-tests/src/stake.rs index 2f2af49f05d..791b8cf1727 100644 --- a/aptos-move/e2e-move-tests/src/stake.rs +++ b/aptos-move/e2e-move-tests/src/stake.rs @@ -3,15 +3,62 @@ use crate::harness::MoveHarness; use aptos_cached_packages::aptos_stdlib; -use aptos_crypto::{ed25519, PrivateKey, Uniform}; +use aptos_crypto::{ + bls12381, bls12381::ProofOfPossession, ed25519, PrivateKey, SigningKey, Uniform, +}; use aptos_language_e2e_tests::account::Account; use aptos_types::{ account_address::AccountAddress, account_config::CORE_CODE_ADDRESS, on_chain_config::ValidatorSet, stake_pool::StakePool, transaction::TransactionStatus, - validator_config::ValidatorConfig, + validator_config::ValidatorConfig, validator_public_keys::ValidatorPublicKeys, }; use move_core_types::parser::parse_struct_tag; +// Used for generating the consesus pub key while doing rotate consensus key +pub fn generate_consensus_pub_key() -> Vec { + let mut rng = rand::thread_rng(); + let network_key = ed25519::PrivateKey::generate_for_testing(); + let network_pubkey_bytes = network_key.public_key().to_bytes().to_vec(); + + let bls_key = bls12381::PrivateKey::generate(&mut rng); + let bls_pub_key = bls12381::PublicKey::from(&bls_key); + let bls_pubkey_bytes = bls_pub_key.to_bytes().to_vec(); + + let cg_pubkey_bytes = { + let mut cg_rng = crypto::bls12381::cl_utils::rng(); + crypto::bls12381::cg_encryption::keygen(&mut cg_rng, &[]) + .expect("CG keygen must succeed") + .1 + .to_vec() + }; + + let pop = ProofOfPossession::create_with_pubkey(&bls_key, &bls_pub_key); + let supra_ed_key = ed25519::PrivateKey::generate_for_testing(); + let supra_ed_pubkey_bytes = supra_ed_key.public_key().to_bytes().to_vec(); + + // When SUPRA_BLS_KEYS feature is enabled (default), the genesis validator key must be + // BCS-encoded ValidatorPublicKeys, not a plain ed25519 key. + let validator_public_keys = ValidatorPublicKeys::new( + network_pubkey_bytes, + bls_pubkey_bytes, + None, + None, + None, + None, + None, + None, + None, + cg_pubkey_bytes, + supra_ed_pubkey_bytes, + ); + let mut consensus_pubkey = + bcs::to_bytes(&validator_public_keys).expect("ValidatorPublicKeys must serialize"); + let mut pop_bytes = pop.to_bytes().to_vec(); + consensus_pubkey.append(&mut pop_bytes); + let consensus_pub_key_with_pop = consensus_pubkey; + consensus_pub_key_with_pop +} + pub fn setup_staking( harness: &mut MoveHarness, account: &Account, @@ -76,8 +123,8 @@ pub fn rotate_consensus_key( account: &Account, pool_address: AccountAddress, ) -> TransactionStatus { - let consensus_key = ed25519::PrivateKey::generate_for_testing(); - let consensus_pubkey = consensus_key.public_key().to_bytes().to_vec(); + // let consensus_key = ed25519::PrivateKey::generate_for_testing(); + let consensus_pubkey = generate_consensus_pub_key(); harness.run_transaction_payload( account, aptos_stdlib::stake_rotate_consensus_key(pool_address, consensus_pubkey), diff --git a/aptos-move/e2e-move-tests/src/supra_governance.rs b/aptos-move/e2e-move-tests/src/supra_governance.rs index 485a39da0c3..d0d73489e4e 100644 --- a/aptos-move/e2e-move-tests/src/supra_governance.rs +++ b/aptos-move/e2e-move-tests/src/supra_governance.rs @@ -53,9 +53,6 @@ pub fn supra_vote( ) -> TransactionStatus { harness.run_transaction_payload( account, - aptos_stdlib::supra_governance_supra_vote( - proposal_id, - should_pass, - ), + aptos_stdlib::supra_governance_supra_vote(proposal_id, should_pass), ) } diff --git a/aptos-move/e2e-move-tests/src/tests/account.rs b/aptos-move/e2e-move-tests/src/tests/account.rs index 2449cbab191..7970eccf6d9 100644 --- a/aptos-move/e2e-move-tests/src/tests/account.rs +++ b/aptos-move/e2e-move-tests/src/tests/account.rs @@ -1,10 +1,9 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::MoveHarness; +use crate::{assert_success, MoveHarness}; use aptos_cached_packages::aptos_stdlib::supra_account_transfer; use aptos_language_e2e_tests::account::Account; -use crate::assert_success; #[test] #[should_panic] // as we disabled the default account feature diff --git a/aptos-move/e2e-move-tests/src/tests/automation_registry.data/pack/Move.toml b/aptos-move/e2e-move-tests/src/tests/automation_registry.data/pack/Move.toml new file mode 100644 index 00000000000..91967340636 --- /dev/null +++ b/aptos-move/e2e-move-tests/src/tests/automation_registry.data/pack/Move.toml @@ -0,0 +1,11 @@ +[package] +name = "automation_registry_test" +version = "0.0.0" + +[addresses] +# A fixed address for the test contract simulating a third-party DeFi protocol. +automation_test = "0xDEADBEEF" + +[dependencies] +SupraFramework = { local = "../../../../../framework/supra-framework" } +AptosStdlib = { local = "../../../../../framework/aptos-stdlib" } diff --git a/aptos-move/e2e-move-tests/src/tests/automation_registry.data/pack/sources/automation_contract_test.move b/aptos-move/e2e-move-tests/src/tests/automation_registry.data/pack/sources/automation_contract_test.move new file mode 100644 index 00000000000..2e4427d4f76 --- /dev/null +++ b/aptos-move/e2e-move-tests/src/tests/automation_registry.data/pack/sources/automation_contract_test.move @@ -0,0 +1,32 @@ +/// Simulates a third-party smart contract (e.g. a DeFi protocol) that registers +/// automation tasks by calling the public `register_without_validation` API. +/// +/// In production a DeFi contract would call `automation_registry::register_without_validation` +/// from inside its own module logic. This module exposes a thin entry-function wrapper so +/// that the Rust e2e test harness can invoke it as a regular signed transaction. +module automation_test::automation_contract_test { + use supra_framework::automation_registry; + + /// Entry-function wrapper that delegates to `register_without_validation`. + /// All arguments are forwarded verbatim; the tx_hash is captured automatically + /// from the native transaction context inside the callee. + public entry fun register_via_contract( + owner: &signer, + payload_tx: vector, + expiry_time: u64, + max_gas_amount: u64, + gas_price_cap: u64, + automation_fee_cap_for_epoch: u64, + aux_data: vector>, + ) { + automation_registry::register_without_validation( + owner, + payload_tx, + expiry_time, + max_gas_amount, + gas_price_cap, + automation_fee_cap_for_epoch, + aux_data, + ) + } +} diff --git a/aptos-move/e2e-move-tests/src/tests/automation_registry.rs b/aptos-move/e2e-move-tests/src/tests/automation_registry.rs new file mode 100644 index 00000000000..5471e33b8f2 --- /dev/null +++ b/aptos-move/e2e-move-tests/src/tests/automation_registry.rs @@ -0,0 +1,287 @@ +// Copyright (c) Supra. +// SPDX-License-Identifier: Apache-2.0 + +//! E2E tests for the `register_without_validation` / `get_transaction_consensus_hash` feature +//! (SUPRA_AUTOMATION_V2_1). +//! +//! These tests exercise the full call chain: +//! signed transaction → VM → native `get_transaction_consensus_hash_internal` → Move registry storage +//! +//! and verify that the hash stored in the registry is the Keccak-256 of the BCS-serialised +//! `SignedTransaction` that triggered the registration. + +use crate::{assert_abort, assert_success, tests::common, MoveHarness}; +use aptos_crypto::HashValue; +use aptos_language_e2e_tests::account::Account; +use aptos_types::{ + move_utils::MemberId, + on_chain_config::FeatureFlag, + transaction::{automation::AutomationTaskMetaData, SignedTransaction}, +}; +use move_core_types::account_address::AccountAddress; + +// ----------------------------------------------------------------------- +// Stack-size helper +// ----------------------------------------------------------------------- + +/// Runs `f` on a thread with a 64 MB stack. +/// +/// Publishing the supra-framework package triggers deep recursive Move type-checking that +/// overflows the OS default stack (~8 MB). This wrapper ensures the compilation succeeds +/// regardless of the default stack size configured by the test runner. +fn run_on_large_stack(f: F) { + std::thread::Builder::new() + .stack_size(64 * 1024 * 1024) + .spawn(f) + .expect("spawning large-stack thread must not fail") + .join() + .expect("large-stack thread must not panic"); +} + +// ----------------------------------------------------------------------- +// Module-level abort code constant (mirrors Move's EDISABLED_AUTOMATION_FEATURE = 15) +// ----------------------------------------------------------------------- + +/// Raw abort code emitted by `automation_registry` when a required feature is disabled. +/// This is NOT wrapped with error::invalid_state — it is the plain u64 constant 15. +const EDISABLED_AUTOMATION_FEATURE: u64 = 15; + +// ----------------------------------------------------------------------- +// Module-level abort code constant (mirrors Move's EDISABLED_AUTOMATION_V2_1_FEATURE = 49) +// ----------------------------------------------------------------------- + +/// Raw abort code emitted by `automation_registry v2.1` when a required feature is disabled. +/// This is NOT wrapped with error::invalid_state — it is the plain u64 constant 49. +const EDISABLED_AUTOMATION_V2_1_FEATURE: u64 = 49; + +// ----------------------------------------------------------------------- +// Helpers +// ----------------------------------------------------------------------- + +/// Builds a harness with SUPRA_NATIVE_AUTOMATION and SUPRA_AUTOMATION_V2_1 enabled, +/// then transitions the automation cycle from CYCLE_READY to CYCLE_STARTED. +/// +/// At head-genesis SUPRA_NATIVE_AUTOMATION is absent from the default feature set, so the +/// registry is initialised in CYCLE_READY state. Calling `on_new_epoch` after enabling the +/// flag transitions the cycle to CYCLE_STARTED, which is required for registration to succeed. +fn setup_harness_with_v2_1() -> MoveHarness { + let mut h = MoveHarness::new_with_features( + vec![ + FeatureFlag::SUPRA_NATIVE_AUTOMATION, + FeatureFlag::SUPRA_AUTOMATION_V2_1, + ], + vec![], + ); + // Transition CYCLE_READY -> CYCLE_STARTED now that SUPRA_NATIVE_AUTOMATION is enabled. + h.executor + .exec("automation_registry", "on_new_epoch", vec![], vec![]); + h +} + +/// Same setup but deliberately *without* SUPRA_AUTOMATION_V2_1, to test the disabled path. +fn setup_harness_without_v2_1() -> MoveHarness { + let mut h = MoveHarness::new_with_features(vec![FeatureFlag::SUPRA_NATIVE_AUTOMATION], vec![ + FeatureFlag::SUPRA_AUTOMATION_V2_1, + ]); + h.executor + .exec("automation_registry", "on_new_epoch", vec![], vec![]); + h +} + +/// Deploys the third-party wrapper contract and returns the deployer account. +/// +/// The contract lives at `0xDEADBEEF` and exposes a `public entry fun register_via_contract` +/// that delegates to `automation_registry::register_without_validation`. This mimics the +/// real-world scenario where a DeFi protocol registers automation tasks through its own module. +fn deploy_wrapper(h: &mut MoveHarness) -> Account { + let addr = AccountAddress::from_hex_literal("0xDEADBEEF").unwrap(); + let account = h.new_account_with_balance_at(addr, 1_000_000_000_000_000); + assert_success!(h.publish_package_cache_building( + &account, + &common::test_dir_path("automation_registry.data/pack"), + )); + account +} + +/// Returns a new user account with enough balance to cover gas and registration/deposit fees. +fn new_funded_user(h: &mut MoveHarness) -> Account { + h.new_account_with_key_pair() +} + +/// A 64-byte dummy payload. `register_without_validation` does not validate the payload +/// bytes, so any non-empty vector is valid for unit-test purposes. +fn dummy_payload_bytes() -> Vec { + (0u8..64u8).collect() +} + +/// AUX data required by the registry for a user-submitted task (type byte = 0x01, empty priority). +fn user_aux_data() -> Vec> { + vec![vec![1u8], vec![]] +} + +/// Calls the `get_task_details(task_index)` view function and BCS-decodes the result. +fn get_task_details(h: &mut MoveHarness, task_index: u64) -> AutomationTaskMetaData { + let output = h.execute_view_function( + str::parse("0x1::automation_registry::get_task_details").unwrap(), + vec![], + vec![bcs::to_bytes(&task_index).unwrap()], + ); + let values = output + .values + .expect("get_task_details view call must succeed"); + bcs::from_bytes(&values[0]).expect("AutomationTaskMetaData must BCS-decode cleanly") +} + +/// Builds (but does not submit) the `register_via_contract` signed transaction. +/// +/// Returning the `SignedTransaction` before submission allows the caller to compute its +/// Keccak-256 hash and then verify that the same bytes end up stored in the registry. +fn build_register_txn(h: &mut MoveHarness, user: &Account, expiry_time: u64) -> SignedTransaction { + h.create_entry_function( + user, + str::parse("0xDEADBEEF::automation_contract_test::register_via_contract").unwrap(), + vec![], + vec![ + bcs::to_bytes(&dummy_payload_bytes()).unwrap(), + bcs::to_bytes(&expiry_time).unwrap(), + bcs::to_bytes(&10_000u64).unwrap(), // max_gas_amount + bcs::to_bytes(&100u64).unwrap(), // gas_price_cap + bcs::to_bytes(&1_000u64).unwrap(), // automation_fee_cap_for_epoch + bcs::to_bytes(&user_aux_data()).unwrap(), + ], + ) +} + +// ----------------------------------------------------------------------- +// E2E Tests +// ----------------------------------------------------------------------- + +/// Verifies that `tx_hash` stored in the registry is exactly the Keccak-256 hash of the +/// BCS-serialised `SignedTransaction` that called `register_via_contract`. +/// +/// This is the primary correctness test for the entire feature: +/// 1. `get_transaction_consensus_hash_internal` (native) reads `txn_consensus_hash` from the +/// `UserTransactionContext` populated by `TransactionMetadata::new()`. +/// 2. `register_without_validation` forwards this hash to the private `register()` call. +/// 3. `register()` stores it in `AutomationTaskMetaData.tx_hash`. +/// 4. We verify the stored value equals what we compute independently of the same bytes +/// before submission. +#[test] +fn test_register_without_validation_hash_matches_txn() { + run_on_large_stack(|| { + let mut h = setup_harness_with_v2_1(); + deploy_wrapper(&mut h); + let user = new_funded_user(&mut h); + + // Expiry must exceed current time (genesis = 0 s) plus at least one cycle (7 200 s). + let expiry_time = 7_200u64 + 86_400; + + // Build the transaction *without* submitting it so we can hash it before the VM sees it. + let signed_txn: SignedTransaction = build_register_txn(&mut h, &user, expiry_time); + + // Compute the expected hash: mirrors TransactionMetadata::new() in transaction_metadata.rs + let expected_hash = HashValue::keccak_256_of( + &bcs::to_bytes(&signed_txn) + .expect("SignedTransaction must always BCS-serialize successfully"), + ); + + // Submit the transaction and assert it succeeds. + let output = h.run_raw(signed_txn); + assert_success!(output.status().to_owned()); + + // Read the task that was just registered (first task ever → task index 0). + let task = get_task_details(&mut h, 0); + + assert_eq!( + task.tx_hash().as_slice(), + expected_hash.as_ref(), + "tx_hash in registry must equal the Keccak-256 of the registering SignedTransaction" + ); + }); +} + +/// Happy-path test: a third-party smart contract calls `register_without_validation` and the +/// task is written to the registry with the correct owner and a 32-byte tx_hash. +/// +/// This exercises the public API surface that DeFi protocols are intended to use. +#[test] +fn test_register_without_validation_from_smart_contract() { + run_on_large_stack(|| { + let mut h = setup_harness_with_v2_1(); + deploy_wrapper(&mut h); + let user = new_funded_user(&mut h); + + let expiry_time = 7_200u64 + 86_400; + let status = h.run_entry_function( + &user, + str::parse("0xDEADBEEF::automation_contract_test::register_via_contract").unwrap(), + vec![], + vec![ + bcs::to_bytes(&dummy_payload_bytes()).unwrap(), + bcs::to_bytes(&expiry_time).unwrap(), + bcs::to_bytes(&10_000u64).unwrap(), + bcs::to_bytes(&100u64).unwrap(), + bcs::to_bytes(&1_000u64).unwrap(), + bcs::to_bytes(&user_aux_data()).unwrap(), + ], + ); + assert_success!(status); + + // Verify task owner. + let task = get_task_details(&mut h, 0); + assert_eq!( + task.owner(), + user.address(), + "task owner must be the account that submitted the transaction" + ); + + // Verify the tx_hash field is a 32-byte Keccak-256 digest. + assert_eq!( + task.tx_hash().len(), + 32, + "tx_hash must be a 32-byte Keccak-256 digest" + ); + + // Verify exactly one task was registered (next index = 1). + let idx_output = h.execute_view_function( + str::parse("0x1::automation_registry::get_next_task_index").unwrap(), + vec![], + vec![], + ); + let values = idx_output + .values + .expect("get_next_task_index view call must succeed"); + let next_index: u64 = bcs::from_bytes(&values[0]).expect("decode task index"); + assert_eq!(next_index, 1, "exactly one task should be registered"); + }); +} + +/// Verifies that calling `register_via_contract` when SUPRA_AUTOMATION_V2_1 is disabled +/// aborts with EDISABLED_AUTOMATION_V2_1_FEATURE = 49. +/// +/// This ensures the feature gate in `register_without_validation` is enforced and that +/// the function cannot be used before the binary upgrade is rolled out to all nodes. +#[test] +fn test_register_without_validation_feature_disabled_aborts() { + run_on_large_stack(|| { + let mut h = setup_harness_without_v2_1(); + deploy_wrapper(&mut h); + let user = new_funded_user(&mut h); + + let expiry_time = 7_200u64 + 86_400; + let status = h.run_entry_function( + &user, + str::parse("0xDEADBEEF::automation_contract_test::register_via_contract").unwrap(), + vec![], + vec![ + bcs::to_bytes(&dummy_payload_bytes()).unwrap(), + bcs::to_bytes(&expiry_time).unwrap(), + bcs::to_bytes(&10_000u64).unwrap(), + bcs::to_bytes(&100u64).unwrap(), + bcs::to_bytes(&1_000u64).unwrap(), + bcs::to_bytes(&user_aux_data()).unwrap(), + ], + ); + assert_abort!(status, EDISABLED_AUTOMATION_V2_1_FEATURE); + }); +} diff --git a/aptos-move/e2e-move-tests/src/tests/fee_payer.rs b/aptos-move/e2e-move-tests/src/tests/fee_payer.rs index c60b5f8b4b2..586a2367c7b 100644 --- a/aptos-move/e2e-move-tests/src/tests/fee_payer.rs +++ b/aptos-move/e2e-move-tests/src/tests/fee_payer.rs @@ -93,7 +93,7 @@ fn test_existing_account_with_fee_payer_aborts() { let output = h.run_raw(transaction); // Alice has an insufficient balance, trying to 1 when she has 0. - assert_abort!(output.status(), 65540); + assert_abort!(output.status(), 65542); let alice_after = h.read_aptos_balance(alice.address()); let bob_after = h.read_aptos_balance(bob.address()); @@ -341,9 +341,16 @@ fn test_account_not_exist_move_abort_with_fee_payer_out_of_gas() { #[test] fn test_account_not_exist_with_fee_payer_without_create_account() { - let mut h = MoveHarness::new_with_features(vec![FeatureFlag::GAS_PAYER_ENABLED], vec![ - FeatureFlag::SPONSORED_AUTOMATIC_ACCOUNT_V1_CREATION, - ]); + // Note: (DP) + // Both this feature needs to be enabled as default account feature is disabled. + // If we turn on default account feature then it is fine if sponsored feature is disabled. + let mut h = MoveHarness::new_with_features( + vec![ + FeatureFlag::GAS_PAYER_ENABLED, + FeatureFlag::SPONSORED_AUTOMATIC_ACCOUNT_V1_CREATION, + ], + vec![], + ); let alice = Account::new(); let bob = h.new_account_at(AccountAddress::from_hex_literal("0xb0b").unwrap()); @@ -359,8 +366,8 @@ fn test_account_not_exist_with_fee_payer_without_create_account() { .fee_payer(bob.clone()) .payload(payload) .sequence_number(0) - .max_gas_amount(1_000_000) - .gas_unit_price(1) + .max_gas_amount(1_500) + .gas_unit_price(100_000) .sign_fee_payer(); let output = h.run_raw(transaction); diff --git a/aptos-move/e2e-move-tests/src/tests/fungible_asset.rs b/aptos-move/e2e-move-tests/src/tests/fungible_asset.rs index 5b435a62480..bd2ab5ba862 100644 --- a/aptos-move/e2e-move-tests/src/tests/fungible_asset.rs +++ b/aptos-move/e2e-move-tests/src/tests/fungible_asset.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{assert_success, tests::common, BlockSplit, MoveHarness, SUCCESS}; -use aptos_cached_packages::aptos_stdlib::{supra_account_batch_transfer, aptos_coin_transfer}; +use aptos_cached_packages::aptos_stdlib::{aptos_coin_transfer, supra_account_batch_transfer}; use aptos_language_e2e_tests::{ account::Account, executor::{ExecutorMode, FakeExecutor}, @@ -18,10 +18,6 @@ use move_core_types::{ use once_cell::sync::Lazy; use serde::Deserialize; use std::str::FromStr; -use aptos_cached_packages::aptos_stdlib; -use aptos_language_e2e_tests::account::TransactionBuilder; -use aptos_types::account_config::AccountResource; -use move_core_types::move_resource::MoveStructType; #[derive(Debug, Deserialize, Eq, PartialEq)] struct FungibleStore { @@ -264,7 +260,7 @@ fn test_prologue_speculation() { let sink_txn = harness.create_transaction_payload( &independent_account, - supra_account_batch_transfer(vec![AccountAddress::random(); 50], vec![10_000_000_000; 50]), + supra_account_batch_transfer(vec![AccountAddress::random(); 50], vec![10_000; 50]), ); let account = harness.new_account_at(AccountAddress::ONE); @@ -276,7 +272,7 @@ fn test_prologue_speculation() { &account, supra_account_batch_transfer( vec![*dst_1.address(), *dst_2.address(), *dst_3.address()], - vec![10_000_000_000, 10_000_000_000, 10_000_000_000], + vec![10_000_100_000_000, 10_000_100_000_000, 10_000_100_000_000], ), ); diff --git a/aptos-move/e2e-move-tests/src/tests/keyless_feature_gating.rs b/aptos-move/e2e-move-tests/src/tests/keyless_feature_gating.rs index ffa5d70f50e..5fc23f89910 100644 --- a/aptos-move/e2e-move-tests/src/tests/keyless_feature_gating.rs +++ b/aptos-move/e2e-move-tests/src/tests/keyless_feature_gating.rs @@ -493,8 +493,8 @@ fn run_jwk_and_config_script(h: &mut MoveHarness) -> Account { TransactionArgument::U64(config.max_exp_horizon_secs), ])) .sequence_number(h.sequence_number(core_resources.address())) - .max_gas_amount(1_000_000) - .gas_unit_price(1) + .max_gas_amount(15_000_000) + .gas_unit_price(100_000) .sign(); // NOTE: We cannot write the Configuration and Groth16Verification key via MoveHarness::set_resource @@ -573,7 +573,7 @@ fn federated_keyless_install_jwk( )) .sequence_number(h.sequence_number(jwk_owner_account.address())) .max_gas_amount(1_000_000) - .gas_unit_price(1) + .gas_unit_price(100_000) .sign(); // NOTE: We cannot write the Configuration and Groth16Verification key via MoveHarness::set_resource @@ -604,8 +604,8 @@ fn run_upgrade_vk_script(h: &mut MoveHarness, core_resources: Account, vk: Groth TransactionArgument::U8Vector(vk.gamma_abc_g1[1].clone()), ])) .sequence_number(h.sequence_number(core_resources.address())) - .max_gas_amount(1_000_000) - .gas_unit_price(1) + .max_gas_amount(2_500_000) + .gas_unit_price(100_000) .sign(); // NOTE: We cannot write the Groth16Verification key via MoveHarness::set_resource diff --git a/aptos-move/e2e-move-tests/src/tests/mod.rs b/aptos-move/e2e-move-tests/src/tests/mod.rs index ae60a3edf46..9117965d4e5 100644 --- a/aptos-move/e2e-move-tests/src/tests/mod.rs +++ b/aptos-move/e2e-move-tests/src/tests/mod.rs @@ -11,6 +11,7 @@ mod aggregator_v2_function_values; mod aggregator_v2_runtime_checks; mod any; mod attributes; +mod automation_registry; mod bcs; mod chain_id; mod code_publishing; diff --git a/aptos-move/e2e-move-tests/src/tests/per_category_gas_limits.data/test/Move.toml b/aptos-move/e2e-move-tests/src/tests/per_category_gas_limits.data/test/Move.toml index f0123a1a751..d37cbbbda4b 100644 --- a/aptos-move/e2e-move-tests/src/tests/per_category_gas_limits.data/test/Move.toml +++ b/aptos-move/e2e-move-tests/src/tests/per_category_gas_limits.data/test/Move.toml @@ -5,4 +5,3 @@ version = "0.0.0" [dependencies] MoveStdlib = { local = "../../../../../framework/move-stdlib" } AptosStdlib = { local = "../../../../../framework/aptos-stdlib" } - diff --git a/aptos-move/e2e-move-tests/src/tests/scripts.rs b/aptos-move/e2e-move-tests/src/tests/scripts.rs index b6a94c0ad68..d11c687c1d1 100644 --- a/aptos-move/e2e-move-tests/src/tests/scripts.rs +++ b/aptos-move/e2e-move-tests/src/tests/scripts.rs @@ -99,7 +99,7 @@ fn test_script_with_object_parameter() { .script(script.clone()) .sequence_number(13) .max_gas_amount(1_000_000) - .gas_unit_price(1) + .gas_unit_price(100_000) .sign(); let status = h.run(txn); @@ -111,7 +111,7 @@ fn test_script_with_object_parameter() { .script(script.clone()) .sequence_number(14) .max_gas_amount(1_000_000) - .gas_unit_price(1) + .gas_unit_price(100_000) .sign(); let status = h.run(txn); diff --git a/aptos-move/e2e-move-tests/src/tests/stake.data/update_rewards_config/Move.toml b/aptos-move/e2e-move-tests/src/tests/stake.data/update_rewards_config/Move.toml index a9fced9b015..71a6210a894 100644 --- a/aptos-move/e2e-move-tests/src/tests/stake.data/update_rewards_config/Move.toml +++ b/aptos-move/e2e-move-tests/src/tests/stake.data/update_rewards_config/Move.toml @@ -1,5 +1,5 @@ [package] -name = 'FederatedKeylessInitConfig' +name = 'EnableRewardsRateDecrease' version = "0.0.0" [dependencies] diff --git a/aptos-move/e2e-move-tests/src/tests/stake.data/update_rewards_config/sources/main.move b/aptos-move/e2e-move-tests/src/tests/stake.data/update_rewards_config/sources/main.move index 2c621aec210..4d85798f7b3 100644 --- a/aptos-move/e2e-move-tests/src/tests/stake.data/update_rewards_config/sources/main.move +++ b/aptos-move/e2e-move-tests/src/tests/stake.data/update_rewards_config/sources/main.move @@ -2,6 +2,7 @@ script { use supra_framework::supra_governance; use supra_framework::staking_config; use aptos_std::fixed_point64; + use std::features; fun main(core_resources: &signer) { let framework_signer = supra_governance::get_signer_testnet_only(core_resources, @supra_framework); @@ -12,6 +13,8 @@ script { 365 * 24 * 60 * 60, fixed_point64::create_from_rational(50, 100), ); + let feature = features::get_periodical_reward_rate_decrease_feature(); + features::change_feature_flags_for_next_epoch(&framework_signer, vector[feature], vector[]); supra_governance::force_end_epoch(&framework_signer); } } diff --git a/aptos-move/e2e-move-tests/src/tests/stake.rs b/aptos-move/e2e-move-tests/src/tests/stake.rs index 8b7f3db6986..0965f9d8d92 100644 --- a/aptos-move/e2e-move-tests/src/tests/stake.rs +++ b/aptos-move/e2e-move-tests/src/tests/stake.rs @@ -191,6 +191,7 @@ fn test_staking_rewards() { harness.new_block_with_metadata(validator_2_address, vec![]); // Enable rewards rate decrease and change rewards config. In production it requires governance. + // This also enables the feature as by default is is disabled. let core_resources = harness.new_account_at(AccountAddress::from_hex_literal("0xA550C18").unwrap()); let script_code = PROPOSAL_SCRIPTS diff --git a/aptos-move/e2e-move-tests/src/tests/storage_refund.rs b/aptos-move/e2e-move-tests/src/tests/storage_refund.rs index 80fb3e67dc5..0b466423f80 100644 --- a/aptos-move/e2e-move-tests/src/tests/storage_refund.rs +++ b/aptos-move/e2e-move-tests/src/tests/storage_refund.rs @@ -93,7 +93,7 @@ fn test_refunds() { assert_result(&mut h, &user_acc, "destroy_collection", vec![], 0, false); } -const LEEWAY: u64 = 2000; +const LEEWAY: u64 = 2000000; // need to 1000x as per gas price fn read_slot_fee_from_gas_schedule(h: &MoveHarness) -> u64 { let slot_fee = h diff --git a/aptos-move/e2e-move-tests/src/tests/transaction_context.rs b/aptos-move/e2e-move-tests/src/tests/transaction_context.rs index 300a362fde4..1042f5f0f2e 100644 --- a/aptos-move/e2e-move-tests/src/tests/transaction_context.rs +++ b/aptos-move/e2e-move-tests/src/tests/transaction_context.rs @@ -254,7 +254,7 @@ fn test_transaction_context_max_gas_amount() { let account = setup(&mut harness); let max_gas_amount = call_get_max_gas_amount_from_native_txn_context(&mut harness, &account); - assert_eq!(max_gas_amount, 2000000); + assert_eq!(max_gas_amount, 100000000); } #[test] @@ -263,7 +263,7 @@ fn test_transaction_context_gas_unit_price() { let account = setup(&mut harness); let max_gas_amount = call_get_gas_unit_price_from_native_txn_context(&mut harness, &account); - assert_eq!(max_gas_amount, 100); + assert_eq!(max_gas_amount, 100000); } #[test] @@ -343,7 +343,7 @@ fn test_transaction_context_secondary_signers() { let mut harness = new_move_harness(); let alice = setup(&mut harness); - let bob = harness.new_account_with_balance_and_sequence_number(1000000, 0); + let bob = harness.new_account_with_balance_and_sequence_number(100_000_000_000, 0); let fun: MemberId = str::parse( "0x1::transaction_context_test::store_secondary_signers_from_native_txn_context_multi", @@ -366,7 +366,7 @@ fn test_transaction_context_secondary_signers() { .payload(payload) .sequence_number(harness.sequence_number(alice.address())) .max_gas_amount(1_000_000) - .gas_unit_price(1) + .gas_unit_price(100_000) .sign_multi_agent(); let output = harness.run_raw(transaction); diff --git a/aptos-move/e2e-tests/Cargo.toml b/aptos-move/e2e-tests/Cargo.toml index 305d8d48304..059e72bca46 100644 --- a/aptos-move/e2e-tests/Cargo.toml +++ b/aptos-move/e2e-tests/Cargo.toml @@ -17,7 +17,7 @@ anyhow = { workspace = true } aptos-abstract-gas-usage = { workspace = true } aptos-bitvec = { workspace = true } aptos-block-executor = { workspace = true } -aptos-cached-packages ={ workspace = true } +aptos-cached-packages = { workspace = true } aptos-crypto = { workspace = true, features = ["fuzzing"] } aptos-framework = { workspace = true } aptos-gas-algebra = { workspace = true } diff --git a/aptos-move/e2e-tests/src/executor.rs b/aptos-move/e2e-tests/src/executor.rs index 52a5c7d3792..3d5184ec2ee 100644 --- a/aptos-move/e2e-tests/src/executor.rs +++ b/aptos-move/e2e-tests/src/executor.rs @@ -56,7 +56,7 @@ use aptos_types::{ }, vm_status::VMStatus, write_set::{WriteOp, WriteSet, WriteSetMut}, - SupraCoinType, CoinType, + CoinType, SupraCoinType, }; use aptos_validator_interface::{DebuggerStateView, RestDebuggerInterface}; use aptos_vm::{ @@ -715,8 +715,14 @@ impl FakeExecutor { /// Executes the transaction as a singleton block and applies the resulting write set to the /// data store. Panics if execution fails pub fn execute_and_apply_transaction(&mut self, transaction: Transaction) -> TransactionOutput { - let mut outputs = self.execute_transaction_block(vec![transaction]).unwrap(); + let mut outputs = self + .execute_transaction_block(vec![transaction.clone()]) + .unwrap(); assert_eq!(outputs.len(), 1, "transaction outputs size mismatch"); + println!( + "transaction execution output: {:#?} : {:#?}", + outputs, transaction + ); let output = outputs.pop().unwrap(); match output.status() { TransactionStatus::Keep(status) => { @@ -735,8 +741,9 @@ impl FakeExecutor { assert_eq!( status, &ExecutionStatus::Success, - "transaction failed with {:?}", - status + "transaction failed with {:?}, {:?}", + status, + transaction ); output }, @@ -1329,7 +1336,12 @@ impl FakeExecutor { .as_ref() .unwrap() .change_set_configs; - finish_session_assert_no_modules(session, &module_storage, change_set_configs) + finish_session_assert_no_modules( + session, + &module_storage, + change_set_configs, + &resolver, + ) }; self.state_store.apply_write_set(&write_set).unwrap(); @@ -1383,6 +1395,7 @@ impl FakeExecutor { session, &module_storage, &ChangeSetConfigs::unlimited_at_gas_feature_version(env.gas_feature_version()), + &resolver, ) }; self.state_store.apply_write_set(&write_set).unwrap(); @@ -1420,6 +1433,7 @@ impl FakeExecutor { session, &module_storage, &ChangeSetConfigs::unlimited_at_gas_feature_version(env.gas_feature_version()), + &resolver, )) } @@ -1466,11 +1480,18 @@ fn finish_session_assert_no_modules( session: SessionExt, module_storage: &impl AptosModuleStorage, change_set_configs: &ChangeSetConfigs, + resolver: &impl AptosMoveResolver, ) -> (WriteSet, Vec) { - let change_set = session + let mut change_set = session .finish(change_set_configs, module_storage) .expect("Failed to finish the session"); - + // Aggregator V1 deltas must be materialized before converting to a storage ChangeSet, + // mirroring what the block executor does via legacy_sequential_materialize_agg_v1. + // This is needed when coin operations go through the FA migration path (fungible_asset_to_coin + // calls mint_internal which increments the optional_aggregator supply as a delta). + change_set + .try_materialize_aggregator_v1_delta_set(resolver) + .expect("Failed to materialize aggregator V1 deltas"); change_set .try_combine_into_storage_change_set(ModuleWriteSet::empty()) .expect("Failed to convert to storage ChangeSet") diff --git a/aptos-move/e2e-testsuite/Cargo.toml b/aptos-move/e2e-testsuite/Cargo.toml index ff0633b3868..be62b299152 100644 --- a/aptos-move/e2e-testsuite/Cargo.toml +++ b/aptos-move/e2e-testsuite/Cargo.toml @@ -36,7 +36,7 @@ serde = { workspace = true, features = ["derive"] } [features] default = [ - "aptos-cached-packages/fuzzing", - "move-core-types/fuzzing", - "aptos-types/fuzzing", + "aptos-cached-packages/fuzzing", + "move-core-types/fuzzing", + "aptos-types/fuzzing", ] diff --git a/aptos-move/e2e-testsuite/src/lib.rs b/aptos-move/e2e-testsuite/src/lib.rs index 846eaede9b1..8b78ef3e9ed 100644 --- a/aptos-move/e2e-testsuite/src/lib.rs +++ b/aptos-move/e2e-testsuite/src/lib.rs @@ -1,5 +1,11 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 +// The proptest `Arbitrary` strategy for the generated `EntryFunctionCall` enum (see +// `transaction_fuzzer`) builds a `TupleUnionValueTree` whose layout computation recurses once +// per enum variant. After the framework upgrade added more entry functions, the default limit +// of 128 is exceeded ("queries overflow the depth limit!"), so raise it for this crate. +#![recursion_limit = "256"] + #[cfg(test)] mod tests; diff --git a/aptos-move/e2e-testsuite/src/tests/automated_transactions.rs b/aptos-move/e2e-testsuite/src/tests/automated_transactions.rs index 77cae7d886e..2201536620b 100644 --- a/aptos-move/e2e-testsuite/src/tests/automated_transactions.rs +++ b/aptos-move/e2e-testsuite/src/tests/automated_transactions.rs @@ -1,6 +1,3 @@ -// Copyright (c) Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - // Copyright (c) 2024 Supra. // SPDX-License-Identifier: Apache-2.0 @@ -9,13 +6,156 @@ use aptos_cached_packages::aptos_framework_sdk_builder; use aptos_crypto::HashValue; use aptos_types::{ chain_id::ChainId, - on_chain_config::AutomationCycleState, + on_chain_config::{AutomationCycleState, FeatureFlag}, transaction::{ - automated_transaction::{AutomatedTransaction, AutomatedTransactionBuilder, BuilderResult}, - ExecutionStatus, Transaction, TransactionStatus, + automated_transaction::{ + AutomatedTransaction, AutomatedTransactionBuilder, AutomatedTransactionDescriptor, + BuilderResult, + }, + automation::AutomationTaskType, + EntryFunction, ExecutionStatus, Transaction, TransactionStatus, }, }; -use move_core_types::vm_status::StatusCode; +use move_core_types::{ + account_address::AccountAddress, identifier::Identifier, language_storage::ModuleId, + vm_status::StatusCode, +}; + +// ───────────────────────────────────────────────────────────────────────────── +// Shared test constants +// ───────────────────────────────────────────────────────────────────────────── + +/// Number of seconds by which a test must advance the chain clock to trigger a +/// cycle transition (CYCLE_STARTED → CYCLE_FINISHED). +const CYCLE_ADVANCE_SECS: u64 = 1200; + +/// Automation-fee cap (in quants) used when registering test tasks. +/// Large enough to satisfy the estimated-fee assertion inside `register`. +const AUTOMATION_FEE_CAP: u64 = 100_000; + +/// Max-gas amount and gas-price cap used for test tasks. Small enough that +/// `gas_price_cap × max_gas_amount` (10 000) is well within the test sender's +/// initial balance of 100 billion tokens, so the gas-balance prologue check +/// passes even after deducting registration fees. +const TASK_MAX_GAS_AMOUNT: u64 = 1_000; +const TASK_GAS_PRICE_CAP: u64 = 100; + +/// A canonical 32-byte dummy transaction hash used as the `tx_hash` field +/// when registering tasks via the bypass helper. The prologue does not check +/// this field, so any 32-byte value is valid. +const DUMMY_TX_HASH: [u8; 32] = [42u8; 32]; + +/// Auxiliary data for a User-Submitted Task (UST) with no explicit priority. +/// Format required by `check_and_validate_aux_data` in `automation_registry.move`: +/// - element 0: `[1u8]` → task type byte (1 = UST) +/// - element 1: `[]` → empty priority → registry auto-assigns task_index +fn ust_aux_data() -> Vec> { + // UST type byte = 1 (mirrors `const UST: u8 = 1` in automation_registry.move) + vec![vec![1u8], vec![]] +} + +// ───────────────────────────────────────────────────────────────────────────── +// Helper: build an EntryFunction that references a module which does NOT exist +// in the framework. +// +// The resulting BCS bytes are well-formed (`bcs::from_bytes::` +// succeeds) but when the automated-transaction processor calls +// `load_and_validate_entry_function` the VM cannot find the module and returns +// `StatusCode::INVALID_AUTOMATION_INNER_PAYLOAD`. +// ───────────────────────────────────────────────────────────────────────────── +fn make_nonexistent_entry_function() -> EntryFunction { + EntryFunction::new( + ModuleId::new( + // 0x0 never has user modules deployed; "phantom_automation_mod" is + // deliberately absent from the genesis framework. + AccountAddress::ZERO, + Identifier::new("phantom_automation_mod").expect("identifier must be valid"), + ), + Identifier::new("phantom_fn").expect("identifier must be valid"), + vec![], // no type arguments + vec![], // no runtime arguments (function signature is irrelevant — it doesn't exist) + ) +} + +// ───────────────────────────────────────────────────────────────────────────── +// Helper: activate the first registered task (task index 0). +// +// Steps: +// 1. Advance the chain clock by CYCLE_ADVANCE_SECS to move the cycle into +// CYCLE_FINISHED state. +// 2. Submit the registry-action transaction that transitions the cycle back +// to CYCLE_STARTED and marks task 0 as ACTIVE. +// ───────────────────────────────────────────────────────────────────────────── +fn activate_first_task(ctx: &mut AutomationRegistrationTestContext) { + ctx.advance_chain_time_in_secs(CYCLE_ADVANCE_SECS); + + let cycle_info = ctx.get_cycle_info(); + assert_eq!( + cycle_info.state, + AutomationCycleState::FINISHED, + "cycle must be FINISHED before it can be restarted" + ); + + let registry_action = + ctx.create_automation_registry_transaction(0, cycle_info.index + 1, 1, vec![0]); + ctx.execute_and_apply_transaction(Transaction::AutomationRegistryTransaction(registry_action)); + + let cycle_info = ctx.get_cycle_info(); + assert_eq!( + cycle_info.state, + AutomationCycleState::STARTED, + "cycle must be STARTED after the registry action" + ); +} + +// ───────────────────────────────────────────────────────────────────────────── +// Helper: build an AutomatedTransactionDescriptor for task 0 using the given +// entry function and gas-unit price. +// +// The `entry_fn` parameter is decoupled from the registry's `payload_tx` bytes +// intentionally: this lets tests inject an invalid entry function into the +// automated transaction even when the stored bytes might differ, or use the +// canonical entry function fetched from the registry for positive-path tests. +// ───────────────────────────────────────────────────────────────────────────── +fn build_automated_txn( + ctx: &mut AutomationRegistrationTestContext, + task_index: u64, + entry_fn: EntryFunction, + gas_unit_price: u64, + expiry_time: u64, +) -> AutomatedTransactionDescriptor { + // The authenticator is the stored tx_hash from the registry task. It is + // used only to populate TransactionMetadata.authentication_key; the prologue + // does not validate it, so using the same DUMMY_TX_HASH works here. + let authenticator = HashValue::new(DUMMY_TX_HASH); + let sender_address = ctx.sender_account_address(); + + let result = AutomatedTransactionBuilder::default() + .with_sender(sender_address) + .with_sequence_number(task_index) + .with_entry_function(entry_fn) + .with_max_gas_amount(TASK_MAX_GAS_AMOUNT) + .with_gas_price_cap(TASK_GAS_PRICE_CAP) + .with_expiration_timestamp_secs(expiry_time) + .with_authenticator(authenticator) + // Priority must match the auto-assigned value (= task_index) so that + // the AutomatedTransactionDescriptor is valid. + .with_task_priority(task_index) + .with_task_type(AutomationTaskType::User) + .with_chain_id(ChainId::test()) + .with_block_height(1) + .with_gas_unit_price(gas_unit_price) + .build(); + + match result { + BuilderResult::Success(txn) => txn, + other => panic!("Expected successful automated-transaction build, got: {other:?}"), + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Existing tests (unchanged) +// ───────────────────────────────────────────────────────────────────────────── #[test] fn check_unregistered_automated_transaction() { @@ -105,20 +245,18 @@ fn check_automated_transaction_successful_execution() { let dest_account = test_context.new_account_data(1_000_000, 0); let payload = aptos_framework_sdk_builder::supra_account_transfer(dest_account.address().clone(), 100); - let gas_price = 100; - let max_gas_amount = 100; - let automation_fee_cap = 100_000; - // Register automation task + // Register automation task using the module-level shared constants so that + // the gas parameters here stay in sync with the new bypass-registration tests. let inner_entry_function = payload.clone().into_entry_function(); - let expiration_time = test_context.chain_time_now() + 8000; + let expiration_time = test_context.chain_time_now() + 8_000; let automation_txn = test_context.create_automation_txn( 0, inner_entry_function.clone(), expiration_time, - gas_price, - max_gas_amount, - automation_fee_cap, + TASK_GAS_PRICE_CAP, // gas_price_cap = 100 + TASK_MAX_GAS_AMOUNT, // max_gas_amount = 1 000 + AUTOMATION_FEE_CAP, // automation_fee_cap_for_epoch = 100 000 ); let output = test_context.execute_and_apply(automation_txn); @@ -136,64 +274,547 @@ fn check_automated_transaction_successful_execution() { .clone() .with_chain_id(ChainId::test()) .with_block_height(1) - .with_gas_unit_price(gas_price) + .with_gas_unit_price(TASK_GAS_PRICE_CAP) .build(); let BuilderResult::Success(automated_txn) = maybe_automated_txn else { panic!("Automated transaction should successfully build: {maybe_automated_txn:?}") }; - let result = test_context - .execute_tagged_transaction(automated_txn.clone().into()); + // The task is PENDING — execution must be rejected before the first cycle starts. + let result = test_context.execute_tagged_transaction(automated_txn.clone().into()); AutomationRegistrationTestContext::check_discarded_output( result, StatusCode::NO_ACTIVE_AUTOMATED_TASK, ); - // Moving to the next cycle - test_context.advance_chain_time_in_secs(1200); + // Advance the chain clock and run the registry action to transition the task + // from PENDING → ACTIVE and the cycle from FINISHED → STARTED. + // `activate_first_task` encapsulates the advance + registry-action + state + // assertions that are identical to the setup in the bypass-registration tests. + activate_first_task(&mut test_context); - // Execute registry action to charge and activate the task - let cycle_info = test_context.get_cycle_info(); - assert_eq!(cycle_info.state, AutomationCycleState::FINISHED); - let registry_action = - test_context.create_automation_registry_transaction(0, cycle_info.index + 1, 1, vec![0]); - test_context - .execute_and_apply_transaction(Transaction::AutomationRegistryTransaction(registry_action)); - let cycle_info = test_context.get_cycle_info(); - assert_eq!(cycle_info.state, AutomationCycleState::STARTED); - - // Execute automated transaction one more time which should be success, as task is already become active after epoch change + // Execute automated transaction; task is now ACTIVE so it should succeed. let sender_address = test_context.sender_account_address(); let sender_seq_num = test_context.account_sequence_number(sender_address); - let output = test_context - .execute_and_apply_transaction(automated_txn.clone().into()); + let output = test_context.execute_and_apply_transaction(automated_txn.clone().into()); assert_eq!( output.status(), &TransactionStatus::Keep(ExecutionStatus::Success), "{output:?}" ); let dest_account_balance = test_context.account_balance(dest_account.address().clone()); - assert_eq!(dest_account_balance, 1_000_100); - // check that sequence number is not updated. + assert_eq!(dest_account_balance, 1000_100); + // Automated transactions must NOT increment the owner's sequence number. assert_eq!( sender_seq_num, test_context.account_sequence_number(sender_address) ); - // try to submit automated transaction with incorrect sender + // Submitting the same automated transaction with the wrong sender must fail: + // the prologue's `has_sender_active_task_with_id_and_type` check uses the + // sender address as part of the task-lookup key. let maybe_automated_txn = automated_txn_builder .with_sender(*dest_account.address()) .with_chain_id(ChainId::test()) .with_block_height(1) - .with_gas_unit_price(gas_price) + .with_gas_unit_price(TASK_GAS_PRICE_CAP) .build(); let BuilderResult::Success(automated_txn) = maybe_automated_txn else { panic!("Automated transaction should successfully build") }; - let result = test_context - .execute_tagged_transaction(automated_txn.clone().into()); + let result = test_context.execute_tagged_transaction(automated_txn.clone().into()); AutomationRegistrationTestContext::check_discarded_output( result, StatusCode::NO_ACTIVE_AUTOMATED_TASK, ); } + +// ───────────────────────────────────────────────────────────────────────────── +// Tests for tasks registered *without* payload validation +// (simulates the `register_without_validation` / SUPRA_AUTOMATION_V2_1 path) +// ───────────────────────────────────────────────────────────────────────────── + +/// **Positive case — V2_1 enabled, valid payload, registered without validation.** +/// +/// A task whose `payload_tx` bytes encode a *valid* EntryFunction (one that +/// exists in the framework and whose arguments match) is registered through the +/// bypass helper (simulating `register_without_validation`). Because the entry +/// function is valid, the automated-transaction processor's Phase-1 load succeeds +/// and the function body runs normally, producing a `Keep(Success)` output. +/// +/// This establishes the baseline: `SUPRA_AUTOMATION_V2_1` being enabled does not +/// break execution of valid tasks, it only changes the behaviour for *invalid* +/// ones (see the negative cases below). +#[test] +fn check_valid_payload_task_registered_without_validation_executes_successfully() { + let mut test_context = AutomationRegistrationTestContext::new(); + + // SUPRA_AUTOMATION_V2_1 is in the default feature set (see aptos_features.rs). + // Enable SUPRA_NATIVE_AUTOMATION to transition the registry from CYCLE_READY + // to CYCLE_STARTED (required for task registration and activation). + test_context.set_supra_native_automation(true); + + let dest_account = test_context.new_account_data(0, 0); + let inner_fn = + aptos_framework_sdk_builder::supra_account_transfer(dest_account.address().clone(), 100) + .into_entry_function(); + + // BCS-encode the valid EntryFunction — this is what the registry stores as + // `payload_tx` in both the validated and the non-validated registration paths. + let valid_payload_bytes = + bcs::to_bytes(&inner_fn).expect("EntryFunction must BCS-serialize successfully"); + + let expiry_time = test_context.chain_time_now() + 8_000; + let sender_address = test_context.sender_account_address(); + + // Register via exec bypass (skips native-layer BCS/type-check validation). + // The Move `register` function still runs and charges the registration fee. + test_context.register_task_bypassing_native_validation( + sender_address, + valid_payload_bytes, + expiry_time, + TASK_MAX_GAS_AMOUNT, + TASK_GAS_PRICE_CAP, + AUTOMATION_FEE_CAP, + DUMMY_TX_HASH.to_vec(), + ust_aux_data(), + ); + + assert_eq!( + test_context.get_next_task_index_from_registry(), + 1, + "exactly one task should now be in the registry" + ); + + // Advance the cycle and make the task ACTIVE. + activate_first_task(&mut test_context); + + let automated_txn = build_automated_txn( + &mut test_context, + 0, // task_index + inner_fn, // the same valid entry function + 1, // gas_unit_price (≤ TASK_GAS_PRICE_CAP) + expiry_time, + ); + + // The entry function exists and its arguments match — execution must succeed. + let output = test_context.execute_and_apply_transaction(automated_txn.into()); + assert_eq!( + output.status(), + &TransactionStatus::Keep(ExecutionStatus::Success), + "valid payload registered without validation must execute successfully: {output:?}" + ); + + // Verify the transfer actually happened. + let dest_balance = test_context.account_balance(*dest_account.address()); + assert_eq!( + dest_balance, 100, + "100 tokens should have been transferred to dest_account" + ); +} + +/// **Negative case — V2_1 enabled, invalid inner payload, registered without validation.** +/// +/// When `SUPRA_AUTOMATION_V2_1` is enabled, a task whose `payload_tx` bytes +/// point to a non-existent module is *discarded* at execution time without +/// charging any gas. The special path in `execute_transaction_impl` catches +/// `INVALID_AUTOMATION_INNER_PAYLOAD` and returns `discarded_output(...)` instead +/// of running the failure epilogue. +/// +/// # Rationale +/// Tasks registered through `register_without_validation` skip the BCS/entry- +/// function check performed by the normal registration flow. A malformed payload +/// that was never verified at registration time should not drain the task owner's +/// account with repeated gas charges if it turns out to be permanently invalid. +/// The `SUPRA_AUTOMATION_V2_1` discard path is the mechanism that prevents this. +#[test] +fn check_invalid_inner_payload_is_discarded_when_v2_1_enabled() { + let mut test_context = AutomationRegistrationTestContext::new(); + + // SUPRA_AUTOMATION_V2_1 is enabled by default via default_features(). + // No explicit toggle needed. SUPRA_NATIVE_AUTOMATION must be enabled + // separately to start the registry cycle. + test_context.set_supra_native_automation(true); + + // Build an EntryFunction that BCS-serialises successfully (so the payload + // bytes are syntactically valid) but references a module that does not exist + // at runtime. `load_and_validate_entry_function` will fail with + // INVALID_AUTOMATION_INNER_PAYLOAD when the processor tries to load it. + let nonexistent_fn = make_nonexistent_entry_function(); + let invalid_payload_bytes = bcs::to_bytes(&nonexistent_fn) + .expect("EntryFunction must BCS-serialize even if the module is absent at runtime"); + + let expiry_time = test_context.chain_time_now() + 8_000; + let sender_address = test_context.sender_account_address(); + + // Register via exec bypass — the native validator is NOT called, so the + // syntactically-valid-but-semantically-invalid payload is accepted. + test_context.register_task_bypassing_native_validation( + sender_address, + invalid_payload_bytes, + expiry_time, + TASK_MAX_GAS_AMOUNT, + TASK_GAS_PRICE_CAP, + AUTOMATION_FEE_CAP, + DUMMY_TX_HASH.to_vec(), + ust_aux_data(), + ); + + assert_eq!( + test_context.get_next_task_index_from_registry(), + 1, + "exactly one task should be registered" + ); + + // Activate the task so the prologue's `has_sender_active_task_with_id_and_type` + // check will pass. + activate_first_task(&mut test_context); + + // Record the balance AFTER registration (coins were transferred for the fee) + // but BEFORE executing the automated transaction. We will compare against + // this to verify that the discard path charges nothing extra. + let balance_before_exec = test_context.account_balance(sender_address); + + // Build the automated transaction carrying the non-existent entry function. + // The builder itself succeeds because it only BCS-decodes the stored bytes + // (which are valid) — it does not query the VM for module existence. + let automated_txn = build_automated_txn(&mut test_context, 0, nonexistent_fn, 1, expiry_time); + + // Execute without applying state changes. We use execute_tagged_transaction + // because the output is DISCARDED (no write set to apply) and + // execute_and_apply_transaction panics on discarded outputs. + let output = test_context.execute_tagged_transaction(automated_txn.into()); + + // With SUPRA_AUTOMATION_V2_1 enabled the processor's special path triggers: + // the output is discarded and no failure epilogue runs. + AutomationRegistrationTestContext::check_discarded_output( + output.clone(), + StatusCode::INVALID_AUTOMATION_INNER_PAYLOAD, + ); + + // Discarded outputs carry FeeStatement::zero(), so gas_used must be 0. + assert_eq!( + output.gas_used(), + 0, + "a discarded output must not charge any gas (FeeStatement::zero())" + ); + + // The sender's balance must be unchanged since the discard path commits + // no write set. (execute_tagged_transaction does not apply state.) + let balance_after_exec = test_context.account_balance(sender_address); + assert_eq!( + balance_before_exec, balance_after_exec, + "balance must not change when the automated transaction is discarded" + ); +} + +/// **Negative case — V2_1 *disabled*, invalid inner payload registered without validation.** +/// +/// When `SUPRA_AUTOMATION_V2_1` is disabled, the special discard path in +/// `execute_transaction_impl` does NOT trigger. Instead the +/// `INVALID_AUTOMATION_INNER_PAYLOAD` error flows through +/// `on_transaction_execution_failure` → `failed_transaction_cleanup`, which runs +/// the failure epilogue and charges the sender for gas consumed up to that point +/// (at minimum the intrinsic-gas charge). +/// +/// The resulting output is `Keep(MiscellaneousError(INVALID_AUTOMATION_INNER_PAYLOAD))` +/// (status code 1132 is in the Verification range, so `keep_or_discard()` returns +/// `Ok(KeptVMStatus::MiscellaneousError)`). Gas *is* charged even though the +/// entry function body never ran, because `charge_intrinsic_gas_for_transaction` +/// was called before the failed load attempt. +/// +/// # Key difference from the enabled case +/// Without V2_1 the protocol has no way to know that the payload was registered +/// without validation, so it applies the same fee-charging logic as for any other +/// kind of execution failure. +#[test] +fn check_invalid_inner_payload_charges_fee_when_v2_1_disabled() { + let mut test_context = AutomationRegistrationTestContext::new(); + + // Enable the base automation feature so the cycle starts and registration + // is accepted. Then explicitly disable SUPRA_AUTOMATION_V2_1 so the + // special discard path in the processor is inactive. + test_context.set_supra_native_automation(true); + // SUPRA_AUTOMATION_V2_1 is in default_features() so we must turn it off. + // set_feature_flag updates the on-chain feature bitset directly; no + // on_new_epoch call is needed because V2_1 does not affect the registry + // state machine (only the VM's error-handling path). + test_context.set_feature_flag(FeatureFlag::SUPRA_AUTOMATION_V2_1, false); + + let nonexistent_fn = make_nonexistent_entry_function(); + let invalid_payload_bytes = + bcs::to_bytes(&nonexistent_fn).expect("EntryFunction must BCS-serialize successfully"); + + let expiry_time = test_context.chain_time_now() + 8_000; + let sender_address = test_context.sender_account_address(); + + // Register the task with the invalid payload. SUPRA_NATIVE_AUTOMATION is + // enabled (so the Move `register` function accepts the call) and the Move + // function itself does not check SUPRA_AUTOMATION_V2_1, so registration + // succeeds regardless of the V2_1 flag. + test_context.register_task_bypassing_native_validation( + sender_address, + invalid_payload_bytes, + expiry_time, + TASK_MAX_GAS_AMOUNT, + TASK_GAS_PRICE_CAP, + AUTOMATION_FEE_CAP, + DUMMY_TX_HASH.to_vec(), + ust_aux_data(), + ); + + assert_eq!( + test_context.get_next_task_index_from_registry(), + 1, + "exactly one task should be registered" + ); + + activate_first_task(&mut test_context); + + let balance_before_exec = test_context.account_balance(sender_address); + + let automated_txn = build_automated_txn(&mut test_context, 0, nonexistent_fn, 1, expiry_time); + + // Execute via execute_tagged_transaction so we can inspect the output before + // deciding whether to apply it. The output is Keep(MiscellaneousError), + // so the write set contains gas-deduction entries. + let output = test_context.execute_tagged_transaction(automated_txn.into()); + + // Without V2_1 the special discard path is bypassed; the failure epilogue + // runs and the output is Keep(MiscellaneousError). + AutomationRegistrationTestContext::check_miscellaneous_output( + output.clone(), + StatusCode::INVALID_AUTOMATION_INNER_PAYLOAD, + ); + + // The failure epilogue charges at least intrinsic gas. + assert!( + output.gas_used() > 0, + "gas must be charged by the failure epilogue when V2_1 is disabled \ + (gas_used = {})", + output.gas_used() + ); + + // Apply the write set manually so the balance change is reflected in the + // fake data store, then assert the balance decreased. + test_context.apply_write_set(output.write_set()); + let balance_after_exec = test_context.account_balance(sender_address); + + assert!( + balance_after_exec < balance_before_exec, + "sender balance must decrease when the failure epilogue charges gas \ + (before = {balance_before_exec}, after = {balance_after_exec})" + ); +} + +/// **Transient execution failure — failure epilogue runs regardless of V2_1.** +/// +/// A task whose `payload_tx` points to an existing function is registered +/// normally (with full validation). At execution time, the Phase-1 load +/// succeeds (the function exists and its argument types are correct), but the +/// function body *aborts* because the transfer amount far exceeds the sender's +/// balance. +/// +/// This produces a `VMStatus::MoveAbort`, which does **not** match the special +/// `INVALID_AUTOMATION_INNER_PAYLOAD` condition in `execute_transaction_impl`. +/// Therefore the failure epilogue always runs — the sender is charged for gas +/// regardless of whether `SUPRA_AUTOMATION_V2_1` is enabled. +/// +/// # What this test verifies +/// * The V2_1 discard path is narrowly scoped to `INVALID_AUTOMATION_INNER_PAYLOAD` +/// (Phase-1 load failure); it does NOT affect ordinary runtime aborts. +/// * The failure epilogue correctly charges gas for a task whose body aborted. +/// * The output status is `Keep(MoveAbort)` — the write set contains gas fees. +#[test] +fn check_transient_execution_failure_charges_fee_regardless_of_v2_1() { + let mut test_context = AutomationRegistrationTestContext::new(); + + // SUPRA_AUTOMATION_V2_1 is enabled by default. We leave it enabled to + // confirm that V2_1 does NOT suppress transient (runtime) failures. + test_context.set_supra_native_automation(true); + + // Use a destination that can receive coins (create it with 0 initial balance). + let dest_account = test_context.new_account_data(0, 0); + + // Transfer amount is astronomically larger than the sender's balance (~100 + // billion quants after registration fees). The prologue only checks that + // `gas_price × max_gas_amount` fits within the balance, NOT the transfer + // amount itself — so the prologue passes. The transfer then aborts inside + // `supra_account_transfer` when it tries to withdraw more than available. + let oversized_transfer_amount = 500_000_000_000_000u64; // 500 trillion >> sender's ~100 billion + + let inner_fn = aptos_framework_sdk_builder::supra_account_transfer( + dest_account.address().clone(), + oversized_transfer_amount, + ) + .into_entry_function(); + + // Register with the validated path to prove the inner function is valid at + // registration time. Only the runtime execution will fail. + let expiry_time = test_context.chain_time_now() + 8_000; + let automation_txn = test_context.create_automation_txn( + 0, + inner_fn.clone(), + expiry_time, + TASK_MAX_GAS_AMOUNT, + TASK_GAS_PRICE_CAP, + AUTOMATION_FEE_CAP, + ); + + let reg_output = test_context.execute_and_apply(automation_txn); + assert_eq!( + reg_output.status(), + &TransactionStatus::Keep(ExecutionStatus::Success), + "registration must succeed: {reg_output:?}" + ); + + assert_eq!( + test_context.get_next_task_index_from_registry(), + 1, + "exactly one task should be registered" + ); + + activate_first_task(&mut test_context); + + let sender_address = test_context.sender_account_address(); + let balance_before_exec = test_context.account_balance(sender_address); + + // Build the automated transaction using the same entry function that was + // registered (which the builder obtains via try_from(task_details)). + let task_details = test_context.get_task_details(0); + let builder = AutomatedTransactionBuilder::try_from(task_details) + .expect("builder construction from registered task must succeed"); + + let result = builder + .with_chain_id(ChainId::test()) + .with_block_height(1) + .with_gas_unit_price(1) + .build(); + + let BuilderResult::Success(automated_txn) = result else { + panic!("automated transaction builder must succeed for a validly registered task"); + }; + + // Execute without applying so we can inspect the output first. + let output = test_context.execute_tagged_transaction(automated_txn.into()); + + // Phase-1 (load) succeeded. Phase-2 (execution body) aborted. + // This is a transient failure → `on_transaction_execution_failure` runs. + // keep_or_discard() for MoveAbort returns Ok(KeptVMStatus::MoveAbort), so + // the output is Keep(MoveAbort { ... }). + match output.status() { + TransactionStatus::Keep(ExecutionStatus::MoveAbort { .. }) => { + // Expected: the execution body aborted at runtime. + }, + other => panic!("expected Keep(MoveAbort) for runtime abort, got: {other:?}"), + } + + // Gas must have been charged by the failure epilogue. + assert!( + output.gas_used() > 0, + "gas must be charged for a runtime abort (failure epilogue ran)" + ); + + // Apply the write set and verify balance decreased. + test_context.apply_write_set(output.write_set()); + let balance_after_exec = test_context.account_balance(sender_address); + + assert!( + balance_after_exec < balance_before_exec, + "sender balance must decrease after a runtime abort \ + (before = {balance_before_exec}, after = {balance_after_exec})" + ); + + // The destination should NOT have received any coins because the transfer + // was rolled back as part of the abort. + let dest_balance = test_context.account_balance(*dest_account.address()); + assert_eq!( + dest_balance, 0, + "destination must not receive tokens when the transfer aborts" + ); +} + +/// **Symmetry check — transient failure with V2_1 explicitly disabled.** +/// +/// Mirrors `check_transient_execution_failure_charges_fee_regardless_of_v2_1` +/// but with `SUPRA_AUTOMATION_V2_1` turned off. The result must be identical +/// (`Keep(MoveAbort)`, gas charged) because the V2_1 flag only influences the +/// `INVALID_AUTOMATION_INNER_PAYLOAD` path, not ordinary runtime aborts. +/// +/// Together with the test above this provides full cross-flag coverage for the +/// transient-failure branch of `execute_transaction_impl`. +#[test] +fn check_transient_execution_failure_charges_fee_when_v2_1_disabled() { + let mut test_context = AutomationRegistrationTestContext::new(); + + test_context.set_supra_native_automation(true); + // Disable V2_1 to confirm it has no effect on runtime aborts. + test_context.set_feature_flag(FeatureFlag::SUPRA_AUTOMATION_V2_1, false); + + let dest_account = test_context.new_account_data(0, 0); + let oversized_transfer_amount = 500_000_000_000_000u64; + + let inner_fn = aptos_framework_sdk_builder::supra_account_transfer( + dest_account.address().clone(), + oversized_transfer_amount, + ) + .into_entry_function(); + + let expiry_time = test_context.chain_time_now() + 8_000; + let automation_txn = test_context.create_automation_txn( + 0, + inner_fn.clone(), + expiry_time, + TASK_MAX_GAS_AMOUNT, + TASK_GAS_PRICE_CAP, + AUTOMATION_FEE_CAP, + ); + + let reg_output = test_context.execute_and_apply(automation_txn); + assert_eq!( + reg_output.status(), + &TransactionStatus::Keep(ExecutionStatus::Success), + "registration must succeed: {reg_output:?}" + ); + + activate_first_task(&mut test_context); + + let sender_address = test_context.sender_account_address(); + let balance_before_exec = test_context.account_balance(sender_address); + + let task_details = test_context.get_task_details(0); + let builder = AutomatedTransactionBuilder::try_from(task_details) + .expect("builder must succeed for a validly registered task"); + + let result = builder + .with_chain_id(ChainId::test()) + .with_block_height(1) + .with_gas_unit_price(1) + .build(); + + let BuilderResult::Success(automated_txn) = result else { + panic!("automated transaction builder must succeed"); + }; + + let output = test_context.execute_tagged_transaction(automated_txn.into()); + + // Result is identical to the V2_1-enabled case: Keep(MoveAbort). + match output.status() { + TransactionStatus::Keep(ExecutionStatus::MoveAbort { .. }) => {}, + other => panic!( + "expected Keep(MoveAbort) regardless of V2_1 flag for runtime abort, got: {other:?}" + ), + } + + assert!( + output.gas_used() > 0, + "gas must be charged by the failure epilogue regardless of V2_1" + ); + + test_context.apply_write_set(output.write_set()); + let balance_after_exec = test_context.account_balance(sender_address); + assert!( + balance_after_exec < balance_before_exec, + "sender balance must decrease (before = {balance_before_exec}, after = {balance_after_exec})" + ); +} diff --git a/aptos-move/e2e-testsuite/src/tests/automation_registration.rs b/aptos-move/e2e-testsuite/src/tests/automation_registration.rs index 41ebbc7f126..72bb6f6aa4d 100644 --- a/aptos-move/e2e-testsuite/src/tests/automation_registration.rs +++ b/aptos-move/e2e-testsuite/src/tests/automation_registration.rs @@ -7,39 +7,35 @@ use aptos_language_e2e_tests::{ account::{Account, AccountData}, executor::FakeExecutor, }; -use aptos_types::account_address::create_multisig_account_address; -use aptos_types::state_store::StateView; -use aptos_types::transaction::automation::Priority; -use aptos_types::transaction::{ExecutionError, Multisig, MultisigTransactionPayload}; use aptos_types::{ + account_address::create_multisig_account_address, + contract_event::ContractEvent, on_chain_config::{ AutomationCycleDetails, AutomationCycleInfo, AutomationCycleState, FeatureFlag, OnChainConfig, }, + state_store::StateView, transaction::{ automation::{ - AutomationRegistryAction, AutomationRegistryRecord, AutomationTaskMetaData, + AutomationRegistryAction, AutomationRegistryRecord, AutomationTaskMetaData, Priority, RegistrationParams, }, - EntryFunction, ExecutionStatus, SignedTransaction, Transaction, TransactionOutput, - TransactionPayload, TransactionStatus, + EntryFunction, ExecutionError, ExecutionStatus, Multisig, MultisigTransactionPayload, + SignedTransaction, Transaction, TransactionOutput, TransactionPayload, TransactionStatus, }, }; use aptos_vm::aptos_vm_viewer::AptosVMViewer; use move_core_types::{ account_address::AccountAddress, value::{serialize_values, MoveValue}, - vm_status::StatusCode, + vm_status::{StatusCode, StatusCode::FEATURE_UNDER_GATING}, }; +use serde::{Deserialize, Serialize}; use std::{ ops::{Deref, DerefMut}, time::Instant, }; -use serde::{Serialize, Deserialize}; -use aptos_types::contract_event::ContractEvent; -use move_core_types::vm_status::StatusCode::FEATURE_UNDER_GATING; - const TIMESTAMP_NOW_SECONDS: &str = "0x1::timestamp::now_seconds"; const ACCOUNT_BALANCE: &str = "0x1::coin::balance"; const SUPRA_COIN: &str = "0x1::supra_coin::SupraCoin"; @@ -52,6 +48,8 @@ const HAS_SENDER_ACTIVE_TASK_WITH_ID: &str = "0x1::automation_registry::has_sender_active_task_with_id"; const GET_TASK_IDS: &str = "0x1::automation_registry::get_task_ids"; +const MAX_GAS_AMOUNT_REGISTRATION: u64 = 500_000_000; + struct MultisigAccountData { multisig_address: AccountAddress, owners: Vec, @@ -98,7 +96,7 @@ impl AutomationRegistrationTestContext { root.rotate_key(private_key, public_key); // Prepare automation registration transaction sender - let txn_sender = executor.create_raw_account_data(100_000_000_000, 0); + let txn_sender = executor.create_raw_account_data(200_000_000_000, 0); executor.add_account_data(&txn_sender); let multisig_account_data = Self::create_multisig_account_data(&mut executor); @@ -112,8 +110,8 @@ impl AutomationRegistrationTestContext { fn create_multisig_account_data(executor: &mut FakeExecutor) -> MultisigAccountData { // Prepare multisig_account for system task registration - let multisig_owner1 = executor.create_raw_account_data(1_000_000_000, 0); - let multisig_owner2 = executor.create_raw_account_data(1_000_000_000, 0); + let multisig_owner1 = executor.create_raw_account_data(1_000_000_000_000, 0); + let multisig_owner2 = executor.create_raw_account_data(1_000_000_000_000, 0); executor.add_account_data(&multisig_owner1); executor.add_account_data(&multisig_owner2); let multisig_address = create_multisig_account_address( @@ -130,8 +128,11 @@ impl AutomationRegistrationTestContext { let account_create_txn = multisig_owner1 .account() .transaction() + // The SUP#3 gas-schedule update raised storage fees ~1000x, so creating the + // multisig account (and its new state slots) now costs ~1.7M gas units at this + // gas unit price. Budget enough headroom for it. .max_gas_amount(1_000_000) - .gas_unit_price(100) + .gas_unit_price(100_000) .payload(create_multisig_payload) .sequence_number(0) .sign(); @@ -140,6 +141,7 @@ impl AutomationRegistrationTestContext { let transfer_txn = multisig_owner1 .account() .transaction() + .gas_unit_price(100_000) .max_gas_amount(1000) .payload(aptos_stdlib::supra_account_transfer( multisig_address, @@ -166,16 +168,12 @@ impl AutomationRegistrationTestContext { } else { (vec![], flag_value) }; - self.executor.exec( - "features", - "change_feature_flags_internal", - vec![], - vec![ + self.executor + .exec("features", "change_feature_flags_internal", vec![], vec![ MoveValue::Signer(acc).simple_serialize().unwrap(), bcs::to_bytes(&enabled).unwrap(), bcs::to_bytes(&disabled).unwrap(), - ], - ); + ]); } pub(crate) fn toggle_feature_with_registry_reconfig( @@ -238,6 +236,7 @@ impl AutomationRegistrationTestContext { .payload(automation_txn) .sequence_number(seq_num) .gas_unit_price(1) + .max_gas_amount(MAX_GAS_AMOUNT_REGISTRATION) .sign() } @@ -267,6 +266,7 @@ impl AutomationRegistrationTestContext { .payload(automation_txn) .sequence_number(seq_num) .gas_unit_price(1) + .max_gas_amount(MAX_GAS_AMOUNT_REGISTRATION) .sign() } @@ -291,6 +291,7 @@ impl AutomationRegistrationTestContext { .payload(automation_txn) .sequence_number(seq_num) .gas_unit_price(1) + .max_gas_amount(MAX_GAS_AMOUNT_REGISTRATION) .sign() } @@ -308,6 +309,7 @@ impl AutomationRegistrationTestContext { )) .sequence_number(seq_num) .gas_unit_price(1) + .max_gas_amount(MAX_GAS_AMOUNT_REGISTRATION) .sign() } @@ -395,11 +397,10 @@ impl AutomationRegistrationTestContext { } pub(crate) fn account_sequence_number(&mut self, account_address: AccountAddress) -> u64 { - let view_output = self.execute_view_function( - str::parse(ACCOUNT_SEQ_NUM).unwrap(), - vec![], - vec![account_address.to_vec()], - ); + let view_output = + self.execute_view_function(str::parse(ACCOUNT_SEQ_NUM).unwrap(), vec![], vec![ + account_address.to_vec(), + ]); let result = view_output.values.expect("Valid result"); assert_eq!(result.len(), 1); bcs::from_bytes::(&result[0]).unwrap() @@ -417,13 +418,12 @@ impl AutomationRegistrationTestContext { } pub(crate) fn get_task_details(&mut self, index: u64) -> AutomationTaskMetaData { - let view_output = self.execute_view_function( - str::parse(AUTOMATION_TASK_DETAILS).unwrap(), - vec![], - vec![MoveValue::U64(index) - .simple_serialize() - .expect("Successful serialization")], - ); + let view_output = + self.execute_view_function(str::parse(AUTOMATION_TASK_DETAILS).unwrap(), vec![], vec![ + MoveValue::U64(index) + .simple_serialize() + .expect("Successful serialization"), + ]); let result = view_output.values.expect("Valid result"); assert!(!result.is_empty()); bcs::from_bytes::(&result[0]) @@ -435,13 +435,11 @@ impl AutomationRegistrationTestContext { vm_viewer: &AptosVMViewer, ) -> AutomationTaskMetaData { let view_output = vm_viewer.execute_view_function( - to_view_function( - str::parse(AUTOMATION_TASK_DETAILS).unwrap(), - vec![], - vec![MoveValue::U64(index) + to_view_function(str::parse(AUTOMATION_TASK_DETAILS).unwrap(), vec![], vec![ + MoveValue::U64(index) .simple_serialize() - .expect("Successful serialization")], - ), + .expect("Successful serialization"), + ]), 50_000, ); let result = view_output.values.expect("Valid result"); @@ -505,6 +503,75 @@ impl AutomationRegistrationTestContext { bcs::from_bytes::>(&result[0]) .expect("Successful deserialization of AutomationCycleInfo") } + + /// Registers an automation task by directly invoking the private Move `register` + /// function through the test executor, bypassing both: + /// + /// 1. **Visibility**: `register` is a `fun` (package-private in Move). The + /// underlying `execute_function_bypass_visibility` call ignores this, so + /// no access-control error is raised. + /// + /// 2. **Native-layer payload validation**: In the normal `AutomationRegistration` + /// transaction flow the VM validates that `payload_bytes` is a well-formed, + /// BCS-encoded `EntryFunction` with correct argument types *before* any Move + /// code runs. The `exec` path skips this check entirely, so arbitrary bytes + /// (including those that encode a call to a non-existent function) are stored + /// directly in the registry. + /// + /// This simulates what happens in production when a smart-contract registers a + /// task via `automation_registry::register_without_validation` (the + /// `SUPRA_AUTOMATION_V2_1` path), which also skips payload validation and relies + /// on the runtime to catch and discard permanently invalid tasks at execution + /// time. + /// + /// # Prerequisites + /// * `SUPRA_NATIVE_AUTOMATION` must be enabled and the automation cycle must be + /// in `CYCLE_STARTED` state before calling this method (the Move `register` + /// function asserts this). + /// * `tx_hash` must be exactly 32 bytes (`TXN_HASH_LENGTH = 32` in the Move + /// contract). + /// * `aux_data` must have exactly 2 elements matching the format validated by + /// `check_and_validate_aux_data`: + /// - index 0: a single byte encoding the task type (`[1u8]` for UST/User) + /// - index 1: BCS-serialised priority `u64`, or empty (`[]`) to let the + /// registry assign the task index as the default priority. + /// * The `owner_address` account must have enough SupraCoin balance to cover + /// the flat registration fee plus the epoch-deposit (`automation_fee_cap`). + pub(crate) fn register_task_bypassing_native_validation( + &mut self, + owner_address: AccountAddress, + payload_bytes: Vec, + expiry_time: u64, + max_gas_amount: u64, + gas_price_cap: u64, + automation_fee_cap: u64, + tx_hash: Vec, + aux_data: Vec>, + ) { + // Call the private `register` Move function via execute_function_bypass_visibility. + // The signer argument is passed as a BCS-serialised MoveValue::Signer so the Move VM + // constructs a valid signer capability for `owner_address` without requiring a + // real signed transaction. + // + // Crucially, none of the native-layer checks (BCS-decode payload, validate + // EntryFunction shape) execute here — only the Move code inside `register` runs. + // This means `payload_bytes` is stored verbatim, even if it encodes a call to a + // non-existent module/function. + self.executor + .exec("automation_registry", "register", vec![], vec![ + MoveValue::Signer(owner_address) + .simple_serialize() + .expect("Signer serialization must not fail"), + bcs::to_bytes(&payload_bytes).expect("payload bytes must be BCS-serialisable"), + bcs::to_bytes(&expiry_time).expect("expiry_time must be BCS-serialisable"), + bcs::to_bytes(&max_gas_amount).expect("max_gas_amount must be BCS-serialisable"), + bcs::to_bytes(&gas_price_cap).expect("gas_price_cap must be BCS-serialisable"), + bcs::to_bytes(&automation_fee_cap) + .expect("automation_fee_cap must be BCS-serialisable"), + bcs::to_bytes(&tx_hash).expect("tx_hash must be BCS-serialisable"), + bcs::to_bytes(&aux_data).expect("aux_data must be BCS-serialisable"), + ]); + } } impl Deref for AutomationRegistrationTestContext { @@ -730,7 +797,7 @@ fn check_task_retrieval_performance() { inner_entry_function.clone(), expiration_time, 25, - 100, + 100_000, automation_fee_cap, ); let output = test_context.execute_and_apply(automation_txn); @@ -807,14 +874,11 @@ fn check_automation_registry_actions_on_cycle_transition() { let result = test_context .execute_tagged_transaction(Transaction::AutomationRegistryTransaction(registry_action)); let status = result.status().status().expect("Expected execution status"); - assert!(matches!( - status, - ExecutionStatus::MoveAbort { - location: _, - code: _, - info: _ - } - )); + assert!(matches!(status, ExecutionStatus::MoveAbort { + location: _, + code: _, + info: _ + })); test_context.advance_chain_time_in_secs(600); @@ -848,14 +912,11 @@ fn check_automation_registry_actions_on_cycle_transition() { ); let status = result.status().status().expect("Expected execution status"); - assert!(matches!( - status, - ExecutionStatus::MoveAbort { - location: _, - code: _, - info: _ - } - )); + assert!(matches!(status, ExecutionStatus::MoveAbort { + location: _, + code: _, + info: _ + })); test_context.execute_and_apply_transaction(Transaction::AutomationRegistryTransaction( registry_action_for_task0, @@ -946,14 +1007,11 @@ fn check_automation_registry_actions_on_cycle_suspension() { .execute_tagged_transaction(Transaction::AutomationRegistryTransaction(registry_action)); let status = result.status().status().expect("Expected execution status"); - assert!(matches!( - status, - ExecutionStatus::MoveAbort { - location: _, - code: _, - info: _ - } - )); + assert!(matches!(status, ExecutionStatus::MoveAbort { + location: _, + code: _, + info: _ + })); } #[test] @@ -972,7 +1030,6 @@ fn check_automation_registry_actions_when_automation_cycle_disabled() { )); } - #[derive(Clone, Debug, Serialize, Deserialize)] struct TransactionExecutionFailed { multisig_address: AccountAddress, @@ -984,11 +1041,12 @@ struct TransactionExecutionFailed { } fn find_transaction_error(events: &[ContractEvent]) -> Vec { - events.iter().filter(|e| e.is_v2()) + events + .iter() + .filter(|e| e.is_v2()) .map(|e| bcs::from_bytes::(e.event_data())) .filter_map(|d| d.ok()) .collect() - } #[test] @@ -1017,7 +1075,9 @@ fn check_system_automation_task_registration() { let failed_event = find_transaction_error(output.events()); assert_eq!(failed_event.len(), 1); let expected_execution_error = ExecutionError { - abort_location: "0000000000000000000000000000000000000000000000000000000000000001::automation_registry".to_string(), + abort_location: + "0000000000000000000000000000000000000000000000000000000000000001::automation_registry" + .to_string(), error_type: "MoveAbort".to_string(), error_code: 41, }; @@ -1047,7 +1107,6 @@ fn check_system_automation_task_registration() { }; assert_eq!(expected_execution_error, failed_event[0].execution_error); - // Try without multisig payload specified let proposal_txn = test_context.create_system_automation_task_registration_proposal(7, &multisig); diff --git a/aptos-move/e2e-testsuite/src/tests/create_account.rs b/aptos-move/e2e-testsuite/src/tests/create_account.rs index 0683caea7f3..40280974393 100644 --- a/aptos-move/e2e-testsuite/src/tests/create_account.rs +++ b/aptos-move/e2e-testsuite/src/tests/create_account.rs @@ -6,10 +6,13 @@ use aptos_language_e2e_tests::{ account::Account, common_transactions::create_account_txn, current_function_name, executor::FakeExecutor, }; -use aptos_types::transaction::{ExecutionStatus, TransactionStatus}; -use aptos_types::{account_config::CoinStoreResource, SupraCoinType}; +use aptos_types::{ + account_config::CoinStoreResource, + transaction::{ExecutionStatus, TransactionStatus}, + SupraCoinType, +}; -// FIX(DP): as default features to FA transfer and default account is disabled +// FIX(DP): as default features to FA transfer and default account is disabled // we need to change this test accordingly #[test] fn create_account() { diff --git a/aptos-move/e2e-testsuite/src/tests/genesis_initializations.rs b/aptos-move/e2e-testsuite/src/tests/genesis_initializations.rs index c8b33d98a23..35900083066 100644 --- a/aptos-move/e2e-testsuite/src/tests/genesis_initializations.rs +++ b/aptos-move/e2e-testsuite/src/tests/genesis_initializations.rs @@ -20,7 +20,10 @@ fn test_timestamp_time_has_started() { "timestamp", "set_time_has_started", vec![], - serialize_values(&vec![MoveValue::Signer(account_address), MoveValue::U64(12)]), + serialize_values(&vec![ + MoveValue::Signer(account_address), + MoveValue::U64(12), + ]), ); println!("{:?}", output); assert_eq!(output.unwrap_err().move_abort_code(), Some(327683)); @@ -29,7 +32,10 @@ fn test_timestamp_time_has_started() { "timestamp", "set_time_has_started", vec![], - serialize_values(&vec![MoveValue::Signer(CORE_CODE_ADDRESS), MoveValue::U64(12)]), + serialize_values(&vec![ + MoveValue::Signer(CORE_CODE_ADDRESS), + MoveValue::U64(12), + ]), ); } diff --git a/aptos-move/e2e-testsuite/src/tests/mod.rs b/aptos-move/e2e-testsuite/src/tests/mod.rs index 6f6b9af534a..6a6d6e06e96 100644 --- a/aptos-move/e2e-testsuite/src/tests/mod.rs +++ b/aptos-move/e2e-testsuite/src/tests/mod.rs @@ -13,6 +13,8 @@ //! Set env REGENERATE_GOLDENFILES to update the golden files when running tests.. mod account_universe; +mod automated_transactions; +mod automation_registration; mod create_account; mod execution_strategies; mod genesis; @@ -26,6 +28,4 @@ mod scripts; mod state_store; mod transaction_fuzzer; mod verify_txn; -mod automation_registration; -mod automated_transactions; mod vm_viewer; diff --git a/aptos-move/e2e-testsuite/src/tests/verify_txn.rs b/aptos-move/e2e-testsuite/src/tests/verify_txn.rs index 23c3f2d94fd..d9fdfec80fc 100644 --- a/aptos-move/e2e-testsuite/src/tests/verify_txn.rs +++ b/aptos-move/e2e-testsuite/src/tests/verify_txn.rs @@ -268,7 +268,7 @@ fn verify_simple_payment() { // FIX(DP): as Default Account feature is not enabled the validation will fail // which says the account does not exists. - + // Create a new transaction from a bogus account that doesn't exist // let bogus_account = executor.create_raw_account_data(100_000, 10); // let txn = bogus_account diff --git a/aptos-move/e2e-testsuite/src/tests/vm_viewer.rs b/aptos-move/e2e-testsuite/src/tests/vm_viewer.rs index 33c6492bf49..ff4acca03ac 100644 --- a/aptos-move/e2e-testsuite/src/tests/vm_viewer.rs +++ b/aptos-move/e2e-testsuite/src/tests/vm_viewer.rs @@ -1,23 +1,26 @@ -// Copyright (c) Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - // Copyright (c) 2024 Supra. // SPDX-License-Identifier: Apache-2.0 use aptos_language_e2e_tests::executor::FakeExecutor; -use aptos_types::move_utils::MemberId; -use aptos_types::transaction::{ViewFunction, ViewFunctionOutput}; +use aptos_logger::debug; +use aptos_types::{ + move_utils::MemberId, + transaction::{ViewFunction, ViewFunctionOutput}, +}; use aptos_vm::aptos_vm_viewer::AptosVMViewer; use move_core_types::language_storage::TypeTag; use std::time::Instant; -use aptos_logger::debug; const TIMESTAMP_NOW_SECONDS: &str = "0x1::timestamp::now_seconds"; const ACCOUNT_BALANCE: &str = "0x1::coin::balance"; const ACCOUNT_SEQ_NUM: &str = "0x1::account::get_sequence_number"; const SUPRA_COIN: &str = "0x1::supra_coin::SupraCoin"; -pub(crate) fn to_view_function(fn_ref: MemberId, ty_args: Vec, args: Vec>) -> ViewFunction { +pub(crate) fn to_view_function( + fn_ref: MemberId, + ty_args: Vec, + args: Vec>, +) -> ViewFunction { ViewFunction::new(fn_ref.module_id, fn_ref.member_id, ty_args, args) } @@ -76,7 +79,10 @@ fn test_vm_viewer() { let viewer_ifc_time = Instant::now(); let time = Instant::now(); let vm_viewer = AptosVMViewer::new(test_executor.state_store()); - debug!("AptosVMViewer creation time: {}", time.elapsed().as_secs_f64()); + debug!( + "AptosVMViewer creation time: {}", + time.elapsed().as_secs_f64() + ); let actual_results = accounts .iter() .map(|account| { diff --git a/aptos-move/framework/Cargo.toml b/aptos-move/framework/Cargo.toml index b63ce009e99..c8bc31a8814 100644 --- a/aptos-move/framework/Cargo.toml +++ b/aptos-move/framework/Cargo.toml @@ -43,6 +43,7 @@ codespan-reporting = { workspace = true } # is because the `dalek-cryptography/bulletproofs` works with version 2 of `dalek-cryptography/curve25519-dalek` and # we work with version 3. Instead, we use `zkcrypto/bulleproofs` which relies on `zkcrypto/curve25519-dalek-ng`. curve25519-dalek = { package = "curve25519-dalek-ng", version = "4" } +crypto = { workspace = true } either = { workspace = true } eth_trie = { workspace = true } flate2 = { workspace = true } diff --git a/aptos-move/framework/aptos-stdlib/Move.toml b/aptos-move/framework/aptos-stdlib/Move.toml index 1a58e9243fb..889da54293f 100644 --- a/aptos-move/framework/aptos-stdlib/Move.toml +++ b/aptos-move/framework/aptos-stdlib/Move.toml @@ -6,7 +6,7 @@ version = "1.0.0" std = "0x1" aptos_std = "0x1" supra_framework = "0x1" -Extensions = "0x1" # For Prover to instantiate `{{Ext}}` in prelude. +Extensions = "0x1" # For Prover to instantiate `{{Ext}}` in prelude. [dependencies] MoveStdlib = { local = "../move-stdlib" } diff --git a/aptos-move/framework/aptos-stdlib/doc/any.md b/aptos-move/framework/aptos-stdlib/doc/any.md index f5193de03b2..d9098f14cb5 100644 --- a/aptos-move/framework/aptos-stdlib/doc/any.md +++ b/aptos-move/framework/aptos-stdlib/doc/any.md @@ -11,6 +11,7 @@ - [Function `pack`](#0x1_any_pack) - [Function `unpack`](#0x1_any_unpack) - [Function `type_name`](#0x1_any_type_name) +- [Function `is_empty`](#0x1_any_is_empty) - [Specification](#@Specification_1) - [Function `pack`](#@Specification_1_pack) - [Function `unpack`](#@Specification_1_unpack) @@ -22,6 +23,7 @@ use 0x1::from_bcs; use 0x1::string; use 0x1::type_info; +use 0x1::vector; @@ -191,6 +193,33 @@ Returns the type name of this Any + + + + +## Function `is_empty` + +Returns true if the BCS-encoded data payload is empty. +An Any value with an empty data vector cannot be decoded and should +be treated as invalid by callers. + + +
public fun is_empty(x: &any::Any): bool
+
+ + + +
+Implementation + + +
public fun is_empty(x: &Any): bool {
+    std::vector::is_empty(&x.data)
+}
+
+ + +
diff --git a/aptos-move/framework/aptos-stdlib/doc/copyable_any.md b/aptos-move/framework/aptos-stdlib/doc/copyable_any.md index ab34a75e7e8..d5dda3ea307 100644 --- a/aptos-move/framework/aptos-stdlib/doc/copyable_any.md +++ b/aptos-move/framework/aptos-stdlib/doc/copyable_any.md @@ -8,8 +8,10 @@ - [Struct `Any`](#0x1_copyable_any_Any) - [Constants](#@Constants_0) - [Function `pack`](#0x1_copyable_any_pack) +- [Function `new`](#0x1_copyable_any_new) - [Function `unpack`](#0x1_copyable_any_unpack) - [Function `type_name`](#0x1_copyable_any_type_name) +- [Function `is_empty`](#0x1_copyable_any_is_empty) - [Specification](#@Specification_1) - [Function `pack`](#@Specification_1_pack) - [Function `unpack`](#@Specification_1_unpack) @@ -21,6 +23,7 @@ use 0x1::from_bcs; use 0x1::string; use 0x1::type_info; +use 0x1::vector; @@ -101,6 +104,39 @@ also required from T. + + + + +## Function `new` + +Construct an Any directly from a pre-known type-name string and +already-BCS-encoded data bytes. Use this only when the type name is +obtained from a trusted source (e.g. type_info::type_name<T>() or a +constant produced by the same) and the data bytes are the BCS encoding +of a value of that type. Prefer pack<T> whenever the concrete type +is statically known at the call site, as it is safer and self-validating. + +This constructor exists primarily for genesis and governance scripts that +receive pre-serialised values from the Rust layer. + + +
public fun new(type_name: string::String, data: vector<u8>): copyable_any::Any
+
+ + + +
+Implementation + + +
public fun new(type_name: String, data: vector<u8>): Any {
+    Any { type_name, data }
+}
+
+ + +
@@ -152,6 +188,33 @@ Returns the type name of this Any + + + + +## Function `is_empty` + +Returns true if the BCS-encoded data payload is empty. +An Any value with an empty data vector cannot be decoded and should +be treated as invalid by callers. + + +
public fun is_empty(x: &copyable_any::Any): bool
+
+ + + +
+Implementation + + +
public fun is_empty(x: &Any): bool {
+    std::vector::is_empty(&x.data)
+}
+
+ + +
diff --git a/aptos-move/framework/aptos-stdlib/sources/any.move b/aptos-move/framework/aptos-stdlib/sources/any.move index 4bd5f9b5e52..456265d4745 100644 --- a/aptos-move/framework/aptos-stdlib/sources/any.move +++ b/aptos-move/framework/aptos-stdlib/sources/any.move @@ -54,6 +54,13 @@ module aptos_std::any { &self.type_name } + /// Returns true if the BCS-encoded data payload is empty. + /// An Any value with an empty data vector cannot be decoded and should + /// be treated as invalid by callers. + public fun is_empty(x: &Any): bool { + std::vector::is_empty(&x.data) + } + #[test_only] struct S has store, drop { x: u64 } @@ -62,4 +69,4 @@ module aptos_std::any { assert!(pack(22).unpack::() == 22, 1); assert!(pack(S { x: 22 }).unpack::() == S { x: 22 }, 2); } -} +} \ No newline at end of file diff --git a/aptos-move/framework/aptos-stdlib/sources/copyable_any.move b/aptos-move/framework/aptos-stdlib/sources/copyable_any.move index 2c1175f9251..8c33aaa413b 100644 --- a/aptos-move/framework/aptos-stdlib/sources/copyable_any.move +++ b/aptos-move/framework/aptos-stdlib/sources/copyable_any.move @@ -23,6 +23,19 @@ module aptos_std::copyable_any { } } + /// Construct an `Any` directly from a pre-known type-name string and + /// already-BCS-encoded data bytes. Use this only when the type name is + /// obtained from a trusted source (e.g. `type_info::type_name()` or a + /// constant produced by the same) and the data bytes are the BCS encoding + /// of a value of that type. Prefer `pack` whenever the concrete type + /// is statically known at the call site, as it is safer and self-validating. + /// + /// This constructor exists primarily for genesis and governance scripts that + /// receive pre-serialised values from the Rust layer. + public fun new(type_name: String, data: vector): Any { + Any { type_name, data } + } + /// Unpack a value from the `Any` representation. This aborts if the value has not the expected type `T`. public fun unpack(self: Any): T { assert!(type_info::type_name() == self.type_name, error::invalid_argument(ETYPE_MISMATCH)); @@ -34,6 +47,13 @@ module aptos_std::copyable_any { &self.type_name } + /// Returns true if the BCS-encoded data payload is empty. + /// An Any value with an empty data vector cannot be decoded and should + /// be treated as invalid by callers. + public fun is_empty(x: &Any): bool { + std::vector::is_empty(&x.data) + } + #[test_only] struct S has store, drop, copy { x: u64 } diff --git a/aptos-move/framework/aptos-token-objects/Move.toml b/aptos-move/framework/aptos-token-objects/Move.toml index b19f4e4cad9..d5f24a3cdb7 100644 --- a/aptos-move/framework/aptos-token-objects/Move.toml +++ b/aptos-move/framework/aptos-token-objects/Move.toml @@ -10,4 +10,4 @@ aptos_token_objects = "0x4" [dependencies] MoveStdlib = { local = "../move-stdlib" } -SupraFramework = { local = "../supra-framework"} +SupraFramework = { local = "../supra-framework" } diff --git a/aptos-move/framework/aptos-token/Move.toml b/aptos-move/framework/aptos-token/Move.toml index deba7e4b55a..454d3eb0b82 100644 --- a/aptos-move/framework/aptos-token/Move.toml +++ b/aptos-move/framework/aptos-token/Move.toml @@ -9,4 +9,4 @@ aptos_token = "0x3" [dependencies] MoveStdlib = { local = "../move-stdlib" } -SupraFramework = { local = "../supra-framework"} +SupraFramework = { local = "../supra-framework" } diff --git a/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs b/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs index 3915ac8630f..5b772cbb3c1 100644 --- a/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs +++ b/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs @@ -779,6 +779,11 @@ pub enum EntryFunctionCall { amount: u64, }, + PboDelegationPoolAdminIncreaseLastUnlockPeriod { + pool_address: AccountAddress, + additional_periods: u64, + }, + /// Allows a delegator to delegate its voting power to a voter. If this delegator already has a delegated voter, /// this change won't take effects until the next lockup period. PboDelegationPoolDelegateVotingPower { @@ -917,6 +922,15 @@ pub enum EntryFunctionCall { unlock_duration: u64, }, + PboDelegationPoolUpdateUnlockingScheduleUnchecked { + pool_address: AccountAddress, + unlock_numerators: Vec, + unlock_denominator: u64, + unlock_start_time: u64, + unlock_duration: u64, + last_unlock_period: u64, + }, + /// Withdraw `amount` of owned inactive stake from the delegation pool at `pool_address`. PboDelegationPoolWithdraw { pool_address: AccountAddress, @@ -1227,7 +1241,7 @@ pub enum EntryFunctionCall { }, /// Change epoch immediately. - /// If `RECONFIGURE_WITH_DKG` is enabled and we are in the middle of a DKG, + /// If `SUPRA_DKG` is enabled and we are in the middle of a DKG, /// stop waiting for DKG and enter the new epoch without randomness. /// /// WARNING: currently only used by tests. In most cases you should use `reconfigure()` instead. @@ -1241,12 +1255,12 @@ pub enum EntryFunctionCall { /// Manually reconfigure. Called at the end of a governance txn that alters on-chain configs. /// /// WARNING: this function always ensures a reconfiguration starts, but when the reconfiguration finishes depends. - /// - If feature `RECONFIGURE_WITH_DKG` is disabled, it finishes immediately. + /// - If feature `SUPRA_DKG` is disabled, it finishes immediately. /// - At the end of the calling transaction, we will be in a new epoch. - /// - If feature `RECONFIGURE_WITH_DKG` is enabled, it starts DKG, and the new epoch will start in a block prologue after DKG finishes. + /// - If feature `SUPRA_DKG` is enabled, it starts DKG, and the new epoch will start in a block prologue after DKG finishes. /// /// This behavior affects when an update of an on-chain config (e.g. `ConsensusConfig`, `Features`) takes effect, - /// since such updates are applied whenever we enter an new epoch. + /// since such updates are applied whenever we enter a new epoch. SupraGovernanceReconfigure {}, /// Create a single-step proposal with the backing `stake_pool`. @@ -1388,6 +1402,11 @@ pub enum EntryFunctionCall { contract_addresses: Vec, }, + VestingWithoutStakingAdminDelayVesting { + contract_address: AccountAddress, + delay_periods: u64, + }, + /// Withdraw all funds to the preset vesting contract's withdrawal address. This can only be called if the contract /// has already been terminated. VestingWithoutStakingAdminWithdraw { @@ -1947,6 +1966,13 @@ impl EntryFunctionCall { pool_address, amount, } => pbo_delegation_pool_add_stake(pool_address, amount), + PboDelegationPoolAdminIncreaseLastUnlockPeriod { + pool_address, + additional_periods, + } => pbo_delegation_pool_admin_increase_last_unlock_period( + pool_address, + additional_periods, + ), PboDelegationPoolDelegateVotingPower { pool_address, new_voter, @@ -2062,6 +2088,21 @@ impl EntryFunctionCall { unlock_start_time, unlock_duration, ), + PboDelegationPoolUpdateUnlockingScheduleUnchecked { + pool_address, + unlock_numerators, + unlock_denominator, + unlock_start_time, + unlock_duration, + last_unlock_period, + } => pbo_delegation_pool_update_unlocking_schedule_unchecked( + pool_address, + unlock_numerators, + unlock_denominator, + unlock_start_time, + unlock_duration, + last_unlock_period, + ), PboDelegationPoolWithdraw { pool_address, amount, @@ -2320,6 +2361,10 @@ impl EntryFunctionCall { } => vesting_update_voter(contract_address, new_voter), VestingVest { contract_address } => vesting_vest(contract_address), VestingVestMany { contract_addresses } => vesting_vest_many(contract_addresses), + VestingWithoutStakingAdminDelayVesting { + contract_address, + delay_periods, + } => vesting_without_staking_admin_delay_vesting(contract_address, delay_periods), VestingWithoutStakingAdminWithdraw { contract_address } => { vesting_without_staking_admin_withdraw(contract_address) }, @@ -4334,6 +4379,27 @@ pub fn pbo_delegation_pool_add_stake( )) } +pub fn pbo_delegation_pool_admin_increase_last_unlock_period( + pool_address: AccountAddress, + additional_periods: u64, +) -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, + ]), + ident_str!("pbo_delegation_pool").to_owned(), + ), + ident_str!("admin_increase_last_unlock_period").to_owned(), + vec![], + vec![ + bcs::to_bytes(&pool_address).unwrap(), + bcs::to_bytes(&additional_periods).unwrap(), + ], + )) +} + /// Allows a delegator to delegate its voting power to a voter. If this delegator already has a delegated voter, /// this change won't take effects until the next lockup period. pub fn pbo_delegation_pool_delegate_voting_power( @@ -4725,6 +4791,35 @@ pub fn pbo_delegation_pool_update_unlocking_schedule( )) } +pub fn pbo_delegation_pool_update_unlocking_schedule_unchecked( + pool_address: AccountAddress, + unlock_numerators: Vec, + unlock_denominator: u64, + unlock_start_time: u64, + unlock_duration: u64, + last_unlock_period: u64, +) -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, + ]), + ident_str!("pbo_delegation_pool").to_owned(), + ), + ident_str!("update_unlocking_schedule_unchecked").to_owned(), + vec![], + vec![ + bcs::to_bytes(&pool_address).unwrap(), + bcs::to_bytes(&unlock_numerators).unwrap(), + bcs::to_bytes(&unlock_denominator).unwrap(), + bcs::to_bytes(&unlock_start_time).unwrap(), + bcs::to_bytes(&unlock_duration).unwrap(), + bcs::to_bytes(&last_unlock_period).unwrap(), + ], + )) +} + /// Withdraw `amount` of owned inactive stake from the delegation pool at `pool_address`. pub fn pbo_delegation_pool_withdraw( pool_address: AccountAddress, @@ -5727,7 +5822,7 @@ pub fn supra_governance_add_supra_approved_script_hash_script( } /// Change epoch immediately. -/// If `RECONFIGURE_WITH_DKG` is enabled and we are in the middle of a DKG, +/// If `SUPRA_DKG` is enabled and we are in the middle of a DKG, /// stop waiting for DKG and enter the new epoch without randomness. /// /// WARNING: currently only used by tests. In most cases you should use `reconfigure()` instead. @@ -5767,12 +5862,12 @@ pub fn supra_governance_force_end_epoch_test_only() -> TransactionPayload { /// Manually reconfigure. Called at the end of a governance txn that alters on-chain configs. /// /// WARNING: this function always ensures a reconfiguration starts, but when the reconfiguration finishes depends. -/// - If feature `RECONFIGURE_WITH_DKG` is disabled, it finishes immediately. +/// - If feature `SUPRA_DKG` is disabled, it finishes immediately. /// - At the end of the calling transaction, we will be in a new epoch. -/// - If feature `RECONFIGURE_WITH_DKG` is enabled, it starts DKG, and the new epoch will start in a block prologue after DKG finishes. +/// - If feature `SUPRA_DKG` is enabled, it starts DKG, and the new epoch will start in a block prologue after DKG finishes. /// /// This behavior affects when an update of an on-chain config (e.g. `ConsensusConfig`, `Features`) takes effect, -/// since such updates are applied whenever we enter an new epoch. +/// since such updates are applied whenever we enter a new epoch. pub fn supra_governance_reconfigure() -> TransactionPayload { TransactionPayload::EntryFunction(EntryFunction::new( ModuleId::new( @@ -6251,6 +6346,27 @@ pub fn vesting_vest_many(contract_addresses: Vec) -> Transaction )) } +pub fn vesting_without_staking_admin_delay_vesting( + contract_address: AccountAddress, + delay_periods: u64, +) -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, + ]), + ident_str!("vesting_without_staking").to_owned(), + ), + ident_str!("admin_delay_vesting").to_owned(), + vec![], + vec![ + bcs::to_bytes(&contract_address).unwrap(), + bcs::to_bytes(&delay_periods).unwrap(), + ], + )) +} + /// Withdraw all funds to the preset vesting contract's withdrawal address. This can only be called if the contract /// has already been terminated. pub fn vesting_without_staking_admin_withdraw( @@ -7551,6 +7667,21 @@ mod decoder { } } + pub fn pbo_delegation_pool_admin_increase_last_unlock_period( + payload: &TransactionPayload, + ) -> Option { + if let TransactionPayload::EntryFunction(script) = payload { + Some( + EntryFunctionCall::PboDelegationPoolAdminIncreaseLastUnlockPeriod { + pool_address: bcs::from_bytes(script.args().get(0)?).ok()?, + additional_periods: bcs::from_bytes(script.args().get(1)?).ok()?, + }, + ) + } else { + None + } + } + pub fn pbo_delegation_pool_delegate_voting_power( payload: &TransactionPayload, ) -> Option { @@ -7789,6 +7920,25 @@ mod decoder { } } + pub fn pbo_delegation_pool_update_unlocking_schedule_unchecked( + payload: &TransactionPayload, + ) -> Option { + if let TransactionPayload::EntryFunction(script) = payload { + Some( + EntryFunctionCall::PboDelegationPoolUpdateUnlockingScheduleUnchecked { + pool_address: bcs::from_bytes(script.args().get(0)?).ok()?, + unlock_numerators: bcs::from_bytes(script.args().get(1)?).ok()?, + unlock_denominator: bcs::from_bytes(script.args().get(2)?).ok()?, + unlock_start_time: bcs::from_bytes(script.args().get(3)?).ok()?, + unlock_duration: bcs::from_bytes(script.args().get(4)?).ok()?, + last_unlock_period: bcs::from_bytes(script.args().get(5)?).ok()?, + }, + ) + } else { + None + } + } + pub fn pbo_delegation_pool_withdraw(payload: &TransactionPayload) -> Option { if let TransactionPayload::EntryFunction(script) = payload { Some(EntryFunctionCall::PboDelegationPoolWithdraw { @@ -8690,6 +8840,19 @@ mod decoder { } } + pub fn vesting_without_staking_admin_delay_vesting( + payload: &TransactionPayload, + ) -> Option { + if let TransactionPayload::EntryFunction(script) = payload { + Some(EntryFunctionCall::VestingWithoutStakingAdminDelayVesting { + contract_address: bcs::from_bytes(script.args().get(0)?).ok()?, + delay_periods: bcs::from_bytes(script.args().get(1)?).ok()?, + }) + } else { + None + } + } + pub fn vesting_without_staking_admin_withdraw( payload: &TransactionPayload, ) -> Option { @@ -9167,6 +9330,10 @@ static SCRIPT_FUNCTION_DECODER_MAP: once_cell::sync::Lazyconst CALCULATE_TRANSACTION_FEE_FOR_DISTRIBUTION: u64 = 105; +
const CALCULATE_TRANSACTION_FEE_FOR_DISTRIBUTION: u64 = 108;
 
@@ -501,7 +511,7 @@ Lifetime: transient Lifetime: transient -
const DEFAULT_ACCOUNT_RESOURCE: u64 = 100;
+
const DEFAULT_ACCOUNT_RESOURCE: u64 = 105;
 
@@ -557,7 +567,7 @@ Whether the account abstraction is enabled. Lifetime: transient -
const DERIVABLE_ACCOUNT_ABSTRACTION: u64 = 97;
+
const DERIVABLE_ACCOUNT_ABSTRACTION: u64 = 102;
 
@@ -579,7 +589,7 @@ Lifetime: transient Whether to distribute transaction fee to validators. -
const DISTRIBUTE_TRANSACTION_FEE: u64 = 106;
+
const DISTRIBUTE_TRANSACTION_FEE: u64 = 109;
 
@@ -641,7 +651,7 @@ Lifetime: transient We do not expect use from Move, so for now only for documentation purposes here -
const ENABLE_FUNCTION_VALUES: u64 = 98;
+
const ENABLE_FUNCTION_VALUES: u64 = 103;
 
@@ -687,7 +697,7 @@ For simplicity, it is represented by type ProviderJWKs (used to rep in JWK Consensus messages, in validator transactions, and in Move. -
const JWK_CONSENSUS_PER_KEY_MODE: u64 = 101;
+
const JWK_CONSENSUS_PER_KEY_MODE: u64 = 106;
 
@@ -820,7 +830,7 @@ Whether new accounts default to the Fungible Asset store. Lifetime: transient -
const NEW_ACCOUNTS_DEFAULT_TO_FA_STORE: u64 = 99;
+
const NEW_ACCOUNTS_DEFAULT_TO_FA_STORE: u64 = 104;
 
@@ -882,7 +892,7 @@ Whether orderless transactions are enabled. Lifetime: transient -
const ORDERLESS_TRANSACTIONS: u64 = 103;
+
const ORDERLESS_TRANSACTIONS: u64 = 107;
 
@@ -1093,6 +1103,46 @@ Lifetime: transient + + +Whether smart contracts can register automation tasks via register_without_validation, +using the get_txn_app_hash native to obtain the registering transaction's hash. +Must only be enabled after all nodes have upgraded to the binary that implements +the get_txn_app_hash_internal native function. + +Lifetime: transient + + +
const SUPRA_AUTOMATION_V2_1: u64 = 101;
+
+ + + + + +Whether BCFT certificate thresholds are enabled. + +Lifetime: permanent + + +
const SUPRA_BCFT_CERTIFICATES: u64 = 98;
+
+ + + + + +Whether the functionality related to the new validator identity representation is enabled. +This flag should only be enabled after all Validators have updated their keys to the new format, including the BLS keys. + +Lifetime: permanent + + +
const SUPRA_BLS_KEYS: u64 = 97;
+
+ + + Whether the automation task sync on block basis is enabled. @@ -1115,6 +1165,20 @@ Lifetime: permanent + + +Whether the APIs related to the DKG feature are enabled. SUPRA_BLS_KEYS must be enabled first, +as the new validator identity format is a prerequisite for the DKG. The default DKG configuration +also requires SUPRA_BCFT_CERTIFICATES to be enabled first. + +Lifetime: transient + + +
const SUPRA_DKG: u64 = 99;
+
+ + + Whether the APIs related to the eth_trie feature are enabled. @@ -1152,6 +1216,18 @@ Lifetime: transient + + +Whether transactions inclusion proofs are enabled. + +Lifetime: permanent + + +
const SUPRA_TRANSACTIONS_INCLUSION_PROOFS: u64 = 100;
+
+ + + Whether the transaction context extension is enabled. This feature allows the module @@ -4266,6 +4342,246 @@ Deprecated feature + + + + +## Function `get_supra_validator_identity_v2_feature` + + + +
public fun get_supra_validator_identity_v2_feature(): u64
+
+ + + +
+Implementation + + +
public fun get_supra_validator_identity_v2_feature(): u64 {
+    SUPRA_BLS_KEYS
+}
+
+ + + +
+ + + +## Function `supra_validator_identity_v2_enabled` + + + +
public fun supra_validator_identity_v2_enabled(): bool
+
+ + + +
+Implementation + + +
public fun supra_validator_identity_v2_enabled(): bool acquires Features {
+    is_enabled(SUPRA_BLS_KEYS)
+}
+
+ + + +
+ + + +## Function `get_supra_bcft_certificates_feature` + + + +
public fun get_supra_bcft_certificates_feature(): u64
+
+ + + +
+Implementation + + +
public fun get_supra_bcft_certificates_feature(): u64 {
+    SUPRA_BCFT_CERTIFICATES
+}
+
+ + + +
+ + + +## Function `supra_bcft_certificates_enabled` + + + +
public fun supra_bcft_certificates_enabled(): bool
+
+ + + +
+Implementation + + +
public fun supra_bcft_certificates_enabled(): bool acquires Features {
+    is_enabled(SUPRA_BCFT_CERTIFICATES)
+}
+
+ + + +
+ + + +## Function `get_supra_dkg_feature` + + + +
public fun get_supra_dkg_feature(): u64
+
+ + + +
+Implementation + + +
public fun get_supra_dkg_feature(): u64 {
+    SUPRA_DKG
+}
+
+ + + +
+ + + +## Function `supra_dkg_enabled` + + + +
public fun supra_dkg_enabled(): bool
+
+ + + +
+Implementation + + +
public fun supra_dkg_enabled(): bool acquires Features {
+    is_enabled(SUPRA_DKG)
+}
+
+ + + +
+ + + +## Function `get_supra_transactions_inclusion_proofs_feature` + + + +
public fun get_supra_transactions_inclusion_proofs_feature(): u64
+
+ + + +
+Implementation + + +
public fun get_supra_transactions_inclusion_proofs_feature(): u64 {
+    SUPRA_TRANSACTIONS_INCLUSION_PROOFS
+}
+
+ + + +
+ + + +## Function `supra_transactions_inclusion_proofs_enabled` + + + +
public fun supra_transactions_inclusion_proofs_enabled(): bool
+
+ + + +
+Implementation + + +
public fun supra_transactions_inclusion_proofs_enabled(): bool acquires Features {
+    is_enabled(SUPRA_TRANSACTIONS_INCLUSION_PROOFS)
+}
+
+ + + +
+ + + +## Function `get_supra_automation_v2_1_feature` + + + +
public fun get_supra_automation_v2_1_feature(): u64
+
+ + + +
+Implementation + + +
public fun get_supra_automation_v2_1_feature(): u64 {
+    SUPRA_AUTOMATION_V2_1
+}
+
+ + + +
+ + + +## Function `supra_automation_v2_1_enabled` + + + +
public fun supra_automation_v2_1_enabled(): bool
+
+ + + +
+Implementation + + +
public fun supra_automation_v2_1_enabled(): bool acquires Features {
+    is_enabled(SUPRA_AUTOMATION_V2_1)
+}
+
+ + +
diff --git a/aptos-move/framework/move-stdlib/sources/configs/features.move b/aptos-move/framework/move-stdlib/sources/configs/features.move index 4d4edf6c48b..32aa6331e5f 100644 --- a/aptos-move/framework/move-stdlib/sources/configs/features.move +++ b/aptos-move/framework/move-stdlib/sources/configs/features.move @@ -850,10 +850,81 @@ module std::features { is_enabled(SUPRA_AUTOMATION_V2) } + /// Whether the functionality related to the new validator identity representation is enabled. + /// This flag should only be enabled after all Validators have updated their keys to the new format, including the BLS keys. + /// + /// Lifetime: permanent + const SUPRA_BLS_KEYS: u64 = 97; + + public fun get_supra_validator_identity_v2_feature(): u64 { + SUPRA_BLS_KEYS + } + + public fun supra_validator_identity_v2_enabled(): bool acquires Features { + is_enabled(SUPRA_BLS_KEYS) + } + + /// Whether BCFT certificate thresholds are enabled. + /// + /// Lifetime: permanent + const SUPRA_BCFT_CERTIFICATES: u64 = 98; + + public fun get_supra_bcft_certificates_feature(): u64 { + SUPRA_BCFT_CERTIFICATES + } + + public fun supra_bcft_certificates_enabled(): bool acquires Features { + is_enabled(SUPRA_BCFT_CERTIFICATES) + } + + /// Whether the APIs related to the DKG feature are enabled. `SUPRA_BLS_KEYS` must be enabled first, + /// as the new validator identity format is a prerequisite for the DKG. The default DKG configuration + /// also requires `SUPRA_BCFT_CERTIFICATES` to be enabled first. + /// + /// Lifetime: transient + const SUPRA_DKG: u64 = 99; + + public fun get_supra_dkg_feature(): u64 { + SUPRA_DKG + } + + public fun supra_dkg_enabled(): bool acquires Features { + is_enabled(SUPRA_DKG) + } + + /// Whether transactions inclusion proofs are enabled. + /// + /// Lifetime: permanent + const SUPRA_TRANSACTIONS_INCLUSION_PROOFS: u64 = 100; + + public fun get_supra_transactions_inclusion_proofs_feature(): u64 { + SUPRA_TRANSACTIONS_INCLUSION_PROOFS + } + + public fun supra_transactions_inclusion_proofs_enabled(): bool acquires Features { + is_enabled(SUPRA_TRANSACTIONS_INCLUSION_PROOFS) + } + + /// Whether smart contracts can register automation tasks via `register_without_validation`, + /// using the `get_txn_app_hash` native to obtain the registering transaction's hash. + /// Must only be enabled after all nodes have upgraded to the binary that implements + /// the `get_txn_app_hash_internal` native function. + /// + /// Lifetime: transient + const SUPRA_AUTOMATION_V2_1: u64 = 101; + + public fun get_supra_automation_v2_1_feature(): u64 { + SUPRA_AUTOMATION_V2_1 + } + + public fun supra_automation_v2_1_enabled(): bool acquires Features { + is_enabled(SUPRA_AUTOMATION_V2_1) + } + /// Whether the account abstraction is enabled. /// /// Lifetime: transient - const DERIVABLE_ACCOUNT_ABSTRACTION: u64 = 97; + const DERIVABLE_ACCOUNT_ABSTRACTION: u64 = 102; public fun is_derivable_account_abstraction_enabled(): bool acquires Features { is_enabled(DERIVABLE_ACCOUNT_ABSTRACTION) @@ -868,11 +939,11 @@ module std::features { /// Lifetime: transient /// /// We do not expect use from Move, so for now only for documentation purposes here - const ENABLE_FUNCTION_VALUES: u64 = 98; + const ENABLE_FUNCTION_VALUES: u64 = 103; /// Whether new accounts default to the Fungible Asset store. /// Lifetime: transient - const NEW_ACCOUNTS_DEFAULT_TO_FA_STORE: u64 = 99; + const NEW_ACCOUNTS_DEFAULT_TO_FA_STORE: u64 = 104; public fun get_new_accounts_default_to_fa_store_feature(): u64 { NEW_ACCOUNTS_DEFAULT_TO_FA_STORE } @@ -881,7 +952,7 @@ module std::features { } /// Lifetime: transient - const DEFAULT_ACCOUNT_RESOURCE: u64 = 100; + const DEFAULT_ACCOUNT_RESOURCE: u64 = 105; public fun get_default_account_resource_feature(): u64 { DEFAULT_ACCOUNT_RESOURCE } @@ -896,7 +967,7 @@ module std::features { /// - while a key-level update is mostly represented by a new type `KeyLevelUpdate` locally, /// For simplicity, it is represented by type `ProviderJWKs` (used to represent issuer-level update) /// in JWK Consensus messages, in validator transactions, and in Move. - const JWK_CONSENSUS_PER_KEY_MODE: u64 = 101; + const JWK_CONSENSUS_PER_KEY_MODE: u64 = 106; public fun get_jwk_consensus_per_key_mode_feature(): u64 { JWK_CONSENSUS_PER_KEY_MODE } @@ -906,7 +977,7 @@ module std::features { /// Whether orderless transactions are enabled. /// Lifetime: transient - const ORDERLESS_TRANSACTIONS: u64 = 103; + const ORDERLESS_TRANSACTIONS: u64 = 108; public fun get_orderless_transactions_feature(): u64 { ORDERLESS_TRANSACTIONS } @@ -915,7 +986,7 @@ module std::features { } /// Whether to calculate the transaction fee for distribution. - const CALCULATE_TRANSACTION_FEE_FOR_DISTRIBUTION: u64 = 105; + const CALCULATE_TRANSACTION_FEE_FOR_DISTRIBUTION: u64 = 110; public fun get_calculate_transaction_fee_for_distribution_feature(): u64 { CALCULATE_TRANSACTION_FEE_FOR_DISTRIBUTION } @@ -924,7 +995,7 @@ module std::features { } /// Whether to distribute transaction fee to validators. - const DISTRIBUTE_TRANSACTION_FEE: u64 = 106; + const DISTRIBUTE_TRANSACTION_FEE: u64 = 111; public fun get_distribute_transaction_fee_feature(): u64 { DISTRIBUTE_TRANSACTION_FEE } diff --git a/aptos-move/framework/src/natives/automation_registry_callbacks.rs b/aptos-move/framework/src/natives/automation_registry_callbacks.rs index 9fd6e915f64..2aeb1f20424 100644 --- a/aptos-move/framework/src/natives/automation_registry_callbacks.rs +++ b/aptos-move/framework/src/natives/automation_registry_callbacks.rs @@ -1,19 +1,11 @@ // Copyright (c) 2025 Supra. // SPDX-License-Identifier: Apache-2.0 -// Copyright (c) 2025 Supra. -// SPDX-License-Identifier: Apache-2.0 -use aptos_native_interface::{ - SafeNativeBuilder, SafeNativeContext, SafeNativeResult, -}; +use aptos_native_interface::{SafeNativeBuilder, SafeNativeContext, SafeNativeResult}; use move_vm_runtime::native_functions::NativeFunction; -use move_vm_types::{ - loaded_data::runtime_types::Type, - values::{Value}, -}; +use move_vm_types::{loaded_data::runtime_types::Type, values::Value}; use smallvec::{smallvec, SmallVec}; -use std::{collections::VecDeque}; - +use std::collections::VecDeque; /*************************************************************************************************** * native fun to check whether the binary has been updated which supports automation registry @@ -39,9 +31,10 @@ fn native_automation_cycle_management_support( pub fn make_all( builder: &SafeNativeBuilder, ) -> impl Iterator + '_ { - let natives = [ - ("native_automation_cycle_management_support", native_automation_cycle_management_support), - ]; + let natives = [( + "native_automation_cycle_management_support", + native_automation_cycle_management_support, + )]; builder.make_named_natives(natives) } diff --git a/aptos-move/framework/src/natives/cryptography/bls12381_bulletproofs.rs b/aptos-move/framework/src/natives/cryptography/bls12381_bulletproofs.rs index 96f04810476..7839d844271 100644 --- a/aptos-move/framework/src/natives/cryptography/bls12381_bulletproofs.rs +++ b/aptos-move/framework/src/natives/cryptography/bls12381_bulletproofs.rs @@ -1,27 +1,21 @@ -// Copyright (c) Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - // Copyright (c) 2024 Supra. +use crate::natives::cryptography::bulletproofs::abort_codes; use aptos_crypto::bulletproofs::MAX_RANGE_BITS; use aptos_gas_schedule::gas_params::natives::aptos_framework::*; use aptos_native_interface::{ safely_pop_arg, RawSafeNative, SafeNativeBuilder, SafeNativeContext, SafeNativeError, SafeNativeResult, }; +use blsttc::G1Projective; use bulletproofs_bls12381::{BulletproofGens, PedersenGens, RangeProof}; use merlin::Transcript; use move_core_types::gas_algebra::{NumArgs, NumBytes}; use move_vm_runtime::native_functions::NativeFunction; -use move_vm_types::{ - loaded_data::runtime_types::Type, - values::{Value}, -}; +use move_vm_types::{loaded_data::runtime_types::Type, values::Value}; use once_cell::sync::Lazy; use smallvec::{smallvec, SmallVec}; use std::collections::VecDeque; -use blsttc::G1Projective; -use crate::natives::cryptography::bulletproofs::abort_codes; /// The Bulletproofs library only seems to support proving [0, 2^{num_bits}) ranges where num_bits is /// either 8, 16, 32 or 64. @@ -33,9 +27,7 @@ fn deserialize_g1(vec: Vec) -> Result { if vec.len() != 48 { return Err(()); } - let array: [u8; 48] = vec - .try_into() - .map_err(|_| ())?; + let array: [u8; 48] = vec.try_into().map_err(|_| ())?; let g1_option = G1Projective::from_compressed(&array); @@ -76,7 +68,6 @@ fn native_verify_range_proof( })?; let pg = { - let rand_base = deserialize_g1(rand_base_bytes).map_err(|_| SafeNativeError::Abort { abort_code: abort_codes::NFE_DESERIALIZE_RANGE_PROOF, })?; @@ -110,7 +101,7 @@ fn verify_range_proof( context.charge( BULLETPROOFS_BASE + BULLETPROOFS_PER_BYTE_RANGEPROOF_DESERIALIZE - * NumBytes::new(proof_bytes.len() as u64), + * NumBytes::new(proof_bytes.len() as u64), )?; let range_proof = match RangeProof::from_bytes(proof_bytes) { diff --git a/aptos-move/framework/src/natives/cryptography/bls12381_scalar.rs b/aptos-move/framework/src/natives/cryptography/bls12381_scalar.rs index 880790faa80..831cbedc52e 100644 --- a/aptos-move/framework/src/natives/cryptography/bls12381_scalar.rs +++ b/aptos-move/framework/src/natives/cryptography/bls12381_scalar.rs @@ -1,19 +1,18 @@ -// Copyright (c) Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - // Copyright (c) 2024 Supra. -use std::collections::VecDeque; -use smallvec::{smallvec, SmallVec}; +use aptos_gas_schedule::gas_params::natives::aptos_framework::{ + HASH_KECCAK256_BASE, HASH_KECCAK256_PER_BYTE, +}; +use aptos_native_interface::{ + safely_pop_arg, RawSafeNative, SafeNativeBuilder, SafeNativeContext, SafeNativeResult, +}; use blst::blst_scalar; -use aptos_gas_schedule::gas_params::natives::aptos_framework::{HASH_KECCAK256_BASE, HASH_KECCAK256_PER_BYTE}; -use aptos_native_interface::{safely_pop_arg, RawSafeNative, SafeNativeBuilder, SafeNativeContext, SafeNativeResult}; -use move_core_types::gas_algebra::{NumBytes}; +use blsttc::{group::ff::Field, Fr}; +use move_core_types::gas_algebra::NumBytes; use move_vm_runtime::native_functions::NativeFunction; -use move_vm_types::loaded_data::runtime_types::Type; -use move_vm_types::values::Value; -use blsttc::Fr; -use blsttc::group::ff::Field; +use move_vm_types::{loaded_data::runtime_types::Type, values::Value}; +use smallvec::{smallvec, SmallVec}; +use std::collections::VecDeque; /// Native function for computing hash to scalar for BLS12-381. /// @@ -30,25 +29,23 @@ fn native_hash_to_scalar( _ty_args: Vec, mut arguments: VecDeque, ) -> SafeNativeResult> { - let msg: Vec = safely_pop_arg!(arguments, Vec); let dst: Vec = safely_pop_arg!(arguments, Vec); let cost = HASH_KECCAK256_BASE - + HASH_KECCAK256_PER_BYTE * (NumBytes::new(msg.len() as u64) + NumBytes::new(dst.len() as u64)); + + HASH_KECCAK256_PER_BYTE + * (NumBytes::new(msg.len() as u64) + NumBytes::new(dst.len() as u64)); context.charge(cost)?; let scalar_fr: Fr; - if let Some(scalar) = blst_scalar::hash_to(&msg, &dst){ - if let Ok(fr_scalar) = scalar.try_into(){ + if let Some(scalar) = blst_scalar::hash_to(&msg, &dst) { + if let Ok(fr_scalar) = scalar.try_into() { scalar_fr = fr_scalar; - } - else { + } else { scalar_fr = Fr::zero(); } - } - else { + } else { scalar_fr = Fr::zero(); } @@ -60,12 +57,10 @@ pub fn make_all( ) -> impl Iterator + '_ { let mut natives = vec![]; - natives.extend([ - ( - "native_hash_to_scalar", - native_hash_to_scalar as RawSafeNative, - ), - ]); + natives.extend([( + "native_hash_to_scalar", + native_hash_to_scalar as RawSafeNative, + )]); builder.make_named_natives(natives) } diff --git a/aptos-move/framework/src/natives/cryptography/class_groups.rs b/aptos-move/framework/src/natives/cryptography/class_groups.rs new file mode 100644 index 00000000000..fafeae1360e --- /dev/null +++ b/aptos-move/framework/src/natives/cryptography/class_groups.rs @@ -0,0 +1,78 @@ +// Copyright (c) 2025 Supra. + +/*************************************************************************************************** + * native fun class_group_validate_pubkey + * + * gas cost: per_pubkey_deserialize_cost + pop_proof_validation + * + * where +? indicates that the expression stops evaluating there if the previous gas-charging step + * failed + **************************************************************************************************/ +use aptos_gas_schedule::gas_params::natives::supra_stdlib::{ + CLASS_GROUPS_PER_PUBKEY_DESERIALIZE, CLASS_GROUPS_POP, +}; +use aptos_native_interface::{ + safely_pop_arg, RawSafeNative, SafeNativeBuilder, SafeNativeContext, SafeNativeResult, +}; +#[cfg(feature = "testing")] +use crypto::bls12381::cl_utils::rng; +use move_core_types::gas_algebra::NumArgs; +use move_vm_runtime::native_functions::NativeFunction; +use move_vm_types::{loaded_data::runtime_types::Type, values::Value}; +use smallvec::{smallvec, SmallVec}; +use std::collections::VecDeque; + +fn native_class_group_validate_pubkey( + context: &mut SafeNativeContext, + _ty_args: Vec, + mut arguments: VecDeque, +) -> SafeNativeResult> { + debug_assert!(_ty_args.is_empty()); + debug_assert!(arguments.len() == 1); + + context.charge(CLASS_GROUPS_PER_PUBKEY_DESERIALIZE * NumArgs::one())?; + context.charge(CLASS_GROUPS_POP)?; + + let pk_bytes = safely_pop_arg!(arguments, Vec); + match crypto::cg_public_key::CGEncryptionKeyBls12381::try_from(pk_bytes.as_slice()) { + Ok(_) => Ok(smallvec![Value::bool(true)]), + Err(_) => Ok(smallvec![Value::bool(false)]), + } +} + +#[cfg(feature = "testing")] +pub fn native_generate_keys( + _context: &mut SafeNativeContext, + _ty_args: Vec, + _arguments: VecDeque, +) -> SafeNativeResult> { + let (sk, pk) = crypto::bls12381::cg_encryption::keygen(&mut rng(), &vec![]).unwrap(); + + Ok(smallvec![ + Value::vector_u8(bcs::to_bytes(&sk).unwrap()), + Value::vector_u8(pk.to_vec()), + ]) +} + +/*************************************************************************************************** + * module + * + **************************************************************************************************/ +pub fn make_all( + builder: &SafeNativeBuilder, +) -> impl Iterator + '_ { + let mut natives = vec![]; + + natives.extend([( + "validate_pubkey_internal", + native_class_group_validate_pubkey as RawSafeNative, + )]); + + #[cfg(feature = "testing")] + natives.append(&mut vec![( + "generate_keys_internal", + native_generate_keys as RawSafeNative, + )]); + + builder.make_named_natives(natives) +} diff --git a/aptos-move/framework/src/natives/cryptography/eth_trie.rs b/aptos-move/framework/src/natives/cryptography/eth_trie.rs index d5297f836e3..bafc3006fb2 100644 --- a/aptos-move/framework/src/natives/cryptography/eth_trie.rs +++ b/aptos-move/framework/src/natives/cryptography/eth_trie.rs @@ -1,22 +1,22 @@ -// Copyright (c) Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - // Copyright (c) 2024 Supra. -use std::collections::VecDeque; -use std::sync::Arc; +use aptos_gas_schedule::gas_params::natives::aptos_framework::{ + ETH_TRIE_PROOF_BASE, ETH_TRIE_PROOF_DECODE_BASE, ETH_TRIE_PROOF_DECODE_PER_BYTE, + ETH_TRIE_PROOF_HASH_BASE, ETH_TRIE_PROOF_HASH_PER_BYTE, +}; +use aptos_native_interface::{ + safely_pop_arg, safely_pop_vec_arg, RawSafeNative, SafeNativeBuilder, SafeNativeContext, + SafeNativeResult, +}; +use eth_trie::{EthTrie, MemoryDB, Trie, DB}; use keccak_hash::{keccak, H256}; -use move_vm_types::values::Value; -use move_vm_types::loaded_data::runtime_types::Type; -use eth_trie::{EthTrie, Trie, DB}; -use eth_trie::MemoryDB; -use smallvec::{smallvec, SmallVec}; use move_core_types::gas_algebra::{NumArgs, NumBytes}; use move_vm_runtime::native_functions::NativeFunction; -use aptos_native_interface::{safely_pop_arg, safely_pop_vec_arg, RawSafeNative, SafeNativeBuilder, SafeNativeContext, SafeNativeResult}; -use aptos_gas_schedule::gas_params::natives::aptos_framework::{ETH_TRIE_PROOF_BASE, ETH_TRIE_PROOF_DECODE_BASE, ETH_TRIE_PROOF_DECODE_PER_BYTE, ETH_TRIE_PROOF_HASH_BASE, ETH_TRIE_PROOF_HASH_PER_BYTE}; +use move_vm_types::{loaded_data::runtime_types::Type, values::Value}; #[cfg(feature = "testing")] use rand::Rng; +use smallvec::{smallvec, SmallVec}; +use std::{collections::VecDeque, sync::Arc}; /// The minimum length (in bytes) for an encoded node to be stored by hash. const HASHED_LENGTH: usize = 32; @@ -48,8 +48,10 @@ pub fn native_verify_proof_eth_trie( let total_proof_bytes = proof.iter().map(|node| node.len() as u64).sum::(); context.charge( - (ETH_TRIE_PROOF_HASH_BASE + ETH_TRIE_PROOF_DECODE_BASE) * NumArgs::new(proof.len() as u64) + - (ETH_TRIE_PROOF_HASH_PER_BYTE + ETH_TRIE_PROOF_DECODE_PER_BYTE) * NumBytes::new(total_proof_bytes))?; + (ETH_TRIE_PROOF_HASH_BASE + ETH_TRIE_PROOF_DECODE_BASE) * NumArgs::new(proof.len() as u64) + + (ETH_TRIE_PROOF_HASH_PER_BYTE + ETH_TRIE_PROOF_DECODE_PER_BYTE) + * NumBytes::new(total_proof_bytes), + )?; // Convert the root (a Vec) into a H256 hash. let root_hash = H256::from_slice(&root); @@ -158,12 +160,10 @@ pub fn make_all( native_generate_random_trie as RawSafeNative, )]); - natives.extend([ - ( - "native_verify_proof_eth_trie", - native_verify_proof_eth_trie as RawSafeNative, - ), - ]); + natives.extend([( + "native_verify_proof_eth_trie", + native_verify_proof_eth_trie as RawSafeNative, + )]); builder.make_named_natives(natives) } diff --git a/aptos-move/framework/src/natives/cryptography/mod.rs b/aptos-move/framework/src/natives/cryptography/mod.rs index 5231d4bdba0..c1dd6e64fed 100644 --- a/aptos-move/framework/src/natives/cryptography/mod.rs +++ b/aptos-move/framework/src/natives/cryptography/mod.rs @@ -3,14 +3,15 @@ pub mod algebra; pub mod bls12381; +pub mod bls12381_bulletproofs; +pub mod bls12381_scalar; pub mod bulletproofs; +pub mod class_groups; pub mod ed25519; +pub mod eth_trie; mod helpers; pub mod multi_ed25519; pub mod ristretto255; pub mod ristretto255_point; pub mod ristretto255_scalar; pub mod secp256k1; -pub mod eth_trie; -pub mod bls12381_scalar; -pub mod bls12381_bulletproofs; diff --git a/aptos-move/framework/src/natives/mod.rs b/aptos-move/framework/src/natives/mod.rs index 151533f1624..364e2031759 100644 --- a/aptos-move/framework/src/natives/mod.rs +++ b/aptos-move/framework/src/natives/mod.rs @@ -6,6 +6,7 @@ pub mod account; pub mod account_abstraction; pub mod aggregator_natives; +mod automation_registry_callbacks; pub mod code; pub mod consensus_config; pub mod create_signer; @@ -19,13 +20,12 @@ pub mod object; pub mod object_code_deployment; pub mod permissioned_signer; pub mod randomness; +pub mod rlp; pub mod state_storage; pub mod string_utils; pub mod transaction_context; pub mod type_info; pub mod util; -pub mod rlp; -mod automation_registry_callbacks; pub mod vector_utils; use crate::natives::cryptography::multi_ed25519; @@ -64,7 +64,10 @@ pub fn all_natives( add_natives_from_module!("genesis", create_signer::make_all(builder)); add_natives_from_module!("multi_ed25519", multi_ed25519::make_all(builder)); add_natives_from_module!("bls12381", cryptography::bls12381::make_all(builder)); - add_natives_from_module!("bls12381_scalar", cryptography::bls12381_scalar::make_all(builder)); + add_natives_from_module!( + "bls12381_scalar", + cryptography::bls12381_scalar::make_all(builder) + ); add_natives_from_module!("eth_trie", cryptography::eth_trie::make_all(builder)); add_natives_from_module!("secp256k1", cryptography::secp256k1::make_all(builder)); add_natives_from_module!("aptos_hash", hash::make_all(builder)); @@ -84,6 +87,10 @@ pub fn all_natives( "bls12381_bulletproofs", cryptography::bls12381_bulletproofs::make_all(builder) ); + add_natives_from_module!( + "class_groups", + cryptography::class_groups::make_all(builder) + ); add_natives_from_module!( "transaction_context", transaction_context::make_all(builder) @@ -104,7 +111,10 @@ pub fn all_natives( dispatchable_fungible_asset::make_all(builder) ); add_natives_from_module!("rlp", rlp::make_all(builder)); - add_natives_from_module!("automation_registry", automation_registry_callbacks::make_all(builder)); + add_natives_from_module!( + "automation_registry", + automation_registry_callbacks::make_all(builder) + ); add_natives_from_module!("vector_utils", vector_utils::make_all(builder)); add_natives_from_module!( "permissioned_signer", diff --git a/aptos-move/framework/src/natives/rlp.rs b/aptos-move/framework/src/natives/rlp.rs index dbb61b264e5..9f650350766 100644 --- a/aptos-move/framework/src/natives/rlp.rs +++ b/aptos-move/framework/src/natives/rlp.rs @@ -1,20 +1,21 @@ -// Copyright (c) Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - // Copyright (c) 2024 Supra. -use std::collections::VecDeque; +use aptos_gas_schedule::gas_params::natives::aptos_framework::{ + RLP_ENCODE_DECODE_BASE, RLP_ENCODE_DECODE_PER_BYTE, UTIL_FROM_BYTES_BASE, + UTIL_FROM_BYTES_PER_BYTE, +}; +use aptos_native_interface::{ + safely_pop_arg, RawSafeNative, SafeNativeBuilder, SafeNativeContext, SafeNativeError, + SafeNativeResult, +}; use ark_std::iterable::Iterable; use keccak_hash::H256; +use move_core_types::{account_address::AccountAddress, gas_algebra::NumBytes}; +use move_vm_runtime::native_functions::NativeFunction; +use move_vm_types::{loaded_data::runtime_types::Type, values::Value}; use rlp::Rlp; use smallvec::{smallvec, SmallVec}; -use aptos_gas_schedule::gas_params::natives::aptos_framework::{RLP_ENCODE_DECODE_BASE, RLP_ENCODE_DECODE_PER_BYTE, UTIL_FROM_BYTES_BASE, UTIL_FROM_BYTES_PER_BYTE}; -use aptos_native_interface::{safely_pop_arg, RawSafeNative, SafeNativeBuilder, SafeNativeContext, SafeNativeError, SafeNativeResult}; -use move_core_types::account_address::AccountAddress; -use move_core_types::gas_algebra::{NumBytes}; -use move_vm_runtime::native_functions::NativeFunction; -use move_vm_types::loaded_data::runtime_types::Type; -use move_vm_types::values::Value; +use std::collections::VecDeque; const E_DECODE_FAILURE: u64 = 0x1; const E_INVALID_TYPE_ARG: u64 = 0x2; @@ -27,8 +28,7 @@ macro_rules! rlp_encode_scalar { ($context:expr, $args:ident, $rust_ty:ty, $num_bytes:expr) => {{ let x: $rust_ty = safely_pop_arg!($args, $rust_ty); $context.charge( - RLP_ENCODE_DECODE_BASE + - RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new($num_bytes) + RLP_ENCODE_DECODE_BASE + RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new($num_bytes), )?; let encoded_data = rlp::encode(&x).to_vec(); Ok(smallvec![Value::vector_u8(encoded_data)]) @@ -42,8 +42,8 @@ macro_rules! rlp_decode_scalar { let encoded_data: Vec = safely_pop_arg!($args, Vec); // Gas charge $context.charge( - RLP_ENCODE_DECODE_BASE + - RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(encoded_data.len() as u64) + RLP_ENCODE_DECODE_BASE + + RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(encoded_data.len() as u64), )?; // RLP decode match rlp::decode::<$rust_ty>(&encoded_data) { @@ -60,7 +60,11 @@ macro_rules! rlp_encode_list { ($data:expr, $rust_ty:ty, $err_code:expr) => {{ let vec_t: Vec<$rust_ty> = match bcs::from_bytes(&$data) { Ok(val) => val, - Err(_) => return Err(SafeNativeError::Abort { abort_code: $err_code }), + Err(_) => { + return Err(SafeNativeError::Abort { + abort_code: $err_code, + }) + }, }; let encoded = rlp::encode_list(&vec_t).to_vec(); Ok(smallvec![Value::vector_u8(encoded)]) @@ -72,7 +76,9 @@ macro_rules! rlp_decode_list { ($rlp:expr, $rust_ty:ty, $build_value_fn:expr, $err_code:expr) => {{ match $rlp.as_list::<$rust_ty>() { Ok(decoded) => Ok(smallvec![$build_value_fn(decoded)]), - Err(_) => Err(SafeNativeError::Abort { abort_code: $err_code }), + Err(_) => Err(SafeNativeError::Abort { + abort_code: $err_code, + }), } }}; } @@ -89,33 +95,34 @@ fn native_rlp_encode( ty_args: Vec, mut args: VecDeque, ) -> SafeNativeResult> { - if ty_args.len() != 1 { - return Err(SafeNativeError::Abort { abort_code: E_INVALID_TYPE_ARG }); + return Err(SafeNativeError::Abort { + abort_code: E_INVALID_TYPE_ARG, + }); } let inner_ty = &ty_args[0]; match inner_ty { - Type::Bool => rlp_encode_scalar!(context, args, bool, 1), - Type::U8 => rlp_encode_scalar!(context, args, u8, 1), - Type::U16 => rlp_encode_scalar!(context, args, u16, 2), - Type::U32 => rlp_encode_scalar!(context, args, u32, 4), - Type::U64 => rlp_encode_scalar!(context, args, u64, 8), - Type::U128 => rlp_encode_scalar!(context, args, u128, 16), + Type::Bool => rlp_encode_scalar!(context, args, bool, 1), + Type::U8 => rlp_encode_scalar!(context, args, u8, 1), + Type::U16 => rlp_encode_scalar!(context, args, u16, 2), + Type::U32 => rlp_encode_scalar!(context, args, u32, 4), + Type::U64 => rlp_encode_scalar!(context, args, u64, 8), + Type::U128 => rlp_encode_scalar!(context, args, u128, 16), // address is custom Type::Address => { let addr: AccountAddress = safely_pop_arg!(args, AccountAddress); let addr_bytes = addr.into_bytes(); context.charge( - RLP_ENCODE_DECODE_BASE + - RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(addr_bytes.len() as u64) + RLP_ENCODE_DECODE_BASE + + RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(addr_bytes.len() as u64), )?; let addr = H256::from(addr_bytes); let encoded_data = rlp::encode(&addr).to_vec(); Ok(smallvec![Value::vector_u8(encoded_data)]) - } + }, // vector is also custom Type::Vector(inner_type) => { @@ -124,17 +131,21 @@ fn native_rlp_encode( Type::U8 => { let bytes: Vec = safely_pop_arg!(args, Vec); context.charge( - RLP_ENCODE_DECODE_BASE + - RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(bytes.len() as u64) + RLP_ENCODE_DECODE_BASE + + RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(bytes.len() as u64), )?; let encoded_data = rlp::encode(&bytes).to_vec(); Ok(smallvec![Value::vector_u8(encoded_data)]) - } - _ => Err(SafeNativeError::Abort { abort_code: E_UNSUPPORTED_TYPE }), + }, + _ => Err(SafeNativeError::Abort { + abort_code: E_UNSUPPORTED_TYPE, + }), } - } + }, - _ => Err(SafeNativeError::Abort { abort_code: E_UNSUPPORTED_TYPE }), + _ => Err(SafeNativeError::Abort { + abort_code: E_UNSUPPORTED_TYPE, + }), } } @@ -143,56 +154,65 @@ fn native_rlp_decode( ty_args: Vec, mut args: VecDeque, ) -> SafeNativeResult> { - if ty_args.len() != 1 { - return Err(SafeNativeError::Abort { abort_code: E_INVALID_TYPE_ARG }); + return Err(SafeNativeError::Abort { + abort_code: E_INVALID_TYPE_ARG, + }); } let inner_ty = &ty_args[0]; match inner_ty { - Type::Bool => rlp_decode_scalar!(context, args, bool, Value::bool), - Type::U8 => rlp_decode_scalar!(context, args, u8, Value::u8), - Type::U16 => rlp_decode_scalar!(context, args, u16, Value::u16), - Type::U32 => rlp_decode_scalar!(context, args, u32, Value::u32), - Type::U64 => rlp_decode_scalar!(context, args, u64, Value::u64), - Type::U128 => rlp_decode_scalar!(context, args, u128, Value::u128), + Type::Bool => rlp_decode_scalar!(context, args, bool, Value::bool), + Type::U8 => rlp_decode_scalar!(context, args, u8, Value::u8), + Type::U16 => rlp_decode_scalar!(context, args, u16, Value::u16), + Type::U32 => rlp_decode_scalar!(context, args, u32, Value::u32), + Type::U64 => rlp_decode_scalar!(context, args, u64, Value::u64), + Type::U128 => rlp_decode_scalar!(context, args, u128, Value::u128), Type::Address => { let encoded_data: Vec = safely_pop_arg!(args, Vec); context.charge( - RLP_ENCODE_DECODE_BASE + - RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(encoded_data.len() as u64) + RLP_ENCODE_DECODE_BASE + + RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(encoded_data.len() as u64), )?; // address => decode as Vec, then convert match rlp::decode::>(&encoded_data) { - Ok(addr_bytes) => { - match AccountAddress::from_bytes(addr_bytes) { - Ok(addr) => Ok(smallvec![Value::address(addr)]), - Err(_) => Err(SafeNativeError::Abort { abort_code: E_DECODE_FAILURE }), - } + Ok(addr_bytes) => match AccountAddress::from_bytes(addr_bytes) { + Ok(addr) => Ok(smallvec![Value::address(addr)]), + Err(_) => Err(SafeNativeError::Abort { + abort_code: E_DECODE_FAILURE, + }), }, - Err(_) => Err(SafeNativeError::Abort { abort_code: E_DECODE_FAILURE }), + Err(_) => Err(SafeNativeError::Abort { + abort_code: E_DECODE_FAILURE, + }), } - } + }, Type::Vector(inner_type) => { match &**inner_type { // only vector encoding is supported Type::U8 => { let encoded_data: Vec = safely_pop_arg!(args, Vec); context.charge( - RLP_ENCODE_DECODE_BASE + - RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(encoded_data.len() as u64) + RLP_ENCODE_DECODE_BASE + + RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(encoded_data.len() as u64), )?; match rlp::decode::>(&encoded_data) { Ok(decoded_bytes) => Ok(smallvec![Value::vector_u8(decoded_bytes)]), - Err(_) => Err(SafeNativeError::Abort { abort_code: E_DECODE_FAILURE }), + Err(_) => Err(SafeNativeError::Abort { + abort_code: E_DECODE_FAILURE, + }), } - } - _ => Err(SafeNativeError::Abort { abort_code: E_UNSUPPORTED_TYPE }), + }, + _ => Err(SafeNativeError::Abort { + abort_code: E_UNSUPPORTED_TYPE, + }), } - } + }, - _ => Err(SafeNativeError::Abort { abort_code: E_UNSUPPORTED_TYPE }), + _ => Err(SafeNativeError::Abort { + abort_code: E_UNSUPPORTED_TYPE, + }), } } @@ -208,41 +228,44 @@ fn native_rlp_encode_list_scalar( ty_args: Vec, mut args: VecDeque, ) -> SafeNativeResult> { - if ty_args.len() != 1 { - return Err(SafeNativeError::Abort { abort_code: E_INVALID_TYPE_ARG }); + return Err(SafeNativeError::Abort { + abort_code: E_INVALID_TYPE_ARG, + }); } let inner_ty = &ty_args[0]; let data: Vec = safely_pop_arg!(args, Vec); let total_data_bytes = data.len() as u64; context.charge( - RLP_ENCODE_DECODE_BASE+ - RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(total_data_bytes))?; + RLP_ENCODE_DECODE_BASE + RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(total_data_bytes), + )?; match inner_ty { Type::Bool => { rlp_encode_list!(data, bool, E_ENCODE_FAILURE) - } + }, Type::U8 => { rlp_encode_list!(data, u8, E_ENCODE_FAILURE) - } + }, Type::U16 => { rlp_encode_list!(data, u16, E_ENCODE_FAILURE) - } + }, Type::U32 => { rlp_encode_list!(data, u32, E_ENCODE_FAILURE) - } + }, Type::U64 => { rlp_encode_list!(data, u64, E_ENCODE_FAILURE) - } + }, Type::U128 => { rlp_encode_list!(data, u128, E_ENCODE_FAILURE) - } + }, Type::Address => { // Address is a bit more custom - let data: Vec = bcs::from_bytes(&data) - .map_err(|_| SafeNativeError::Abort { abort_code: E_ENCODE_FAILURE })?; + let data: Vec = + bcs::from_bytes(&data).map_err(|_| SafeNativeError::Abort { + abort_code: E_ENCODE_FAILURE, + })?; let mut address_vec = vec![]; for addr in data { @@ -252,10 +275,10 @@ fn native_rlp_encode_list_scalar( } let encoded_data = rlp::encode_list(&address_vec).to_vec(); Ok(smallvec![Value::vector_u8(encoded_data)]) - } - _ => { - Err(SafeNativeError::Abort { abort_code: E_UNSUPPORTED_TYPE }) - } + }, + _ => Err(SafeNativeError::Abort { + abort_code: E_UNSUPPORTED_TYPE, + }), } } @@ -264,16 +287,17 @@ fn native_rlp_decode_list_scalar( ty_args: Vec, mut args: VecDeque, ) -> SafeNativeResult> { - if ty_args.len() != 1 { - return Err(SafeNativeError::Abort { abort_code: E_INVALID_TYPE_ARG }); + return Err(SafeNativeError::Abort { + abort_code: E_INVALID_TYPE_ARG, + }); } let inner_ty = &ty_args[0]; let encoded_data: Vec = safely_pop_arg!(args, Vec); context.charge( - RLP_ENCODE_DECODE_BASE+ - RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(encoded_data.len() as u64) + RLP_ENCODE_DECODE_BASE + + RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(encoded_data.len() as u64), )?; let rlp = Rlp::new(&encoded_data); @@ -310,17 +334,23 @@ fn native_rlp_decode_list_scalar( } match AccountAddress::from_bytes(address_bytes) { Ok(addr) => address_vec.push(addr), - Err(_) => return Err(SafeNativeError::Abort { - abort_code: E_DECODE_FAILURE, - }), + Err(_) => { + return Err(SafeNativeError::Abort { + abort_code: E_DECODE_FAILURE, + }) + }, } } Ok(smallvec![Value::vector_address(address_vec)]) }, - Err(_) => Err(SafeNativeError::Abort { abort_code: E_DECODE_FAILURE }), + Err(_) => Err(SafeNativeError::Abort { + abort_code: E_DECODE_FAILURE, + }), } }, - _ => Err(SafeNativeError::Abort { abort_code: E_UNSUPPORTED_TYPE }), + _ => Err(SafeNativeError::Abort { + abort_code: E_UNSUPPORTED_TYPE, + }), } } @@ -329,14 +359,14 @@ fn native_rlp_encode_list_byte_array( _ty_args: Vec, mut args: VecDeque, ) -> SafeNativeResult> { - let data: Vec = safely_pop_arg!(args, Vec); let total_data_bytes = data.len() as u64; context.charge( - RLP_ENCODE_DECODE_BASE+ - RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(total_data_bytes))?; - let data: Vec> = bcs::from_bytes(&data) - .map_err(|_| SafeNativeError::Abort { abort_code: E_ENCODE_FAILURE })?; + RLP_ENCODE_DECODE_BASE + RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(total_data_bytes), + )?; + let data: Vec> = bcs::from_bytes(&data).map_err(|_| SafeNativeError::Abort { + abort_code: E_ENCODE_FAILURE, + })?; let encoded_data = rlp::encode_list::, _>(&data).to_vec(); Ok(smallvec![Value::vector_u8(encoded_data)]) } @@ -346,11 +376,10 @@ fn native_rlp_decode_list_byte_array( _ty_args: Vec, mut args: VecDeque, ) -> SafeNativeResult> { - let encoded_data: Vec = safely_pop_arg!(args, Vec); context.charge( - RLP_ENCODE_DECODE_BASE+ - RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(encoded_data.len() as u64) + RLP_ENCODE_DECODE_BASE + + RLP_ENCODE_DECODE_PER_BYTE * NumBytes::new(encoded_data.len() as u64), )?; let rlp = Rlp::new(&encoded_data); @@ -359,14 +388,17 @@ fn native_rlp_decode_list_byte_array( Ok(decoded) => { //serialize and return data context.charge( - UTIL_FROM_BYTES_BASE+ - UTIL_FROM_BYTES_PER_BYTE * NumBytes::new(encoded_data.len() as u64) + UTIL_FROM_BYTES_BASE + + UTIL_FROM_BYTES_PER_BYTE * NumBytes::new(encoded_data.len() as u64), )?; - let serialized_data = bcs::to_bytes(&decoded) - .map_err(|_| SafeNativeError::Abort { abort_code: E_DECODE_FAILURE })?; + let serialized_data = bcs::to_bytes(&decoded).map_err(|_| SafeNativeError::Abort { + abort_code: E_DECODE_FAILURE, + })?; Ok(smallvec![Value::vector_u8(serialized_data)]) }, - Err(_) => Err(SafeNativeError::Abort { abort_code: E_DECODE_FAILURE }), + Err(_) => Err(SafeNativeError::Abort { + abort_code: E_DECODE_FAILURE, + }), } } @@ -378,12 +410,22 @@ pub fn make_all( natives.extend([ ("native_rlp_encode", native_rlp_encode as RawSafeNative), ("native_rlp_decode", native_rlp_decode as RawSafeNative), - - ("native_rlp_encode_list_scalar", native_rlp_encode_list_scalar as RawSafeNative), - ("native_rlp_decode_list_scalar", native_rlp_decode_list_scalar as RawSafeNative), - - ("native_rlp_encode_list_byte_array", native_rlp_encode_list_byte_array as RawSafeNative), - ("native_rlp_decode_list_byte_array", native_rlp_decode_list_byte_array as RawSafeNative), + ( + "native_rlp_encode_list_scalar", + native_rlp_encode_list_scalar as RawSafeNative, + ), + ( + "native_rlp_decode_list_scalar", + native_rlp_decode_list_scalar as RawSafeNative, + ), + ( + "native_rlp_encode_list_byte_array", + native_rlp_encode_list_byte_array as RawSafeNative, + ), + ( + "native_rlp_decode_list_byte_array", + native_rlp_decode_list_byte_array as RawSafeNative, + ), ]); builder.make_named_natives(natives) diff --git a/aptos-move/framework/src/natives/transaction_context.rs b/aptos-move/framework/src/natives/transaction_context.rs index 9dbc0b189ec..f5c8f50195c 100644 --- a/aptos-move/framework/src/natives/transaction_context.rs +++ b/aptos-move/framework/src/natives/transaction_context.rs @@ -378,6 +378,34 @@ fn get_user_transaction_context_opt_from_context<'a>( .user_transaction_context_opt } +/*************************************************************************************************** + * native fun get_transaction_consensus_hash_internal + * + * gas cost: base_cost + * + * Returns the Keccak-256 hash of the current signed transaction (transaction_consensus_hash). + * Aborts if called outside a user transaction context (e.g. system or view sessions). + * + **************************************************************************************************/ +fn native_get_transaction_consensus_hash_internal( + context: &mut SafeNativeContext, + _ty_args: Vec, + _args: VecDeque, +) -> SafeNativeResult> { + context.charge(TRANSACTION_CONTEXT_GET_TXN_CONSENSUS_HASH_BASE)?; + + let user_transaction_context_opt = get_user_transaction_context_opt_from_context(context); + if let Some(txn_context) = user_transaction_context_opt { + Ok(smallvec![Value::vector_u8( + txn_context.txn_consensus_hash().to_vec() + )]) + } else { + Err(SafeNativeError::Abort { + abort_code: error::invalid_state(abort_codes::ETRANSACTION_CONTEXT_NOT_AVAILABLE), + }) + } +} + /*************************************************************************************************** * module * @@ -406,6 +434,10 @@ pub fn make_all( "multisig_payload_internal", native_multisig_payload_internal, ), + ( + "get_transaction_consensus_hash_internal", + native_get_transaction_consensus_hash_internal, + ), ]; builder.make_named_natives(natives) diff --git a/aptos-move/framework/src/release_bundle.rs b/aptos-move/framework/src/release_bundle.rs index c1aaccd15d3..285a1bb0cca 100644 --- a/aptos-move/framework/src/release_bundle.rs +++ b/aptos-move/framework/src/release_bundle.rs @@ -204,7 +204,11 @@ impl ReleasePackage { // The Sha2-256 digest here is the combined hash of all the hashes of the `.move` files and // the manifest file(Move.toml) in the source package. // Check [move_package::resolution::digest::compile_digest] - emitln!(writer, "// source package's SHA2-256 digest: {}", self.metadata.source_digest); + emitln!( + writer, + "// source package's SHA2-256 digest: {}", + self.metadata.source_digest + ); emitln!(writer, "script {"); writer.indent(); emitln!(writer, "use std::vector;"); diff --git a/aptos-move/framework/supra-framework/doc/aggregator_v2.md b/aptos-move/framework/supra-framework/doc/aggregator_v2.md index de7cb1e7cc7..9876000bc0b 100644 --- a/aptos-move/framework/supra-framework/doc/aggregator_v2.md +++ b/aptos-move/framework/supra-framework/doc/aggregator_v2.md @@ -713,7 +713,7 @@ Useful for when object is sometimes created via string_concat(), and sometimes d Concatenates before, snapshot and after into a single string. snapshot passed needs to have integer type - currently supported types are u64 and u128. Raises EUNSUPPORTED_AGGREGATOR_SNAPSHOT_TYPE if called with another type. -If length of prefix and suffix together exceeds 1024 bytes, ECONCAT_STRING_LENGTH_TOO_LARGE is raised. +If length of prefix and suffix together exceed 1024 bytes, ECONCAT_STRING_LENGTH_TOO_LARGE is raised. Parallelism info: This operation enables parallelism. diff --git a/aptos-move/framework/supra-framework/doc/automation_registry.md b/aptos-move/framework/supra-framework/doc/automation_registry.md index bd959b043df..812a2714480 100644 --- a/aptos-move/framework/supra-framework/doc/automation_registry.md +++ b/aptos-move/framework/supra-framework/doc/automation_registry.md @@ -42,6 +42,7 @@ This contract is part of the Supra Framework and is designed to manage automated - [Struct `TaskCancelledInsufficentBalanceV2`](#0x1_automation_registry_TaskCancelledInsufficentBalanceV2) - [Struct `TaskCancelledCapacitySurpassed`](#0x1_automation_registry_TaskCancelledCapacitySurpassed) - [Struct `TaskCancelledCapacitySurpassedV2`](#0x1_automation_registry_TaskCancelledCapacitySurpassedV2) +- [Struct `TaskCancelledByRuntime`](#0x1_automation_registry_TaskCancelledByRuntime) - [Struct `RemovedTasks`](#0x1_automation_registry_RemovedTasks) - [Struct `ActiveTasks`](#0x1_automation_registry_ActiveTasks) - [Struct `ErrorTaskDoesNotExist`](#0x1_automation_registry_ErrorTaskDoesNotExist) @@ -73,6 +74,7 @@ This contract is part of the Supra Framework and is designed to manage automated - [Function `get_registry_total_locked_balance`](#0x1_automation_registry_get_registry_total_locked_balance) - [Function `get_active_task_ids`](#0x1_automation_registry_get_active_task_ids) - [Function `get_task_details`](#0x1_automation_registry_get_task_details) +- [Function `deconstruct_task_metadata_v2`](#0x1_automation_registry_deconstruct_task_metadata_v2) - [Function `deconstruct_task_metadata`](#0x1_automation_registry_deconstruct_task_metadata) - [Function `get_task_owner`](#0x1_automation_registry_get_task_owner) - [Function `get_task_details_bulk`](#0x1_automation_registry_get_task_details_bulk) @@ -106,7 +108,9 @@ This contract is part of the Supra Framework and is designed to manage automated - [Function `grant_authorization`](#0x1_automation_registry_grant_authorization) - [Function `revoke_authorization`](#0x1_automation_registry_revoke_authorization) - [Function `cancel_task`](#0x1_automation_registry_cancel_task) +- [Function `stop_tasks_internal`](#0x1_automation_registry_stop_tasks_internal) - [Function `stop_tasks`](#0x1_automation_registry_stop_tasks) +- [Function `cancel_invalid_task`](#0x1_automation_registry_cancel_invalid_task) - [Function `stop_system_tasks`](#0x1_automation_registry_stop_system_tasks) - [Function `cancel_system_task`](#0x1_automation_registry_cancel_system_task) - [Function `initialize_refund_bookkeeping_resource`](#0x1_automation_registry_initialize_refund_bookkeeping_resource) @@ -115,7 +119,9 @@ This contract is part of the Supra Framework and is designed to manage automated - [Function `monitor_cycle_end`](#0x1_automation_registry_monitor_cycle_end) - [Function `on_new_epoch`](#0x1_automation_registry_on_new_epoch) - [Function `register`](#0x1_automation_registry_register) +- [Function `register_without_validation`](#0x1_automation_registry_register_without_validation) - [Function `register_system_task`](#0x1_automation_registry_register_system_task) +- [Function `register_system_task_without_validation`](#0x1_automation_registry_register_system_task_without_validation) - [Function `process_tasks`](#0x1_automation_registry_process_tasks) - [Function `on_cycle_transition`](#0x1_automation_registry_on_cycle_transition) - [Function `on_cycle_suspend`](#0x1_automation_registry_on_cycle_suspend) @@ -186,6 +192,7 @@ This contract is part of the Supra Framework and is designed to manage automated use 0x1::supra_coin; use 0x1::system_addresses; use 0x1::timestamp; +use 0x1::transaction_context; use 0x1::vector; use 0x1::vector_utils;
@@ -1812,6 +1819,57 @@ Event emitted when an automation task is cancelled due to automation fee capacit + + + + +## Struct `TaskCancelledByRuntime` + +Emitted when the VM/runtime cancels a task that was registered without payload +validation and was later found to be invalid. The diagnostic_message is a +human-readable explanation provided by the runtime (e.g. BCS decode error, unknown +entry function). Consumers should use this event -- rather than TasksStoppedV2 alone -- +to distinguish runtime-driven cancellations from voluntary owner-initiated stops. + + +
#[event]
+struct TaskCancelledByRuntime has drop, store
+
+ + + +
+Fields + + +
+
+task_index: u64 +
+
+ +
+
+owner: address +
+
+ +
+
+registration_hash: vector<u8> +
+
+ +
+
+diagnostic_message: string::String +
+
+ +
+
+ +
@@ -2558,6 +2616,17 @@ Supra native automation feature is not initialized or enabled + + +Supra automation v2.1 feature is not enabled. Distinct from EDISABLED_AUTOMATION_FEATURE +(which covers the base automation feature) so callers can tell the two conditions apart. + + +
const EDISABLED_AUTOMATION_V2_1_FEATURE: u64 = 49;
+
+ + + Task index list is empty. @@ -2668,6 +2737,16 @@ Invalid number of auxiliary data. + + +The refund fee for remaining cycle time is greater than total cycle fee for the task. + + +
const EINVALID_CYCLE_REFUND_FEE: u64 = 48;
+
+ + + Invalid expiry time: it cannot be earlier than the current time @@ -3520,6 +3599,59 @@ Error will be returned if entry with specified task index does not exist. + + + + +## Function `deconstruct_task_metadata_v2` + +Retrieves specific metadata details of an automation task entry by its task index. + +1. u64 - The task index. +2. address - The owner of the task. +3. vector<u8> - The payload transaction (encoded). +4. u64 - The expiry time of the task (timestamp). +5. vector<u8> - The hash of the transaction. +6. u64 - The maximum gas amount allowed for the task. +7. u64 - The gas price cap for executing the task. +8. u64 - The automation fee cap for the current epoch. +9. vector<vector<u8>> - Auxiliary data related to the task (can be multiple items). +10. u64 - The time at which the task was registered (timestamp). +11. u8 - The state of the task (e.g., active, cancelled, completed). +12. u64 - The locked fee reserved for the next epoch execution. + + +
public fun deconstruct_task_metadata_v2(task_metadata: &automation_registry::AutomationTaskMetaData): (u64, address, vector<u8>, u64, vector<u8>, u64, u64, u64, vector<vector<u8>>, u64, u8, u64)
+
+ + + +
+Implementation + + +
public fun deconstruct_task_metadata_v2(
+    task_metadata: &AutomationTaskMetaData
+): (u64, address, vector<u8>, u64, vector<u8>, u64, u64, u64, vector<vector<u8>>, u64, u8, u64) {
+    (
+        task_metadata.task_index,
+        task_metadata.owner,
+        task_metadata.payload_tx,
+        task_metadata.expiry_time,
+        task_metadata.tx_hash,
+        task_metadata.max_gas_amount,
+        task_metadata.gas_price_cap,
+        task_metadata.automation_fee_cap_for_epoch,
+        task_metadata.aux_data,
+        task_metadata.registration_time,
+        task_metadata.state,
+        task_metadata.locked_fee_for_next_epoch
+    )
+}
+
+ + +
@@ -4621,18 +4753,19 @@ Committed gas-limit is updated by reducing it with the max-gas-amount of the can - + -## Function `stop_tasks` +## Function `stop_tasks_internal` -Immediately stops automation tasks for the specified task_indexes. -Only tasks that exist and are owned by the sender can be stopped. -If any of the specified tasks are not owned by the sender, the transaction will abort. -When a task is stopped, the committed gas for the next epoch is reduced -by the max gas amount of the stopped task. Half of the remaining task fee is refunded. +Core logic for immediately stopping a set of user automation tasks owned by owner. +Extracted from the public entry stop_tasks so the same refund-and-removal path can be +reused by the VM-only cancel_invalid_task without requiring a signer from the owner. +Callers are responsible for ensuring owner is the legitimate task owner before calling; +the per-task ownership assert inside this function provides a defence-in-depth check. -
public entry fun stop_tasks(owner_signer: &signer, task_indexes: vector<u64>)
+
+
fun stop_tasks_internal(owner: address, task_indexes: vector<u64>)
 
@@ -4641,8 +4774,8 @@ by the max gas amount of the stopped task. Half of the remaining task fee is ref Implementation -
public entry fun stop_tasks(
-    owner_signer: &signer,
+
fun stop_tasks_internal(
+    owner: address,
     task_indexes: vector<u64>
 ) acquires AutomationRegistryV2, ActiveAutomationRegistryConfigV2, AutomationCycleDetails, AutomationRefundBookkeeping {
     assert!(features::supra_native_automation_enabled(), EDISABLED_AUTOMATION_FEATURE);
@@ -4651,7 +4784,6 @@ by the max gas amount of the stopped task. Half of the remaining task fee is ref
     // Ensure that task indexes are provided
     assert!(!vector::is_empty(&task_indexes), EEMPTY_TASK_INDEXES);
 
-    let owner = signer::address_of(owner_signer);
     let automation_registry = &mut borrow_global_mut<AutomationRegistryV2>(@supra_framework).main;
     let arc = borrow_global<ActiveAutomationRegistryConfigV2>(@supra_framework).main_config;
     let refund_bookkeeping = borrow_global_mut<AutomationRefundBookkeeping>(@supra_framework);
@@ -4663,7 +4795,7 @@ by the max gas amount of the stopped task. Half of the remaining task fee is ref
 
     let stopped_task_details = vector[];
     let total_refund_fee = 0;
-    let epoch_locked_fees = automation_registry.epoch_locked_fees;
+    let total_cycle_locked_fees = automation_registry.epoch_locked_fees;
 
     // Calculate refundable fee for this remaining time task in current epoch
     let current_time = timestamp::now_seconds();
@@ -4700,8 +4832,14 @@ by the max gas amount of the stopped task. Half of the remaining task fee is ref
                 automation_registry.gas_committed_for_next_epoch = automation_registry.gas_committed_for_next_epoch - task.max_gas_amount;
             };
 
-            let (epoch_fee_refund, deposit_refund) = if (task.state != PENDING) {
-                let task_fee = calculate_task_fee(
+            let (cycle_locked_fee_for_task, cycle_fee_refund, deposit_refund) = if (task.state != PENDING) {
+                let task_fee_for_full_cycle =
+                    calculate_automation_fee_for_interval(
+                        cycle_info.duration_secs,
+                        task.max_gas_amount,
+                        automation_fee_per_sec,
+                        arc.registry_max_gas_cap);
+                let task_fee_for_residual_time = calculate_task_fee(
                     &arc,
                     &task,
                     residual_interval,
@@ -4709,27 +4847,28 @@ by the max gas amount of the stopped task. Half of the remaining task fee is ref
                     automation_fee_per_sec
                 );
                 // Refund full deposit and the half of the remaining run-time fee when task is active or cancelled stage
-                (task_fee / REFUND_FRACTION, task.locked_fee_for_next_epoch)
+                (task_fee_for_full_cycle, task_fee_for_residual_time / REFUND_FRACTION, task.locked_fee_for_next_epoch)
             } else {
-                (0, (task.locked_fee_for_next_epoch / REFUND_FRACTION))
+                (0, 0, (task.locked_fee_for_next_epoch / REFUND_FRACTION))
             };
             let result = safe_unlock_locked_deposit(
                 refund_bookkeeping,
                 task.locked_fee_for_next_epoch,
                 task.task_index);
             assert!(result, EDEPOSIT_REFUND);
-            let (result, remaining_epoch_locked_fees) = safe_unlock_locked_epoch_fee(
-                epoch_locked_fees,
-                epoch_fee_refund,
+            assert!(cycle_locked_fee_for_task >= cycle_fee_refund, EINVALID_CYCLE_REFUND_FEE);
+            let (result, remaining_cycle_locked_fees) = safe_unlock_locked_epoch_fee(
+                total_cycle_locked_fees,
+                cycle_locked_fee_for_task,
                 task.task_index);
             assert!(result, EEPOCH_FEE_REFUND);
-            epoch_locked_fees = remaining_epoch_locked_fees;
+            total_cycle_locked_fees = remaining_cycle_locked_fees;
 
-            total_refund_fee = total_refund_fee + (epoch_fee_refund + deposit_refund);
+            total_refund_fee = total_refund_fee + (cycle_fee_refund + deposit_refund);
 
             vector::push_back(
                 &mut stopped_task_details,
-                TaskStoppedV2 { task_index, deposit_refund, epoch_fee_refund, registration_hash: task.tx_hash }
+                TaskStoppedV2 { task_index, deposit_refund, epoch_fee_refund: cycle_fee_refund, registration_hash: task.tx_hash }
             );
         }
     });
@@ -4743,6 +4882,7 @@ by the max gas amount of the stopped task. Half of the remaining task fee is ref
         let resource_account_balance = coin::balance<SupraCoin>(automation_registry.registry_fee_address);
         assert!(resource_account_balance >= total_refund_fee, EINSUFFICIENT_BALANCE_FOR_REFUND);
         coin::transfer<SupraCoin>(&resource_signer, owner, total_refund_fee);
+        automation_registry.epoch_locked_fees = total_cycle_locked_fees;
 
         // Emit task stopped event
         event::emit(TasksStoppedV2 {
@@ -4755,6 +4895,110 @@ by the max gas amount of the stopped task. Half of the remaining task fee is ref
 
 
 
+
+
+
+
+## Function `stop_tasks`
+
+Immediately stops automation tasks for the specified task_indexes.
+Only tasks that exist and are owned by the sender can be stopped.
+If any of the specified tasks are not owned by the sender, the transaction will abort.
+When a task is stopped, the committed gas for the next epoch is reduced
+by the max gas amount of the stopped task. Half of the remaining task fee is refunded.
+
+
+
public entry fun stop_tasks(owner_signer: &signer, task_indexes: vector<u64>)
+
+ + + +
+Implementation + + +
public entry fun stop_tasks(
+    owner_signer: &signer,
+    task_indexes: vector<u64>
+) acquires AutomationRegistryV2, ActiveAutomationRegistryConfigV2, AutomationCycleDetails, AutomationRefundBookkeeping {
+    stop_tasks_internal(signer::address_of(owner_signer), task_indexes)
+}
+
+ + + +
+ + + +## Function `cancel_invalid_task` + +Cancels a single automation task that the runtime has determined to be invalid. +May only be called by the VM (enforced via system_addresses::assert_vm). + +This is the runtime-side remedy for tasks registered through +register_without_validation: because that path skips BCS/entry-function checks, +a malformed payload may reach the scheduler and fail repeatedly. The runtime calls +this function to remove the task immediately, refund the owner in full (same policy +as a voluntary stop_tasks call), and emit a diagnostic event so the owner can see +why the task was cancelled. + +Two events are emitted: +- TasksStoppedV2 (fee refund amounts, via stop_tasks_internal) +- TaskCancelledByRuntime (task identity + human-readable diagnostic message) + + +
fun cancel_invalid_task(vm: signer, task_index: u64, diagnostic_message: string::String)
+
+ + + +
+Implementation + + +
fun cancel_invalid_task(
+    vm: signer,
+    task_index: u64,
+    diagnostic_message: std::string::String,
+) acquires AutomationRegistryV2, ActiveAutomationRegistryConfigV2, AutomationCycleDetails, AutomationRefundBookkeeping {
+    // Guard: only the VM may trigger runtime cancellation.
+    system_addresses::assert_vm(&vm);
+
+    // Read owner address and registration hash before the mutable borrow inside
+    // stop_tasks_internal. AutomationTaskMetaData has `copy` ability, so
+    // enumerable_map::get_value returns an owned copy -- no live reference survives
+    // this block, allowing the subsequent mutable borrow to proceed without conflict.
+    let owner;
+    let registration_hash;
+    {
+        let automation_registry = borrow_global<AutomationRegistryV2>(@supra_framework);
+        assert!(
+            enumerable_map::contains(&automation_registry.main.tasks, task_index),
+            EAUTOMATION_TASK_NOT_FOUND
+        );
+        let task = enumerable_map::get_value(&automation_registry.main.tasks, task_index);
+        owner = task.owner;
+        registration_hash = task.tx_hash;
+    };
+
+    // Perform the full refund and removal -- same path as a voluntary stop_tasks call.
+    // Also emits TasksStoppedV2 with the per-task fee detail.
+    stop_tasks_internal(owner, vector[task_index]);
+
+    // Emit the runtime-specific event so indexers/explorers can surface the diagnostic
+    // message to the owner rather than showing only an unexplained stop.
+    event::emit(TaskCancelledByRuntime {
+        task_index,
+        owner,
+        registration_hash,
+        diagnostic_message,
+    });
+}
+
+ + +
@@ -4888,6 +5132,7 @@ Committed gas-limit is updated by reducing it with the max-gas-amount of the can assert!(automation_task_metadata.state != CANCELLED, EALREADY_CANCELLED); if (automation_task_metadata.state == PENDING) { enumerable_map::remove_value(&mut automation_registry.main.tasks, task_index); + vector::remove_value(&mut automation_registry.system_tasks_state.task_ids, &task_index); } else { // it is safe not to check the state as above, the cancelled tasks are already rejected. let automation_task_metadata_mut = enumerable_map::get_value_mut( &mut automation_registry.main.tasks, @@ -5374,6 +5619,62 @@ Registers a new automation task entry. + + + + +## Function `register_without_validation` + +Registers a new automation task from a smart contract call. + +Unlike the AutomationRegistrationPayload transaction path (which calls the private +register via the VM and performs full payload validation before execution), this +function does NOT validate that payload_tx encodes a well-formed entry function with +correct parameter types. If the payload is malformed, the task will fail silently at +execution time and the caller will have paid registration and deposit fees for nothing. +The caller is responsible for providing a valid BCS-encoded EntryFunction payload. + +The required consenus hash of the transaciton registering the task is obtained from native +layer. + +Requires both supra_native_automation_enabled and supra_automation_v2_1_enabled. + + +
public fun register_without_validation(owner_signer: &signer, payload_tx: vector<u8>, expiry_time: u64, max_gas_amount: u64, gas_price_cap: u64, automation_fee_cap_for_epoch: u64, aux_data: vector<vector<u8>>)
+
+ + + +
+Implementation + + +
public fun register_without_validation(
+    owner_signer: &signer,
+    payload_tx: vector<u8>,
+    expiry_time: u64,
+    max_gas_amount: u64,
+    gas_price_cap: u64,
+    automation_fee_cap_for_epoch: u64,
+    aux_data: vector<vector<u8>>
+) acquires AutomationRegistryV2, AutomationCycleDetails, ActiveAutomationRegistryConfigV2, AutomationRefundBookkeeping {
+    assert!(features::supra_automation_v2_1_enabled(), EDISABLED_AUTOMATION_V2_1_FEATURE);
+    let tx_hash = supra_framework::transaction_context::get_transaction_consensus_hash();
+    register(
+        owner_signer,
+        payload_tx,
+        expiry_time,
+        max_gas_amount,
+        gas_price_cap,
+        automation_fee_cap_for_epoch,
+        tx_hash,
+        aux_data,
+    )
+}
+
+ + +
@@ -5475,6 +5776,58 @@ Note, system tasks are not charged registration and deposit fee. + + + + +## Function `register_system_task_without_validation` + +Registers a new system automation task from a smart contract call. + +Unlike the AutomationRegistrationPayload transaction path (which calls the private +register_system_task via the VM and performs full payload validation before execution), this +function does NOT validate that payload_tx encodes a well-formed entry function with +correct parameter types. If the payload is malformed, the task will fail silently at +execution time and the caller will have paid registration and deposit fees for nothing. +The caller is responsible for providing a valid BCS-encoded EntryFunction payload. + +The required consenus hash of the transaciton registering the task is obtained from native +layer. + +Requires both supra_native_automation_enabled and supra_automation_v2_1_enabled. + + +
public fun register_system_task_without_validation(owner_signer: &signer, payload_tx: vector<u8>, expiry_time: u64, max_gas_amount: u64, aux_data: vector<vector<u8>>)
+
+ + + +
+Implementation + + +
public fun register_system_task_without_validation(
+    owner_signer: &signer,
+    payload_tx: vector<u8>,
+    expiry_time: u64,
+    max_gas_amount: u64,
+    aux_data: vector<vector<u8>>
+) acquires AutomationRegistryV2, AutomationCycleDetails, ActiveAutomationRegistryConfigV2 {
+    assert!(features::supra_automation_v2_1_enabled(), EDISABLED_AUTOMATION_V2_1_FEATURE);
+    let tx_hash = supra_framework::transaction_context::get_transaction_consensus_hash();
+    register_system_task(
+        owner_signer,
+        payload_tx,
+        expiry_time,
+        max_gas_amount,
+        tx_hash,
+        aux_data,
+    )
+}
+
+ + +
@@ -5654,6 +6007,7 @@ In case if end is identified the registry state is update to CYCLE_READY and cor vector::for_each(task_indexes, |task_index| { if (enumerable_map::contains(&automation_registry.main.tasks, task_index)) { let task = enumerable_map::remove_value(&mut automation_registry.main.tasks, task_index); + vector::push_back(&mut removed_tasks, task_index); mark_task_processed(transition_state, task_index); // Nothing to refund for GST tasks if (is_of_type(&task, UST)) { @@ -5666,9 +6020,8 @@ In case if end is identified the registry state is update to CYCLE_READY and cor &resource_signer, epoch_locked_fees, current_time, - &mut removed_tasks ) - }; + } } }); @@ -5902,7 +6255,7 @@ Removes system task from registry state. Refunds the deposit fee and any autoamtion fees of the task. -
fun refund_task_fees(task: automation_registry::AutomationTaskMetaData, automation_registry: &mut automation_registry::AutomationRegistry, refund_bookkeeping: &mut automation_registry::AutomationRefundBookkeeping, arc: &automation_registry::ActiveAutomationRegistryConfigV2, transition_state: &mut automation_registry::TransitionState, resource_signer: &signer, epoch_locked_fees: u64, current_time: u64, removed_tasks: &mut vector<u64>): u64
+
fun refund_task_fees(task: automation_registry::AutomationTaskMetaData, automation_registry: &mut automation_registry::AutomationRegistry, refund_bookkeeping: &mut automation_registry::AutomationRefundBookkeeping, arc: &automation_registry::ActiveAutomationRegistryConfigV2, transition_state: &mut automation_registry::TransitionState, resource_signer: &signer, epoch_locked_fees: u64, current_time: u64): u64
 
@@ -5920,7 +6273,6 @@ Refunds the deposit fee and any autoamtion fees of the task. resource_signer: &signer, epoch_locked_fees: u64, current_time: u64, - removed_tasks: &mut vector<u64> ) : u64 { assert!(is_of_type(&task, UST), EREGISTERED_TASK_INVALID_TYPE); @@ -5950,7 +6302,6 @@ Refunds the deposit fee and any autoamtion fees of the task. task.owner, task.locked_fee_for_next_epoch, task.locked_fee_for_next_epoch); - vector::push_back(removed_tasks, task.task_index); epoch_locked_fees }
diff --git a/aptos-move/framework/supra-framework/doc/block.md b/aptos-move/framework/supra-framework/doc/block.md index 978777c3c42..5a66c681285 100644 --- a/aptos-move/framework/supra-framework/doc/block.md +++ b/aptos-move/framework/supra-framework/doc/block.md @@ -47,6 +47,7 @@ This module defines a struct storing the metadata of the block and new block eve use 0x1::error; use 0x1::event; use 0x1::features; +use 0x1::leader_ban_registry; use 0x1::option; use 0x1::randomness; use 0x1::reconfiguration; @@ -426,23 +427,34 @@ This can only be called during Genesis. Implementation -
public(friend) fun initialize(supra_framework: &signer, epoch_interval_microsecs: u64) {
+
public(friend) fun initialize(
+    supra_framework: &signer, epoch_interval_microsecs: u64
+) {
     system_addresses::assert_supra_framework(supra_framework);
-    assert!(epoch_interval_microsecs != 0, error::invalid_argument(EZERO_EPOCH_INTERVAL));
+    assert!(
+        epoch_interval_microsecs != 0,
+        error::invalid_argument(EZERO_EPOCH_INTERVAL)
+    );
 
-    move_to<CommitHistory>(supra_framework, CommitHistory {
-        max_capacity: 2000,
-        next_idx: 0,
-        table: table_with_length::new(),
-    });
+    move_to<CommitHistory>(
+        supra_framework,
+        CommitHistory {
+            max_capacity: 2000,
+            next_idx: 0,
+            table: table_with_length::new()
+        }
+    );
 
     move_to<BlockResource>(
         supra_framework,
         BlockResource {
             height: 0,
             epoch_interval: epoch_interval_microsecs,
-            new_block_events: account::new_event_handle<NewBlockEvent>(supra_framework),
-            update_epoch_interval_events: account::new_event_handle<UpdateEpochIntervalEvent>(supra_framework),
+            new_block_events: account::new_event_handle<NewBlockEvent>(
+                supra_framework
+            ),
+            update_epoch_interval_events: account::new_event_handle<
+                UpdateEpochIntervalEvent>(supra_framework)
         }
     );
 }
@@ -470,11 +482,10 @@ Initialize the commit history resource if it's not in genesis.
 
 
public fun initialize_commit_history(fx: &signer, max_capacity: u32) {
     assert!(max_capacity != 0, error::invalid_argument(EZERO_MAX_CAPACITY));
-    move_to<CommitHistory>(fx, CommitHistory {
-        max_capacity,
-        next_idx: 0,
-        table: table_with_length::new(),
-    });
+    move_to<CommitHistory>(
+        fx,
+        CommitHistory { max_capacity, next_idx: 0, table: table_with_length::new() }
+    );
 }
 
@@ -500,8 +511,7 @@ Can only be called as part of the Supra governance proposal process established
public fun update_epoch_interval_microsecs(
-    supra_framework: &signer,
-    new_epoch_interval: u64,
+    supra_framework: &signer, new_epoch_interval: u64
 ) acquires BlockResource {
     system_addresses::assert_supra_framework(supra_framework);
     assert!(new_epoch_interval != 0, error::invalid_argument(EZERO_EPOCH_INTERVAL));
@@ -511,13 +521,11 @@ Can only be called as part of the Supra governance proposal process established
     block_resource.epoch_interval = new_epoch_interval;
 
     if (std::features::module_event_migration_enabled()) {
-        event::emit(
-            UpdateEpochInterval { old_epoch_interval, new_epoch_interval },
-        );
+        event::emit(UpdateEpochInterval { old_epoch_interval, new_epoch_interval });
     } else {
         event::emit_event<UpdateEpochIntervalEvent>(
             &mut block_resource.update_epoch_interval_events,
-            UpdateEpochIntervalEvent { old_epoch_interval, new_epoch_interval },
+            UpdateEpochIntervalEvent { old_epoch_interval, new_epoch_interval }
         );
     };
 }
@@ -584,7 +592,7 @@ Return epoch interval in seconds.
     // Blocks can only be produced by a valid proposer or by the VM itself for Nil blocks (no user txs).
     assert!(
         proposer == @vm_reserved || stake::is_current_epoch_validator(proposer),
-        error::permission_denied(EINVALID_PROPOSER),
+        error::permission_denied(EINVALID_PROPOSER)
     );
 
     let proposer_index = option::none();
@@ -603,7 +611,7 @@ Return epoch interval in seconds.
         previous_block_votes_bitvec,
         proposer,
         failed_proposer_indices,
-        time_microseconds: timestamp,
+        time_microseconds: timestamp
     };
     emit_new_block_event(vm, &mut block_metadata_ref.new_block_events, new_block_event);
 
@@ -612,6 +620,13 @@ Return epoch interval in seconds.
     stake::update_performance_statistics(proposer_index, failed_proposer_indices);
     state_storage::on_new_block(reconfiguration::current_epoch());
 
+    leader_ban_registry::update_ban_registry(
+        epoch,
+        round,
+        proposer_index,
+        failed_proposer_indices
+    );
+
     automation_registry::monitor_cycle_end();
 
     block_metadata_ref.epoch_interval
@@ -649,16 +664,17 @@ The runtime always runs this before executing the transactions in a block.
     previous_block_votes_bitvec: vector<u8>,
     timestamp: u64
 ) acquires BlockResource, CommitHistory {
-    let epoch_interval = block_prologue_common(
-        &vm,
-        hash,
-        epoch,
-        round,
-        proposer,
-        failed_proposer_indices,
-        previous_block_votes_bitvec,
-        timestamp
-    );
+    let epoch_interval =
+        block_prologue_common(
+            &vm,
+            hash,
+            epoch,
+            round,
+            proposer,
+            failed_proposer_indices,
+            previous_block_votes_bitvec,
+            timestamp
+        );
     randomness::on_new_block(&vm, epoch, round, option::none());
     if (timestamp - reconfiguration::last_reconfiguration_time() >= epoch_interval) {
         reconfiguration::reconfigure();
@@ -677,7 +693,7 @@ The runtime always runs this before executing the transactions in a block.
 block_prologue() but trigger reconfiguration with DKG after epoch timed out.
 
 
-
fun block_prologue_ext(vm: signer, hash: address, epoch: u64, round: u64, proposer: address, failed_proposer_indices: vector<u64>, previous_block_votes_bitvec: vector<u8>, timestamp: u64, randomness_seed: option::Option<vector<u8>>)
+
fun block_prologue_ext(vm: signer, hash: address, epoch: u64, round: u64, proposer: address, failed_proposer_indices: vector<u64>, previous_block_votes_bitvec: vector<u8>, timestamp: u64, randomness_seed_vec: vector<u8>)
 
@@ -695,18 +711,26 @@ The runtime always runs this before executing the transactions in a block. failed_proposer_indices: vector<u64>, previous_block_votes_bitvec: vector<u8>, timestamp: u64, - randomness_seed: Option<vector<u8>>, + randomness_seed_vec: vector<u8> ) acquires BlockResource, CommitHistory { - let epoch_interval = block_prologue_common( - &vm, - hash, - epoch, - round, - proposer, - failed_proposer_indices, - previous_block_votes_bitvec, - timestamp - ); + let randomness_seed = + if (vector::length(&randomness_seed_vec) == 0) { + option::none() + } else { + option::some(randomness_seed_vec) + }; + + let epoch_interval = + block_prologue_common( + &vm, + hash, + epoch, + round, + proposer, + failed_proposer_indices, + previous_block_votes_bitvec, + timestamp + ); randomness::on_new_block(&vm, epoch, round, randomness_seed); if (timestamp - reconfiguration::last_reconfiguration_time() >= epoch_interval) { @@ -800,16 +824,20 @@ Emit the event and update height and global timestamp if (table_with_length::contains(&commit_history_ref.table, idx)) { table_with_length::remove(&mut commit_history_ref.table, idx); }; - table_with_length::add(&mut commit_history_ref.table, idx, copy new_block_event); + table_with_length::add( + &mut commit_history_ref.table, idx, copy new_block_event + ); spec { assume idx + 1 <= MAX_U32; }; commit_history_ref.next_idx = (idx + 1) % commit_history_ref.max_capacity; }; - timestamp::update_global_time(vm, new_block_event.proposer, new_block_event.time_microseconds); + timestamp::update_global_time( + vm, new_block_event.proposer, new_block_event.time_microseconds + ); assert!( event::counter(event_handle) == new_block_event.height, - error::invalid_argument(ENUM_NEW_BLOCK_EVENTS_DOES_NOT_MATCH_BLOCK_HEIGHT), + error::invalid_argument(ENUM_NEW_BLOCK_EVENTS_DOES_NOT_MATCH_BLOCK_HEIGHT) ); event::emit_event<NewBlockEvent>(event_handle, new_block_event); } @@ -850,7 +878,7 @@ reconfiguration event. previous_block_votes_bitvec: vector::empty(), proposer: @vm_reserved, failed_proposer_indices: vector::empty(), - time_microseconds: timestamp::now_microseconds(), + time_microseconds: timestamp::now_microseconds() }, ); } @@ -878,8 +906,7 @@ new block event for WriteSetPayload.
public fun emit_writeset_block_event(
-    vm_signer: &signer,
-    fake_block_hash: address
+    vm_signer: &signer, fake_block_hash: address
 ) acquires BlockResource, CommitHistory {
     system_addresses::assert_vm(vm_signer);
     let block_metadata_ref = borrow_global_mut<BlockResource>(@supra_framework);
@@ -896,7 +923,7 @@ new block event for WriteSetPayload.
             previous_block_votes_bitvec: vector::empty(),
             proposer: @vm_reserved,
             failed_proposer_indices: vector::empty(),
-            time_microseconds: timestamp::now_microseconds(),
+            time_microseconds: timestamp::now_microseconds()
         },
     );
 }
@@ -1249,7 +1276,7 @@ The BlockResource existed under the @supra_framework.
 ### Function `block_prologue_ext`
 
 
-
fun block_prologue_ext(vm: signer, hash: address, epoch: u64, round: u64, proposer: address, failed_proposer_indices: vector<u64>, previous_block_votes_bitvec: vector<u8>, timestamp: u64, randomness_seed: option::Option<vector<u8>>)
+
fun block_prologue_ext(vm: signer, hash: address, epoch: u64, round: u64, proposer: address, failed_proposer_indices: vector<u64>, previous_block_votes_bitvec: vector<u8>, timestamp: u64, randomness_seed_vec: vector<u8>)
 
diff --git a/aptos-move/framework/supra-framework/doc/committee_map.md b/aptos-move/framework/supra-framework/doc/committee_map.md index 88ce2e20ed0..a14ca00f3a0 100644 --- a/aptos-move/framework/supra-framework/doc/committee_map.md +++ b/aptos-move/framework/supra-framework/doc/committee_map.md @@ -36,6 +36,7 @@ requirements: - [Function `get_committeeInfo_address`](#0x1_committee_map_get_committeeInfo_address) - [Function `init_module`](#0x1_committee_map_init_module) - [Function `validate_committee_type`](#0x1_committee_map_validate_committee_type) +- [Function `assert_removal_allowed`](#0x1_committee_map_assert_removal_allowed) - [Function `get_committee_info`](#0x1_committee_map_get_committee_info) - [Function `get_committee_ids`](#0x1_committee_map_get_committee_ids) - [Function `get_committee_id`](#0x1_committee_map_get_committee_id) @@ -646,62 +647,112 @@ Capability that grants an owner the right to perform action. - + -Define the CommitteeType as constants +The number of nodes in the CLAN is too small or even -
const FAMILY: u8 = 1;
+
const ECLAN_TOO_SMALL_OR_EVEN_NODES_IN_CLAN: u64 = 13;
 
- + + +The number of nodes in the CLAN is invalid + + +
const EINVALID_CLAN_NODE_NUMBERS: u64 = 9;
+
+ + + + The committee is not found -
const INVALID_COMMITTEE_ID: u64 = 6;
+
const EINVALID_COMMITTEE_ID: u64 = 6;
 
- + -The number of committee is not equal to the number of committee member +The number of committees is not equal to the number of committee members -
const INVALID_COMMITTEE_NUMBERS: u64 = 4;
+
const EINVALID_COMMITTEE_NUMBERS: u64 = 4;
 
- + The committee type is invalid -
const INVALID_COMMITTEE_TYPE: u64 = 7;
+
const EINVALID_COMMITTEE_TYPE: u64 = 7;
+
+ + + + + +The number of nodes in the FAMILY is invalid + + +
const EINVALID_FAMILIY_NODE_NUMBERS: u64 = 10;
 
- + The number of nodes in the committee is invalid -
const INVALID_NODE_NUMBERS: u64 = 8;
+
const EINVALID_NODE_NUMBERS: u64 = 8;
 
- + + +The number of nodes in the TRIBE is invalid + + +
const EINVALID_TRIBE_NODE_NUMBERS: u64 = 11;
+
+ + + + The node is not found in the committee -
const NODE_NOT_FOUND: u64 = 5;
+
const ENODE_NOT_FOUND: u64 = 5;
+
+ + + + + +The number of nodes in the committee is ZERO + + +
const EZERO_COMMITTEE_NODE_NUMBER: u64 = 12;
+
+ + + + + +Define the CommitteeType as constants + + +
const FAMILY: u8 = 1;
 
@@ -766,7 +817,7 @@ Internal - Assert if the node exists in the committee
fun ensure_node_address_exist(committee: &CommitteeInfo, node_address: address) {
-    assert!(does_node_exist(committee, node_address), error::invalid_argument(NODE_NOT_FOUND))
+    assert!(does_node_exist(committee, node_address), error::invalid_argument(ENODE_NOT_FOUND))
 }
 
@@ -930,16 +981,16 @@ Its Initial function which will be executed automatically while deployed package
fun validate_committee_type(committee_type: u8, num_of_nodes: u64): u8 {
-    assert!(committee_type >= FAMILY && committee_type <= TRIBE, INVALID_COMMITTEE_TYPE);
+    assert!(committee_type >= FAMILY && committee_type <= TRIBE, EINVALID_COMMITTEE_TYPE);
     if (committee_type == FAMILY) {
         // f+1, number of nodes in a family committee should be greater than 1
-        assert!(num_of_nodes > 1, INVALID_NODE_NUMBERS);
+        assert!(num_of_nodes > 1, EINVALID_FAMILIY_NODE_NUMBERS);
     } else if (committee_type == CLAN) {
-        // 2f+1, number of nodes in a clan committee should be odd and greater than 3
-        assert!(num_of_nodes >= 3 && num_of_nodes % 2 == 1, INVALID_NODE_NUMBERS);
+        // 2f+1, number of nodes in a clan committee should be odd and greater than or equal to 3
+        assert!(num_of_nodes >= 3 && num_of_nodes % 2 == 1, ECLAN_TOO_SMALL_OR_EVEN_NODES_IN_CLAN);
     } else {
-        // 3f+1, number of nodes in a tribe committee should be in the format of 3f+1 and greater than 4
-        assert!(num_of_nodes >= 4 && (num_of_nodes - 1) % 3 == 0, INVALID_NODE_NUMBERS);
+        // 3f+1, number of nodes in a tribe committee should be in the format of 3f+1 and greater than or equal to 4
+        assert!(num_of_nodes >= 4 && (num_of_nodes - 1) % 3 == 0, EINVALID_TRIBE_NODE_NUMBERS);
     };
     committee_type
 }
@@ -947,6 +998,33 @@ Its Initial function which will be executed automatically while deployed package
 
 
 
+
+
+
+
+## Function `assert_removal_allowed`
+
+Ensures removing exactly one member keeps the committee type invariants valid.
+
+
+
fun assert_removal_allowed(committee: &committee_map::CommitteeInfo)
+
+ + + +
+Implementation + + +
fun assert_removal_allowed(committee: &CommitteeInfo) {
+    let current_num_of_nodes = simple_map::length(&committee.map);
+    assert!(current_num_of_nodes > 0, EZERO_COMMITTEE_NODE_NUMBER);
+    validate_committee_type(committee.committee_type, current_num_of_nodes - 1);
+}
+
+ + +
@@ -1076,7 +1154,7 @@ Get the node's information let committee = simple_map::borrow(&committee_store.committee_map, &id); let (addrs, nodes) = simple_map::to_vec_pair(committee.map); let (flag, index) = vector::index_of(&addrs, &node_address); - assert!(flag, error::invalid_argument(NODE_NOT_FOUND)); + assert!(flag, error::invalid_argument(ENODE_NOT_FOUND)); let node_info = vector::borrow(&nodes, index); NodeData { @@ -1259,31 +1337,31 @@ This function is used to add a new committee to the store rpc_port: vector<u16>, committee_type: u8 ) acquires CommitteeInfoStore, SupraCommitteeEventHandler { - // Assert the length of the vector for two are the same + // Assert the length of the vector for two is the same let node_address_len = vector::length(&node_addresses); assert!( node_address_len == vector::length(&ip_public_address), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( node_address_len == vector::length(&node_public_key), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( node_address_len == vector::length(&network_public_key), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( node_address_len == vector::length(&cg_public_key), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( node_address_len == vector::length(&network_port), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( node_address_len == vector::length(&rpc_port), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); // Only the OwnerCap capability can access it let _acquire = &capability::acquire(owner_signer, &OwnerCap {}); @@ -1377,31 +1455,31 @@ Add the committee in bulk let ids_len = vector::length(&ids); assert!( ids_len == vector::length(&node_addresses_bulk), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( ids_len == vector::length(&ip_public_address_bulk), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( ids_len == vector::length(&node_public_key_bulk), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( ids_len == vector::length(&network_public_key_bulk), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( ids_len == vector::length(&cg_public_key_bulk), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( ids_len == vector::length(&network_port_bulk), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( ids_len == vector::length(&rpc_por_bulkt), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); while (vector::length(&ids) != 0) { let id = vector::pop_back(&mut ids); @@ -1461,7 +1539,7 @@ Remove the committee from the store let committee_store = borrow_global_mut<CommitteeInfoStore>(com_store_addr); assert!( simple_map::contains_key(&committee_store.committee_map, &id), - error::invalid_argument(INVALID_COMMITTEE_ID) + error::invalid_argument(EINVALID_COMMITTEE_ID) ); let (id, committee_info) = simple_map::remove(&mut committee_store.committee_map, &id); // Also remove the node_to_committee_map @@ -1470,7 +1548,7 @@ Remove the committee from the store let addr = vector::pop_back(&mut addrs); assert!( simple_map::contains_key(&committee_store.node_to_committee_map, &addr), - error::invalid_argument(NODE_NOT_FOUND) + error::invalid_argument(ENODE_NOT_FOUND) ); simple_map::remove(&mut committee_store.node_to_committee_map, &addr); }; @@ -1552,6 +1630,27 @@ Upsert the node to the committee let _acquire = &capability::acquire(owner_signer, &OwnerCap {}); let committee_store = borrow_global_mut<CommitteeInfoStore>(com_store_addr); + let event_handler = borrow_global_mut<SupraCommitteeEventHandler>(get_committeeInfo_address(owner_signer)); + + // If the node is already associated with another committee, remove the stale entry first. + if (simple_map::contains_key(&committee_store.node_to_committee_map, &node_address)) { + let old_committee_id = *simple_map::borrow(&committee_store.node_to_committee_map, &node_address); + if (old_committee_id != id && simple_map::contains_key(&committee_store.committee_map, &old_committee_id)) { + let old_committee = simple_map::borrow_mut(&mut committee_store.committee_map, &old_committee_id); + if (does_node_exist(old_committee, node_address)) { + assert_removal_allowed(old_committee); + let (_, old_node_info) = simple_map::remove(&mut old_committee.map, &node_address); + emit_event( + &mut event_handler.remove_committee_member, + RemoveCommitteeMemberEvent { + committee_id: old_committee_id, + committee_member: old_node_info + } + ) + } + } + }; + let committee = simple_map::borrow_mut(&mut committee_store.committee_map, &id); let node_info = NodeInfo { ip_public_address: copy ip_public_address, @@ -1561,7 +1660,6 @@ Upsert the node to the committee network_port: network_port, rpc_port: rpc_port, }; - let event_handler = borrow_global_mut<SupraCommitteeEventHandler>(get_committeeInfo_address(owner_signer)); if (!does_node_exist(committee, node_address)) { emit_event( &mut event_handler.add_committee_member, @@ -1619,31 +1717,31 @@ Upsert nodes to the committee // Assert the length of the vector for two are the same assert!( vector::length(&ids) == vector::length(&node_addresses), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( vector::length(&ids) == vector::length(&ip_public_address), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( vector::length(&ids) == vector::length(&node_public_key), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( vector::length(&ids) == vector::length(&network_public_key), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( vector::length(&ids) == vector::length(&cg_public_key), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( vector::length(&ids) == vector::length(&network_port), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( vector::length(&ids) == vector::length(&rpc_port), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); while (vector::length(&ids) != 0) { let id = vector::pop_back(&mut ids); @@ -1702,6 +1800,7 @@ Remove the node from the committee let committee_store = borrow_global_mut<CommitteeInfoStore>(com_store_addr); let committee = simple_map::borrow_mut(&mut committee_store.committee_map, &id); ensure_node_address_exist(committee, node_address); + assert_removal_allowed(committee); let (_, node_info) = simple_map::remove(&mut committee.map, &node_address); let event_handler = borrow_global_mut<SupraCommitteeEventHandler>(get_committeeInfo_address(owner_signer)); emit_event( diff --git a/aptos-move/framework/supra-framework/doc/dkg.md b/aptos-move/framework/supra-framework/doc/dkg.md index 6ae6728a12c..3138cd16fb8 100644 --- a/aptos-move/framework/supra-framework/doc/dkg.md +++ b/aptos-move/framework/supra-framework/doc/dkg.md @@ -3,6 +3,9 @@ # Module `0x1::dkg` +Deprecated. Replaced by supra_dkg. Retained because the module has already been deployed to +production. + DKG on-chain states and helper functions. @@ -196,20 +199,20 @@ The completed and in-progress DKG sessions. ## Constants - + -
const EDKG_IN_PROGRESS: u64 = 1;
+
const EDKG_NOT_IN_PROGRESS: u64 = 2;
 
- + -
const EDKG_NOT_IN_PROGRESS: u64 = 2;
+
const EDKG_IN_PROGRESS: u64 = 1;
 
@@ -237,7 +240,7 @@ Called in genesis to initialize on-chain states. supra_framework, DKGState { last_completed: std::option::none(), - in_progress: std::option::none(), + in_progress: std::option::none() } ); } @@ -269,26 +272,25 @@ Abort if a DKG is already in progress. dealer_epoch: u64, randomness_config: RandomnessConfig, dealer_validator_set: vector<ValidatorConsensusInfo>, - target_validator_set: vector<ValidatorConsensusInfo>, + target_validator_set: vector<ValidatorConsensusInfo> ) acquires DKGState { let dkg_state = borrow_global_mut<DKGState>(@supra_framework); let new_session_metadata = DKGSessionMetadata { dealer_epoch, randomness_config, dealer_validator_set, - target_validator_set, + target_validator_set }; let start_time_us = timestamp::now_microseconds(); - dkg_state.in_progress = std::option::some(DKGSessionState { - metadata: new_session_metadata, - start_time_us, - transcript: vector[], - }); - - emit(DKGStartEvent { - start_time_us, - session_metadata: new_session_metadata, - }); + dkg_state.in_progress = std::option::some( + DKGSessionState { + metadata: new_session_metadata, + start_time_us, + transcript: vector[] + } + ); + + emit(DKGStartEvent { start_time_us, session_metadata: new_session_metadata }); }
@@ -316,7 +318,10 @@ Abort if DKG is not in progress.
public(friend) fun finish(transcript: vector<u8>) acquires DKGState {
     let dkg_state = borrow_global_mut<DKGState>(@supra_framework);
-    assert!(option::is_some(&dkg_state.in_progress), error::invalid_state(EDKG_NOT_IN_PROGRESS));
+    assert!(
+        option::is_some(&dkg_state.in_progress),
+        error::invalid_state(EDKG_NOT_IN_PROGRESS)
+    );
     let session = option::extract(&mut dkg_state.in_progress);
     session.transcript = transcript;
     dkg_state.last_completed = option::some(session);
@@ -417,7 +422,21 @@ Return the dealer epoch of a DKGS
 
 
 
-
invariant [suspendable] chain_status::is_operating() ==> exists<DKGState>(@supra_framework);
+
invariant [suspendable] chain_status::is_operating() ==>
+    exists<DKGState>(@supra_framework);
+
+ + + + + + + +
fun has_incomplete_session(): bool {
+   if (exists<DKGState>(@supra_framework)) {
+       option::spec_is_some(global<DKGState>(@supra_framework).in_progress)
+   } else { false }
+}
 
@@ -474,21 +493,6 @@ Return the dealer epoch of a DKGS - - - - -
fun has_incomplete_session(): bool {
-   if (exists<DKGState>(@supra_framework)) {
-       option::spec_is_some(global<DKGState>(@supra_framework).in_progress)
-   } else {
-       false
-   }
-}
-
- - - ### Function `try_clear_incomplete_session` diff --git a/aptos-move/framework/supra-framework/doc/dkg_committee.md b/aptos-move/framework/supra-framework/doc/dkg_committee.md new file mode 100644 index 00000000000..ef0093c6bfe --- /dev/null +++ b/aptos-move/framework/supra-framework/doc/dkg_committee.md @@ -0,0 +1,499 @@ + + + +# Module `0x1::dkg_committee` + + + +- [Struct `DkgNodeConfig`](#0x1_dkg_committee_DkgNodeConfig) +- [Struct `DkgCommittee`](#0x1_dkg_committee_DkgCommittee) +- [Struct `ReceiverCommittee`](#0x1_dkg_committee_ReceiverCommittee) +- [Struct `DkgCommitteeOutput`](#0x1_dkg_committee_DkgCommitteeOutput) +- [Constants](#@Constants_0) +- [Function `new_dkg_node_config`](#0x1_dkg_committee_new_dkg_node_config) +- [Function `get_addr`](#0x1_dkg_committee_get_addr) +- [Function `get_dkg_pubkey`](#0x1_dkg_committee_get_dkg_pubkey) +- [Function `len`](#0x1_dkg_committee_len) +- [Function `get_committee`](#0x1_dkg_committee_get_committee) +- [Function `new_dkg_committee`](#0x1_dkg_committee_new_dkg_committee) +- [Function `new_dkg_committee_from_validator_consensus_info`](#0x1_dkg_committee_new_dkg_committee_from_validator_consensus_info) +- [Function `new_receiver_committee`](#0x1_dkg_committee_new_receiver_committee) +- [Function `new_dkg_committee_output`](#0x1_dkg_committee_new_dkg_committee_output) +- [Function `get_dkg_committee_output_threshold_type`](#0x1_dkg_committee_get_dkg_committee_output_threshold_type) +- [Function `get_dkg_committee_output_keys`](#0x1_dkg_committee_get_dkg_committee_output_keys) + + +
use 0x1::bcs;
+use 0x1::validator_consensus_info;
+use 0x1::validator_public_keys;
+use 0x1::vector;
+
+ + + + + +## Struct `DkgNodeConfig` + + + +
struct DkgNodeConfig has copy, drop, store
+
+ + + +
+Fields + + +
+
+addr: address +
+
+ +
+
+identity: vector<u8> +
+
+ +
+
+dkg_pubkey: vector<u8> +
+
+ +
+
+ + +
+ + + +## Struct `DkgCommittee` + + + +
struct DkgCommittee has copy, drop, store
+
+ + + +
+Fields + + +
+
+committee: vector<dkg_committee::DkgNodeConfig> +
+
+ +
+
+threshold_type: validator_public_keys::CertificateThresholdType +
+
+ +
+
+ + +
+ + + +## Struct `ReceiverCommittee` + + + +
struct ReceiverCommittee has copy, drop, store
+
+ + + +
+Fields + + +
+
+is_resharing: bool +
+
+ +
+
+dkg_threshold_type: validator_public_keys::CertificateThresholdType +
+
+ +
+
+committee: dkg_committee::DkgCommittee +
+
+ +
+
+ + +
+ + + +## Struct `DkgCommitteeOutput` + +Input for DKG key output - contains threshold type and keys for one committee + + +
struct DkgCommitteeOutput has copy, drop
+
+ + + +
+Fields + + +
+
+threshold_type: u8 +
+
+ The threshold type (0=validity, 1=quorum, 2=unanimous, etc.) +
+
+keys: vector<vector<u8>> +
+
+ Public key shares for each validator (indexed by validator position) +
+
+ + +
+ + + +## Constants + + + + + + +
const EINVALID_DKG_COMMITTEE_SIZE: u64 = 1;
+
+ + + + + +## Function `new_dkg_node_config` + + + +
public fun new_dkg_node_config(addr: address, identity: vector<u8>, dkg_pubkey: vector<u8>): dkg_committee::DkgNodeConfig
+
+ + + +
+Implementation + + +
public fun new_dkg_node_config(
+    addr: address, identity: vector<u8>, dkg_pubkey: vector<u8>
+): DkgNodeConfig {
+    DkgNodeConfig { addr, identity, dkg_pubkey }
+}
+
+ + + +
+ + + +## Function `get_addr` + + + +
public fun get_addr(dkg_node: &dkg_committee::DkgNodeConfig): address
+
+ + + +
+Implementation + + +
public fun get_addr(dkg_node: &DkgNodeConfig): address {
+    dkg_node.addr
+}
+
+ + + +
+ + + +## Function `get_dkg_pubkey` + + + +
public fun get_dkg_pubkey(dkg_node: &dkg_committee::DkgNodeConfig): vector<u8>
+
+ + + +
+Implementation + + +
public fun get_dkg_pubkey(dkg_node: &DkgNodeConfig): vector<u8> {
+    dkg_node.dkg_pubkey
+}
+
+ + + +
+ + + +## Function `len` + + + +
public fun len(committee: &dkg_committee::DkgCommittee): u64
+
+ + + +
+Implementation + + +
public fun len(committee: &DkgCommittee): u64 {
+    vector::length(&committee.committee)
+}
+
+ + + +
+ + + +## Function `get_committee` + + + +
public fun get_committee(dkg_committee: &dkg_committee::DkgCommittee): vector<dkg_committee::DkgNodeConfig>
+
+ + + +
+Implementation + + +
public fun get_committee(dkg_committee: &DkgCommittee): vector<DkgNodeConfig> {
+    dkg_committee.committee
+}
+
+ + + +
+ + + +## Function `new_dkg_committee` + + + +
public fun new_dkg_committee(committee: vector<dkg_committee::DkgNodeConfig>, threshold_type: validator_public_keys::CertificateThresholdType): dkg_committee::DkgCommittee
+
+ + + +
+Implementation + + +
public fun new_dkg_committee(
+    committee: vector<DkgNodeConfig>, threshold_type: CertificateThresholdType
+): DkgCommittee {
+    assert!(vector::length(&committee) > 0, EINVALID_DKG_COMMITTEE_SIZE);
+    DkgCommittee { committee, threshold_type }
+}
+
+ + + +
+ + + +## Function `new_dkg_committee_from_validator_consensus_info` + + + +
public fun new_dkg_committee_from_validator_consensus_info(validator_committee: vector<validator_consensus_info::ValidatorConsensusInfo>, threshold_type: validator_public_keys::CertificateThresholdType): dkg_committee::DkgCommittee
+
+ + + +
+Implementation + + +
public fun new_dkg_committee_from_validator_consensus_info(
+    validator_committee: vector<ValidatorConsensusInfo>,
+    threshold_type: CertificateThresholdType
+): DkgCommittee {
+    assert!(vector::length(&validator_committee) > 0, EINVALID_DKG_COMMITTEE_SIZE);
+
+    // The order of the committee members is important for DKG.
+    // The order should correspond to the order of the validator committee.
+    // The output of the DKG has keys in the same order as the committee.
+    let dkg_committee = vector[];
+    vector::for_each(
+        validator_committee,
+        |x| {
+            let validator_keys_bytes = validator_consensus_info::get_pk_bytes(&x);
+            let addr = validator_consensus_info::get_addr(&x);
+            vector::push_back(
+                &mut dkg_committee,
+                DkgNodeConfig {
+                    addr,
+                    identity: bcs::to_bytes(&addr),
+                    dkg_pubkey: validator_keys_bytes
+                }
+            );
+        }
+    );
+
+    DkgCommittee { committee: dkg_committee, threshold_type }
+}
+
+ + + +
+ + + +## Function `new_receiver_committee` + + + +
public fun new_receiver_committee(is_resharing: bool, dkg_threshold_type: validator_public_keys::CertificateThresholdType, committee: dkg_committee::DkgCommittee): dkg_committee::ReceiverCommittee
+
+ + + +
+Implementation + + +
public fun new_receiver_committee(
+    is_resharing: bool,
+    dkg_threshold_type: CertificateThresholdType,
+    committee: DkgCommittee
+): ReceiverCommittee {
+    ReceiverCommittee { is_resharing, dkg_threshold_type, committee }
+}
+
+ + + +
+ + + +## Function `new_dkg_committee_output` + +Create a new DkgCommitteeOutput + + +
public fun new_dkg_committee_output(threshold_type: u8, keys: vector<vector<u8>>): dkg_committee::DkgCommitteeOutput
+
+ + + +
+Implementation + + +
public fun new_dkg_committee_output(
+    threshold_type: u8, keys: vector<vector<u8>>
+): DkgCommitteeOutput {
+    DkgCommitteeOutput { threshold_type, keys }
+}
+
+ + + +
+ + + +## Function `get_dkg_committee_output_threshold_type` + +Get threshold type from DkgCommitteeOutput + + +
public fun get_dkg_committee_output_threshold_type(output: &dkg_committee::DkgCommitteeOutput): u8
+
+ + + +
+Implementation + + +
public fun get_dkg_committee_output_threshold_type(
+    output: &DkgCommitteeOutput
+): u8 {
+    output.threshold_type
+}
+
+ + + +
+ + + +## Function `get_dkg_committee_output_keys` + +Get keys from DkgCommitteeOutput + + +
public fun get_dkg_committee_output_keys(output: &dkg_committee::DkgCommitteeOutput): vector<vector<u8>>
+
+ + + +
+Implementation + + +
public fun get_dkg_committee_output_keys(output: &DkgCommitteeOutput): vector<vector<u8>> {
+    output.keys
+}
+
+ + + +
+ + +[move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/supra-framework/doc/dkg_config.md b/aptos-move/framework/supra-framework/doc/dkg_config.md new file mode 100644 index 00000000000..3fea15a4d6b --- /dev/null +++ b/aptos-move/framework/supra-framework/doc/dkg_config.md @@ -0,0 +1,574 @@ + + + +# Module `0x1::dkg_config` + +DKG configuration module for configurable DKG parameters. +This config can be updated via governance and takes effect at the next epoch. + + +- [Struct `ReceiverCommitteeConfig`](#0x1_dkg_config_ReceiverCommitteeConfig) +- [Resource `DkgConfig`](#0x1_dkg_config_DkgConfig) +- [Constants](#@Constants_0) +- [Function `initialize`](#0x1_dkg_config_initialize) +- [Function `set_for_next_epoch`](#0x1_dkg_config_set_for_next_epoch) +- [Function `has_key_threshold_type`](#0x1_dkg_config_has_key_threshold_type) +- [Function `on_new_epoch`](#0x1_dkg_config_on_new_epoch) +- [Function `new`](#0x1_dkg_config_new) +- [Function `new_receiver_committee_config`](#0x1_dkg_config_new_receiver_committee_config) +- [Function `default`](#0x1_dkg_config_default) +- [Function `current`](#0x1_dkg_config_current) +- [Function `get_dealer_committee_threshold_type`](#0x1_dkg_config_get_dealer_committee_threshold_type) +- [Function `get_receiver_committee_configs`](#0x1_dkg_config_get_receiver_committee_configs) +- [Function `get_is_resharing`](#0x1_dkg_config_get_is_resharing) +- [Function `get_committee_threshold_type`](#0x1_dkg_config_get_committee_threshold_type) +- [Function `get_dkg_threshold_type`](#0x1_dkg_config_get_dkg_threshold_type) + + +
use 0x1::config_buffer;
+use 0x1::error;
+use 0x1::system_addresses;
+use 0x1::validator_public_keys;
+
+ + + + + +## Struct `ReceiverCommitteeConfig` + +Configuration for a single receiver committee in DKG. + + +
struct ReceiverCommitteeConfig has copy, drop, store
+
+ + + +
+Fields + + +
+
+is_resharing: bool +
+
+ Whether this committee uses resharing from the previous epoch's public key. +
+
+committee_threshold_type: validator_public_keys::CertificateThresholdType +
+
+ The threshold type for this committee (e.g., quorum, clan_majority). +
+
+dkg_threshold_type: validator_public_keys::CertificateThresholdType +
+
+ The threshold type for output keys in DKG for this committee (e.g., validity, quorum). +
+
+ + +
+ + + +## Resource `DkgConfig` + +Main DKG configuration stored at @supra_framework. +Controls DKG parameters that can be updated via governance. + + +
struct DkgConfig has copy, drop, store, key
+
+ + + +
+Fields + + +
+
+dealer_committee_threshold_type: validator_public_keys::CertificateThresholdType +
+
+ Threshold type for the dealer committee. (e.g., quorum, clan_majority). +
+
+receiver_committees: vector<dkg_config::ReceiverCommitteeConfig> +
+
+ Configuration for each receiver committee. + Default: [(false, validity), (false, quorum)] +
+
+ + +
+ + + +## Constants + + + + +Error: Receiver committees vector cannot be empty. + + +
const EEMPTY_RECEIVER_COMMITTEES: u64 = 1;
+
+ + + + + +Error: Cannot enable resharing for a threshold type that doesn't exist in current config. + + +
const ERESHARING_FOR_NONEXISTENT_THRESHOLD_TYPE: u64 = 2;
+
+ + + + + +## Function `initialize` + +Initialize DKG config during genesis. + + +
public(friend) fun initialize(framework: &signer)
+
+ + + +
+Implementation + + +
public(friend) fun initialize(framework: &signer) {
+    system_addresses::assert_supra_framework(framework);
+    if (!exists<DkgConfig>(@supra_framework)) {
+        move_to(framework, default());
+    }
+}
+
+ + + +
+ + + +## Function `set_for_next_epoch` + +Set a new DKG config for the next epoch. +This can only be called by on-chain governance. +Example usage: +``` +let new_config = dkg_config::new( +quorum_certificate_type(), +vector[ +dkg_config::new_receiver_committee_config(true, validity_certificate_type()), +dkg_config::new_receiver_committee_config(true, quorum_certificate_type()), +] +); +dkg_config::set_for_next_epoch(&framework_signer, new_config); +supra_governance::reconfigure(&framework_signer); +``` + + +
public fun set_for_next_epoch(framework: &signer, new_config: dkg_config::DkgConfig)
+
+ + + +
+Implementation + + +
public fun set_for_next_epoch(
+    framework: &signer, new_config: DkgConfig
+) acquires DkgConfig {
+    system_addresses::assert_supra_framework(framework);
+
+    // Validate: receiver_committees cannot be empty
+    assert!(
+        vector::length(&new_config.receiver_committees) > 0,
+        error::invalid_argument(EEMPTY_RECEIVER_COMMITTEES)
+    );
+
+    // Validate: if resharing is enabled for a dkg threshold type, it must exist in current config
+    let current_config = current();
+    let i = 0;
+    let len = vector::length(&new_config.receiver_committees);
+    while (i < len) {
+        let new_rc = vector::borrow(&new_config.receiver_committees, i);
+        if (new_rc.is_resharing) {
+            // Check if this threshold type exists in current config
+            assert!(
+                has_key_threshold_type(¤t_config, new_rc.dkg_threshold_type),
+                error::invalid_argument(ERESHARING_FOR_NONEXISTENT_THRESHOLD_TYPE)
+            );
+        };
+        i = i + 1;
+    };
+
+    config_buffer::upsert(new_config);
+}
+
+ + + +
+ + + +## Function `has_key_threshold_type` + +Check if a threshold type exists in the config's receiver committees. + + +
fun has_key_threshold_type(config: &dkg_config::DkgConfig, threshold_type: validator_public_keys::CertificateThresholdType): bool
+
+ + + +
+Implementation + + +
fun has_key_threshold_type(
+    config: &DkgConfig, threshold_type: CertificateThresholdType
+): bool {
+    let i = 0;
+    let len = vector::length(&config.receiver_committees);
+    while (i < len) {
+        let rc = vector::borrow(&config.receiver_committees, i);
+        if (rc.dkg_threshold_type == threshold_type) {
+            return true
+        };
+        i = i + 1;
+    };
+    false
+}
+
+ + + +
+ + + +## Function `on_new_epoch` + +Apply any pending DKG config at epoch boundary. +Called from reconfiguration_with_dkg::finish(). + + +
public(friend) fun on_new_epoch(framework: &signer)
+
+ + + +
+Implementation + + +
public(friend) fun on_new_epoch(framework: &signer) acquires DkgConfig {
+    system_addresses::assert_supra_framework(framework);
+    if (config_buffer::does_exist<DkgConfig>()) {
+        let new_config = config_buffer::extract_v2<DkgConfig>();
+        if (exists<DkgConfig>(@supra_framework)) {
+            *borrow_global_mut<DkgConfig>(@supra_framework) = new_config;
+        } else {
+            move_to(framework, new_config);
+        }
+    }
+}
+
+ + + +
+ + + +## Function `new` + +Create a new DkgConfig. + + +
public fun new(dealer_committee_threshold_type: validator_public_keys::CertificateThresholdType, receiver_committees: vector<dkg_config::ReceiverCommitteeConfig>): dkg_config::DkgConfig
+
+ + + +
+Implementation + + +
public fun new(
+    dealer_committee_threshold_type: CertificateThresholdType,
+    receiver_committees: vector<ReceiverCommitteeConfig>
+): DkgConfig {
+    DkgConfig { dealer_committee_threshold_type, receiver_committees }
+}
+
+ + + +
+ + + +## Function `new_receiver_committee_config` + +Create a new ReceiverCommitteeConfig. + + +
public fun new_receiver_committee_config(is_resharing: bool, committee_threshold_type: validator_public_keys::CertificateThresholdType, dkg_threshold_type: validator_public_keys::CertificateThresholdType): dkg_config::ReceiverCommitteeConfig
+
+ + + +
+Implementation + + +
public fun new_receiver_committee_config(
+    is_resharing: bool,
+    committee_threshold_type: CertificateThresholdType,
+    dkg_threshold_type: CertificateThresholdType
+): ReceiverCommitteeConfig {
+    ReceiverCommitteeConfig {
+        is_resharing,
+        committee_threshold_type,
+        dkg_threshold_type
+    }
+}
+
+ + + +
+ + + +## Function `default` + +Returns the default DKG configuration. + +Assumes that the SUPRA_BCFT_CERTIFICATES feature flag is enabled. + + +
public fun default(): dkg_config::DkgConfig
+
+ + + +
+Implementation + + +
public fun default(): DkgConfig {
+    DkgConfig {
+        dealer_committee_threshold_type: quorum_certificate_type(),
+        receiver_committees: vector[
+            ReceiverCommitteeConfig {
+                is_resharing: false,
+                committee_threshold_type: quorum_certificate_type(),
+                dkg_threshold_type: bcft_quorum_certificate_type()
+            },
+            ReceiverCommitteeConfig {
+                is_resharing: false,
+                committee_threshold_type: quorum_certificate_type(),
+                dkg_threshold_type: bcft_validity_certificate_type()
+            },
+            ReceiverCommitteeConfig {
+                is_resharing: false,
+                committee_threshold_type: quorum_certificate_type(),
+                dkg_threshold_type: clan_majority_certificate_type()
+            }
+        ]
+    }
+}
+
+ + + +
+ + + +## Function `current` + +Get the current DKG config. + + +
public fun current(): dkg_config::DkgConfig
+
+ + + +
+Implementation + + +
public fun current(): DkgConfig acquires DkgConfig {
+    if (exists<DkgConfig>(@supra_framework)) {
+        *borrow_global<DkgConfig>(@supra_framework)
+    } else {
+        // This branch should not be executed:
+        //     1. If the network is started from genesis then the default config should be
+        //        applied during genesis.
+        //     2. If the DKG feature flag is enabled in an existing network, then governance
+        //        should set a config before enabling the feature flag.
+        //
+        // This branch exists as a fallback that ensures that the `BlockMetadata` transaction
+        // does not fail in case of misconfiguration.
+        default()
+    }
+}
+
+ + + +
+ + + +## Function `get_dealer_committee_threshold_type` + +Get the dealer threshold type from the config. + + +
public fun get_dealer_committee_threshold_type(config: &dkg_config::DkgConfig): validator_public_keys::CertificateThresholdType
+
+ + + +
+Implementation + + +
public fun get_dealer_committee_threshold_type(config: &DkgConfig):
+    CertificateThresholdType {
+    config.dealer_committee_threshold_type
+}
+
+ + + +
+ + + +## Function `get_receiver_committee_configs` + +Get the receiver committee configs from the DkgConfig. + + +
public fun get_receiver_committee_configs(config: &dkg_config::DkgConfig): vector<dkg_config::ReceiverCommitteeConfig>
+
+ + + +
+Implementation + + +
public fun get_receiver_committee_configs(config: &DkgConfig):
+    vector<ReceiverCommitteeConfig> {
+    config.receiver_committees
+}
+
+ + + +
+ + + +## Function `get_is_resharing` + +Get is_resharing from a ReceiverCommitteeConfig. + + +
public fun get_is_resharing(config: &dkg_config::ReceiverCommitteeConfig): bool
+
+ + + +
+Implementation + + +
public fun get_is_resharing(config: &ReceiverCommitteeConfig): bool {
+    config.is_resharing
+}
+
+ + + +
+ + + +## Function `get_committee_threshold_type` + +Get committee_threshold_type from a ReceiverCommitteeConfig. + + +
public fun get_committee_threshold_type(config: &dkg_config::ReceiverCommitteeConfig): validator_public_keys::CertificateThresholdType
+
+ + + +
+Implementation + + +
public fun get_committee_threshold_type(
+    config: &ReceiverCommitteeConfig
+): CertificateThresholdType {
+    config.committee_threshold_type
+}
+
+ + + +
+ + + +## Function `get_dkg_threshold_type` + +Get dkg_threshold_type from a ReceiverCommitteeConfig. + + +
public fun get_dkg_threshold_type(config: &dkg_config::ReceiverCommitteeConfig): validator_public_keys::CertificateThresholdType
+
+ + + +
+Implementation + + +
public fun get_dkg_threshold_type(config: &ReceiverCommitteeConfig):
+    CertificateThresholdType {
+    config.dkg_threshold_type
+}
+
+ + + +
+ + +[move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/supra-framework/doc/evm_config.md b/aptos-move/framework/supra-framework/doc/evm_config.md index 6a60a5adffc..9644b3bb39b 100644 --- a/aptos-move/framework/supra-framework/doc/evm_config.md +++ b/aptos-move/framework/supra-framework/doc/evm_config.md @@ -5,32 +5,41 @@ -- [Resource `EvmConfig`](#0x1_evm_config_EvmConfig) +- [Resource `EvmContractsDetails`](#0x1_evm_config_EvmContractsDetails) +- [Resource `EvmScalarConfig`](#0x1_evm_config_EvmScalarConfig) - [Constants](#@Constants_0) - [Function `initialize`](#0x1_evm_config_initialize) -- [Function `set_for_next_epoch`](#0x1_evm_config_set_for_next_epoch) +- [Function `upsert_evm_contract_details_for_next_epoch`](#0x1_evm_config_upsert_evm_contract_details_for_next_epoch) +- [Function `upsert_config_for_next_epoch`](#0x1_evm_config_upsert_config_for_next_epoch) +- [Function `get_contract_value`](#0x1_evm_config_get_contract_value) +- [Function `get_scalar_config_value`](#0x1_evm_config_get_scalar_config_value) +- [Function `validate_scalar_config`](#0x1_evm_config_validate_scalar_config) +- [Function `is_valid_evm_address`](#0x1_evm_config_is_valid_evm_address) - [Function `on_new_epoch`](#0x1_evm_config_on_new_epoch) -- [Specification](#@Specification_1) - - [Function `set_for_next_epoch`](#@Specification_1_set_for_next_epoch) - - [Function `on_new_epoch`](#@Specification_1_on_new_epoch) -
use 0x1::config_buffer;
+
use 0x1::bcs;
+use 0x1::config_buffer;
 use 0x1::error;
+use 0x1::event;
+use 0x1::option;
+use 0x1::signer;
+use 0x1::simple_map;
+use 0x1::string;
 use 0x1::system_addresses;
 use 0x1::vector;
 
- + -## Resource `EvmConfig` +## Resource `EvmContractsDetails` -The struct stores the on-chain EVM configuration. -
struct EvmConfig has drop, store, key
+
#[event]
+struct EvmContractsDetails has copy, drop, store, key
 
@@ -41,7 +50,35 @@ The struct stores the on-chain EVM configuration.
-config: vector<u8> +details: simple_map::SimpleMap<string::String, address> +
+
+ +
+
+ + + + + + +## Resource `EvmScalarConfig` + + + +
#[event]
+struct EvmScalarConfig has copy, drop, store, key
+
+ + + +
+Fields + + +
+
+config: simple_map::SimpleMap<string::String, u128>
@@ -56,12 +93,132 @@ The struct stores the on-chain EVM configuration. ## Constants - + + +Requested key does not exist in the map + + +
const EKEY_NOT_FOUND: u64 = 4;
+
+ + + + + +Supra EVM Gas Estimate Margin + + +
const CONFIG_KEY_EVM_GAS_ESTIMATE_MARGIN: vector<u8> = [101, 118, 109, 95, 103, 97, 115, 95, 101, 115, 116, 105, 109, 97, 116, 101, 95, 109, 97, 114, 103, 105, 110];
+
+ + + + + +Well-known config key for the EVM gas normalisation denominator. +This u64 value is used to scale EVM gas units into Supra gas units. + + +
const CONFIG_KEY_EVM_GAS_NORMALIZATION_DENOM: vector<u8> = [101, 118, 109, 95, 103, 97, 115, 95, 110, 111, 114, 109, 97, 108, 105, 122, 97, 116, 105, 111, 110, 95, 100, 101, 110, 111, 109];
+
+ + + + + +Empty keys/values to update config. + + +
const EEMPTY_DATA: u64 = 1;
+
+ + + + -The provided on chain config bytes are empty or invalid +gas used ratio cannot exceed decimal precision -
const EINVALID_CONFIG: u64 = 1;
+
const EGAS_USED_RATIO_CANNOT_EXCEED_DECIMAL_PRECISION: u64 = 7;
+
+ + + + + +Invalid EVM address, valid EVM address must fit in 20 bytes + + +
const EINVALID_EVM_ADDRESS: u64 = 3;
+
+ + + + + +Input keys and values should have the same amount of data + + +
const EKEYS_VALUES_MISMATCH: u64 = 2;
+
+ + + + + +Required Key is missing or value type is incorrect for a key + + +
const EMISSING_KEY_OR_INCORRECT_VAL_TYPE: u64 = 5;
+
+ + + + + +Resource already exist at address + + +
const ERESOURCE_ALREADY_EXISTS: u64 = 6;
+
+ + + + + +Evm and Move address length + + +
const EVM_ADDRESS_BYTE_LENGTH: u64 = 20;
+
+ + + + + + + +
const MOVE_ADDRESS_BYTE_LENGTH: u64 = 32;
+
+ + + + + +Supra EVM Gas Used Ratio + + +
const SUPRA_EVM_GAS_USED_RATIO: vector<u8> = [101, 118, 109, 95, 103, 97, 115, 95, 117, 115, 101, 100, 95, 114, 97, 116, 105, 111];
+
+ + + + + +DECIMAL_PRECISION + + +
const SUPRA_EVM_GAS_USED_RATIO_DECIMAL_PRECISION: vector<u8> = [101, 118, 109, 95, 103, 97, 115, 95, 117, 115, 101, 100, 95, 114, 97, 116, 105, 111, 95, 100, 101, 99, 105, 109, 97, 108, 95, 112, 114, 101, 99, 105, 115, 105, 111, 110];
 
@@ -70,10 +227,14 @@ The provided on chain config bytes are empty or invalid ## Function `initialize` -Publishes the EvmConfig config. +Publishes both the EVM contract address map and the scalar config map. +contract_keys/contract_values must be the same length and every address +must be a valid 20-byte EVM address (upper 12 bytes of the 32-byte Move +address must be zero). config_keys/config_values must be the same +length and must include all required keys (e.g. evm_gas_normalization_denom). -
public(friend) fun initialize(supra_framework: &signer, config: vector<u8>)
+
public(friend) fun initialize(supra_framework: &signer, contract_keys: vector<string::String>, contract_values: vector<address>, config_keys: vector<string::String>, config_values: vector<u128>)
 
@@ -82,10 +243,45 @@ Publishes the EvmConfig config. Implementation -
public(friend) fun initialize(supra_framework: &signer, config: vector<u8>) {
+
public(friend) fun initialize(
+    supra_framework: &signer,
+    contract_keys: vector<String>,
+    contract_values: vector<address>,
+    config_keys: vector<String>,
+    config_values: vector<u128>
+) {
     system_addresses::assert_supra_framework(supra_framework);
-    assert!(!vector::is_empty(&config), error::invalid_argument(EINVALID_CONFIG));
-    move_to(supra_framework, EvmConfig { config });
+    assert!(!vector::is_empty(&contract_keys), error::invalid_argument(EEMPTY_DATA));
+    assert!(!vector::is_empty(&config_keys), error::invalid_argument(EEMPTY_DATA));
+    let supra_framework_addr = signer::address_of(supra_framework);
+    assert!(!exists<EvmContractsDetails>(supra_framework_addr),error::invalid_state(ERESOURCE_ALREADY_EXISTS));
+    assert!(!exists<EvmScalarConfig>(supra_framework_addr),error::invalid_state(ERESOURCE_ALREADY_EXISTS));
+    assert!(
+        vector::length(&contract_keys) == vector::length(&contract_values),
+        error::invalid_argument(EKEYS_VALUES_MISMATCH)
+    );
+    assert!(
+        vector::length(&config_keys) == vector::length(&config_values),
+        error::invalid_argument(EKEYS_VALUES_MISMATCH)
+    );
+
+    // Check that no contract value is invalid EVM address
+    let all_valid_evm_address = vector::all(&contract_values,
+    |v|{ is_valid_evm_address(v) });
+    assert!(all_valid_evm_address, error::invalid_argument(EINVALID_EVM_ADDRESS));
+
+    let contract_details = EvmContractsDetails {
+        details: simple_map::new_from(contract_keys, contract_values)
+    };
+    move_to(supra_framework, contract_details);
+    event::emit(contract_details);
+
+    let evm_config = EvmScalarConfig {
+        config: simple_map::new_from(config_keys, config_values)
+    };
+    validate_scalar_config(&evm_config);
+    move_to(supra_framework, evm_config);
+    event::emit(evm_config);
 }
 
@@ -93,19 +289,21 @@ Publishes the EvmConfig config.
- + -## Function `set_for_next_epoch` +## Function `upsert_evm_contract_details_for_next_epoch` -This can be called by on-chain governance to update on-chain evm configs for the next epoch. +This can be called by on-chain governance to update on-chain evm contract +details for the next epoch. Example usage: ``` -supra_framework::evm_config::set_for_next_epoch(&framework_signer, some_config_bytes); +supra_framework::evm_config::upsert_evm_contract_details_for_next_epoch( +&framework_signer, vector["contract1_name"], vector[contract1_address]); supra_framework::supra_governance::reconfigure(&framework_signer); ``` -
public fun set_for_next_epoch(account: &signer, config: vector<u8>)
+
public fun upsert_evm_contract_details_for_next_epoch(account: &signer, keys: vector<string::String>, values: vector<address>)
 
@@ -114,10 +312,30 @@ supra_framework::supra_governance::reconfigure(&framework_signer); Implementation -
public fun set_for_next_epoch(account: &signer, config: vector<u8>) {
+
public fun upsert_evm_contract_details_for_next_epoch(
+    account: &signer,
+    keys: vector<String>,
+    values: vector<address>
+) acquires EvmContractsDetails {
     system_addresses::assert_supra_framework(account);
-    assert!(!vector::is_empty(&config), error::invalid_argument(EINVALID_CONFIG));
-    std::config_buffer::upsert<EvmConfig>(EvmConfig {config});
+    assert!(!vector::is_empty(&keys), error::invalid_argument(EEMPTY_DATA));
+    assert!(
+        vector::length(&keys) == vector::length(&values),
+        error::invalid_argument(EKEYS_VALUES_MISMATCH)
+    );
+    let all_valid_evm_address = vector::all(&values, |v| { is_valid_evm_address(v) });
+    assert!(all_valid_evm_address, error::invalid_argument(EINVALID_EVM_ADDRESS));
+    if (!exists<EvmContractsDetails>(@supra_framework)) {
+        std::config_buffer::upsert<EvmContractsDetails>(
+            EvmContractsDetails { details: simple_map::new_from(keys, values) }
+        );
+        return
+    };
+    let updated_config = *borrow_global<EvmContractsDetails>(@supra_framework);
+    vector::zip(keys, values, |key, value| {
+        simple_map::upsert(&mut updated_config.details, key, value);
+    });
+    std::config_buffer::upsert<EvmContractsDetails>(updated_config);
 }
 
@@ -125,16 +343,21 @@ supra_framework::supra_governance::reconfigure(&framework_signer); - + -## Function `on_new_epoch` +## Function `upsert_config_for_next_epoch` -Only used in reconfigurations to apply the pending EvmConfig in buffer, if there is any. -If supra_framework has a EvmConfig, then update the new config to supra_framework. -Otherwise, move the new config to supra_framework. +This can be called by on-chain governance to update on-chain evm config +for the next epoch. Values are plain u128 scalars. +Example usage: +``` +supra_framework::evm_config::upsert_config_for_next_epoch( +&framework_signer, vector["config_key"], vector[new_value]); +supra_framework::supra_governance::reconfigure(&framework_signer); +``` -
public(friend) fun on_new_epoch(framework: &signer)
+
public fun upsert_config_for_next_epoch(account: &signer, keys: vector<string::String>, values: vector<u128>)
 
@@ -143,16 +366,35 @@ Otherwise, move the new config to supra_framework. Implementation -
public(friend) fun on_new_epoch(framework: &signer) acquires EvmConfig {
-    system_addresses::assert_supra_framework(framework);
-    if (config_buffer::does_exist<EvmConfig>()) {
-        let new_config = config_buffer::extract<EvmConfig>();
-        if (exists<EvmConfig>(@supra_framework)) {
-            *borrow_global_mut<EvmConfig>(@supra_framework) = new_config;
-        } else {
-            move_to(framework, new_config);
-        };
-    }
+
public fun upsert_config_for_next_epoch(
+    account: &signer,
+    keys: vector<String>,
+    values: vector<u128>
+) acquires EvmScalarConfig {
+    system_addresses::assert_supra_framework(account);
+    assert!(!vector::is_empty(&keys), error::invalid_argument(EEMPTY_DATA));
+    assert!(
+        vector::length(&keys) == vector::length(&values),
+        error::invalid_argument(EKEYS_VALUES_MISMATCH)
+    );
+    if (!exists<EvmScalarConfig>(@supra_framework)) {
+        let evm_config =
+            EvmScalarConfig { config: simple_map::new_from(keys, values) };
+        // Config did not exist earlier, so validate the config for
+        // presence of required keys and value type match
+        validate_scalar_config(&evm_config);
+        std::config_buffer::upsert<EvmScalarConfig>(evm_config);
+        return;
+    };
+    // Copy existing config
+    let updated_config = *borrow_global<EvmScalarConfig>(@supra_framework);
+    // We are never removing existing keys so by induction if all required
+    // keys are present in config during initialization
+    // they will be there later as well, so no need to validate here
+    vector::zip(keys, values, |key, value| {
+        simple_map::upsert(&mut updated_config.config, key, value);
+    });
+    std::config_buffer::upsert<EvmScalarConfig>(updated_config);
 }
 
@@ -160,37 +402,169 @@ Otherwise, move the new config to supra_framework. - + -## Specification +## Function `get_contract_value` +Returns the contract address stored under key in the EvmContractsDetails map. +Aborts with EKEY_NOT_FOUND if the resource has not been initialised or the key +is not present in the map. -
pragma verify = true;
-pragma aborts_if_is_strict;
+
#[view]
+public fun get_contract_value(key: string::String): address
 
- +
+Implementation -### Function `set_for_next_epoch` +
public fun get_contract_value(key: String): address acquires EvmContractsDetails {
+    assert!(exists<EvmContractsDetails>(@supra_framework), error::not_found(EKEY_NOT_FOUND));
+    let details = borrow_global<EvmContractsDetails>(@supra_framework);
+    assert!(
+        simple_map::contains_key(&details.details, &key),
+        error::not_found(EKEY_NOT_FOUND)
+    );
+    *simple_map::borrow(&details.details, &key)
+}
+
-
public fun set_for_next_epoch(account: &signer, config: vector<u8>)
+
+
+
+ + + +## Function `get_scalar_config_value` + +Returns the u128 value stored under key in the EvmScalarConfig map. +Aborts with EKEY_NOT_FOUND if the resource has not been initialised or the key +is not present in the map. + + +
#[view]
+public fun get_scalar_config_value(key: string::String): u128
 
+
+Implementation + -
include config_buffer::SetForNextEpochAbortsIf;
+
public fun get_scalar_config_value(key: String): u128 acquires EvmScalarConfig {
+    assert!(exists<EvmScalarConfig>(@supra_framework), error::not_found(EKEY_NOT_FOUND));
+    let config = borrow_global<EvmScalarConfig>(@supra_framework);
+    assert!(
+        simple_map::contains_key(&config.config, &key),
+        error::not_found(EKEY_NOT_FOUND)
+    );
+    *simple_map::borrow(&config.config, &key)
+}
 
- +
+ + + +## Function `validate_scalar_config` + + + +
fun validate_scalar_config(evm_config: &evm_config::EvmScalarConfig)
+
+ + -### Function `on_new_epoch` +
+Implementation + + +
fun validate_scalar_config(evm_config: &EvmScalarConfig) {
+    let required_keys = vector[string::utf8(CONFIG_KEY_EVM_GAS_NORMALIZATION_DENOM),
+                               string::utf8(CONFIG_KEY_EVM_GAS_ESTIMATE_MARGIN),
+                               string::utf8(SUPRA_EVM_GAS_USED_RATIO),
+                               string::utf8(SUPRA_EVM_GAS_USED_RATIO_DECIMAL_PRECISION)];
+    // With u128 as the value type, the Move type system prevents type mismatches at
+    // compile time. The only meaningful runtime check is key presence.
+    vector::for_each_reverse(required_keys, |rk| {
+        assert!(simple_map::contains_key(&evm_config.config, &rk),
+            error::invalid_argument(EMISSING_KEY_OR_INCORRECT_VAL_TYPE)
+        );
+        assert!(*simple_map::borrow(&evm_config.config, &rk) > 0u128, error::invalid_argument(EMISSING_KEY_OR_INCORRECT_VAL_TYPE));
+    });
+    let gas_used_ratio = *simple_map::borrow(&evm_config.config, &string::utf8(SUPRA_EVM_GAS_USED_RATIO));
+    let gas_used_ratio_decimal_precision = *simple_map::borrow(&evm_config.config, &string::utf8(SUPRA_EVM_GAS_USED_RATIO_DECIMAL_PRECISION));
+    assert!(gas_used_ratio <= gas_used_ratio_decimal_precision, error::invalid_argument(EGAS_USED_RATIO_CANNOT_EXCEED_DECIMAL_PRECISION));
+}
+
+ + + +
+ + + +## Function `is_valid_evm_address` + + + +
fun is_valid_evm_address(addr: &address): bool
+
+ + + +
+Implementation + + +
fun is_valid_evm_address(addr: &address): bool {
+    // BCS serialises a Move `address` as a raw fixed-size 32-byte array in
+    // big-endian order (most-significant byte first).  An EVM address is only
+    // 20 bytes wide, so when a 20-byte EVM address is stored in a 32-byte Move
+    // address the EVM bytes occupy the last 20 positions (indices 12-31) and the
+    // leading 12 bytes (indices 0-11) must all be zero.
+    // We iterate only over that prefix and bail immediately on the first non-zero
+    // byte to avoid unnecessary work.
+    let evm_addr_bytes = bcs::to_bytes(addr);
+
+    // Sanity check: BCS encoding of an address is always 32 bytes. If somehow
+    // the length differs, the address cannot be valid.
+    if (vector::length(&evm_addr_bytes) != MOVE_ADDRESS_BYTE_LENGTH) {
+        return false
+    };
+
+    // Check that all 12 high-order prefix bytes are zero.  A non-zero byte here
+    // means the value cannot fit in 20 bytes and is therefore not a valid EVM address.
+    let i = 0u64;
+    let addr_length_diff = MOVE_ADDRESS_BYTE_LENGTH - EVM_ADDRESS_BYTE_LENGTH;
+    while (i < addr_length_diff) {
+        if (*vector::borrow(&evm_addr_bytes, i) != 0u8) {
+            // Non-zero prefix byte found - not a valid 20-byte EVM address.
+            return false
+        };
+        i = i + 1;
+    };
+
+    true
+}
+
+ + + +
+ + + +## Function `on_new_epoch` + +Only used in reconfigurations to apply the pending configs in buffer, if any. +If supra_framework already holds the resource, overwrite it; otherwise move it in.
public(friend) fun on_new_epoch(framework: &signer)
@@ -198,11 +572,40 @@ Otherwise, move the new config to supra_framework.
 
 
 
+
+Implementation + -
requires @supra_framework == std::signer::address_of(framework);
-include config_buffer::OnNewEpochRequirement<EvmConfig>;
-aborts_if false;
+
public(friend) fun on_new_epoch(framework: &signer) acquires EvmScalarConfig, EvmContractsDetails {
+    system_addresses::assert_supra_framework(framework);
+    if (config_buffer::does_exist<EvmContractsDetails>()) {
+        //TODO: change to extract_v2 when extract_v2 is merged and available
+        let new_config = config_buffer::extract<EvmContractsDetails>();
+        if (!exists<EvmContractsDetails>(@supra_framework)) {
+            move_to(framework, new_config);
+        } else {
+            let old_config = borrow_global_mut<EvmContractsDetails>(@supra_framework);
+            *old_config = new_config;
+        };
+        event::emit(new_config)
+    };
+    if (config_buffer::does_exist<EvmScalarConfig>()) {
+        // change to extract_v2 when it is available
+        let new_config = config_buffer::extract<EvmScalarConfig>();
+        if (!exists<EvmScalarConfig>(@supra_framework)) {
+            move_to(framework, new_config);
+        } else {
+            let old_config = borrow_global_mut<EvmScalarConfig>(@supra_framework);
+            *old_config = new_config;
+        };
+        event::emit(new_config)
+    };
+}
 
+ +
+ + [move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/supra-framework/doc/fungible_asset.md b/aptos-move/framework/supra-framework/doc/fungible_asset.md index e7afd03aa3d..5342c37e7d5 100644 --- a/aptos-move/framework/supra-framework/doc/fungible_asset.md +++ b/aptos-move/framework/supra-framework/doc/fungible_asset.md @@ -3710,30 +3710,34 @@ Mutate specified fields of the fungible asset's object::object_address(&metadata_ref.metadata); let mutable_metadata = borrow_global_mut<Metadata>(metadata_address); - if (option::is_some(&name)){ - let name = option::extract(&mut name); - assert!(string::length(&name) <= MAX_NAME_LENGTH, error::out_of_range(ENAME_TOO_LONG)); - mutable_metadata.name = name; + if (option::is_some(&name)) { + let new_name = option::destroy_some(name); + assert!(string::length(&new_name) <= MAX_NAME_LENGTH, error::out_of_range(ENAME_TOO_LONG)); + mutable_metadata.name = new_name; }; - if (option::is_some(&symbol)){ - let symbol = option::extract(&mut symbol); - assert!(string::length(&symbol) <= MAX_SYMBOL_LENGTH, error::out_of_range(ESYMBOL_TOO_LONG)); - mutable_metadata.symbol = symbol; + + if (option::is_some(&symbol)) { + let new_symbol = option::destroy_some(symbol); + assert!(string::length(&new_symbol) <= MAX_SYMBOL_LENGTH, error::out_of_range(ESYMBOL_TOO_LONG)); + mutable_metadata.symbol = new_symbol; }; - if (option::is_some(&decimals)){ - let decimals = option::extract(&mut decimals); - assert!(decimals <= MAX_DECIMALS, error::out_of_range(EDECIMALS_TOO_LARGE)); - mutable_metadata.decimals = decimals; + + if (option::is_some(&decimals)) { + let new_decimals = option::destroy_some(decimals); + assert!(new_decimals <= MAX_DECIMALS, error::out_of_range(EDECIMALS_TOO_LARGE)); + mutable_metadata.decimals = new_decimals; }; - if (option::is_some(&icon_uri)){ - let icon_uri = option::extract(&mut icon_uri); - assert!(string::length(&icon_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG)); - mutable_metadata.icon_uri = icon_uri; + + if (option::is_some(&icon_uri)) { + let new_icon_uri = option::destroy_some(icon_uri); + assert!(string::length(&new_icon_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG)); + mutable_metadata.icon_uri = new_icon_uri; }; - if (option::is_some(&project_uri)){ - let project_uri = option::extract(&mut project_uri); - assert!(string::length(&project_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG)); - mutable_metadata.project_uri = project_uri; + + if (option::is_some(&project_uri)) { + let new_project_uri = option::destroy_some(project_uri); + assert!(string::length(&new_project_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG)); + mutable_metadata.project_uri = new_project_uri; }; }
diff --git a/aptos-move/framework/supra-framework/doc/genesis.md b/aptos-move/framework/supra-framework/doc/genesis.md index 19e59287331..a45e4e9503c 100644 --- a/aptos-move/framework/supra-framework/doc/genesis.md +++ b/aptos-move/framework/supra-framework/doc/genesis.md @@ -19,6 +19,8 @@ - [Function `initialize_supra_native_automation_v2`](#0x1_genesis_initialize_supra_native_automation_v2) - [Function `initialize_core_resources_and_supra_coin`](#0x1_genesis_initialize_core_resources_and_supra_coin) - [Function `initialize_evm_genesis_config`](#0x1_genesis_initialize_evm_genesis_config) +- [Function `initialize_evm_config`](#0x1_genesis_initialize_evm_config) +- [Function `initialize_leader_ban_registry_config`](#0x1_genesis_initialize_leader_ban_registry_config) - [Function `create_accounts`](#0x1_genesis_create_accounts) - [Function `create_account`](#0x1_genesis_create_account) - [Function `create_multiple_multisig_accounts_with_schema`](#0x1_genesis_create_multiple_multisig_accounts_with_schema) @@ -58,13 +60,16 @@ use 0x1::coin; use 0x1::consensus_config; use 0x1::create_signer; +use 0x1::dkg_config; use 0x1::error; +use 0x1::evm_config; use 0x1::evm_genesis_config; use 0x1::execution_config; use 0x1::fixed_point32; use 0x1::gas_schedule; +use 0x1::leader_ban_registry; +use 0x1::leader_ban_registry_config; use 0x1::multisig_account; -use 0x1::nonce_validation; use 0x1::option; use 0x1::pbo_delegation_pool; use 0x1::reconfiguration; @@ -579,14 +584,13 @@ Genesis step 1: Initialize supra framework account and core modules on chain. rewards_rate: u64, rewards_rate_denominator: u64, voting_power_increase_limit: u64, - genesis_timestamp_in_microseconds: u64, + genesis_timestamp_in_microseconds: u64 ) { // Initialize the supra framework account. This is the account where system resources and modules will be // deployed to. This will be entirely managed by on-chain governance and no entities have the key or privileges // to use this account. - let (supra_framework_account, supra_framework_signer_cap) = account::create_framework_reserved_account( - @supra_framework - ); + let (supra_framework_account, supra_framework_signer_cap) = + account::create_framework_reserved_account(@supra_framework); // Initialize account configs on supra framework account. account::initialize(&supra_framework_account); @@ -595,21 +599,27 @@ Genesis step 1: Initialize supra framework account and core modules on chain. b"script_prologue", b"module_prologue", b"multi_agent_script_prologue", - b"epilogue", + b"epilogue" ); // Give the decentralized on-chain governance control over the core framework account. - supra_governance::store_signer_cap(&supra_framework_account, @supra_framework, supra_framework_signer_cap); + supra_governance::store_signer_cap( + &supra_framework_account, @supra_framework, supra_framework_signer_cap + ); // put reserved framework reserved accounts under supra governance let framework_reserved_addresses = vector<address>[@0x2, @0x3, @0x4, @0x5, @0x6, @0x7, @0x8, @0x9, @0xa]; while (!vector::is_empty(&framework_reserved_addresses)) { let address = vector::pop_back<address>(&mut framework_reserved_addresses); - let (_, framework_signer_cap) = account::create_framework_reserved_account(address); - supra_governance::store_signer_cap(&supra_framework_account, address, framework_signer_cap); + let (_, framework_signer_cap) = + account::create_framework_reserved_account(address); + supra_governance::store_signer_cap( + &supra_framework_account, address, framework_signer_cap + ); }; consensus_config::initialize(&supra_framework_account, consensus_config); + dkg_config::initialize(&supra_framework_account); execution_config::set(&supra_framework_account, execution_config); supra_config::initialize(&supra_framework_account, supra_config); version::initialize(&supra_framework_account, initial_version); @@ -624,7 +634,7 @@ Genesis step 1: Initialize supra framework account and core modules on chain. allow_validator_set_change, rewards_rate, rewards_rate_denominator, - voting_power_increase_limit, + voting_power_increase_limit ); storage_gas::initialize(&supra_framework_account); gas_schedule::initialize(&supra_framework_account, gas_schedule); @@ -637,7 +647,6 @@ Genesis step 1: Initialize supra framework account and core modules on chain. reconfiguration::initialize(&supra_framework_account); block::initialize(&supra_framework_account, epoch_interval_microsecs); state_storage::initialize(&supra_framework_account); - nonce_validation::initialize(&supra_framework_account) }
@@ -705,9 +714,8 @@ Deprecated in favoor of initialize_supra_native_automation_v2. _congestion_threshold_percentage: u8, _congestion_base_fee_in_quants_per_sec: u64, _congestion_exponent: u8, - _task_capacity: u16, -) { -} + _task_capacity: u16 +) {}
@@ -743,7 +751,7 @@ Genesis step 3: Initialize Supra Native Automation. cycle_duration: u64, sys_task_duration_cap_in_secs: u64, sys_registry_max_gas_cap: u64, - sys_task_capacity: u16, + sys_task_capacity: u16 ) { automation_registry::initialize( supra_framework, @@ -758,7 +766,7 @@ Genesis step 3: Initialize Supra Native Automation. task_capacity, sys_task_duration_cap_in_secs, sys_registry_max_gas_cap, - sys_task_capacity, + sys_task_capacity ) }
@@ -784,8 +792,7 @@ Only called for testnets and e2e tests.
fun initialize_core_resources_and_supra_coin(
-    supra_framework: &signer,
-    core_resources_auth_key: vector<u8>,
+    supra_framework: &signer, core_resources_auth_key: vector<u8>
 ) {
     let (burn_cap, mint_cap) = supra_coin::initialize(supra_framework);
     coin::create_coin_conversion_map(supra_framework);
@@ -799,8 +806,12 @@ Only called for testnets and e2e tests.
 
     let core_resources = account::create_account(@core_resources);
     supra_account::register_supra(&core_resources); // register Supra store
-    account::rotate_authentication_key_internal(&core_resources, core_resources_auth_key);
-    supra_coin::configure_accounts_for_test(supra_framework, &core_resources, mint_cap);
+    account::rotate_authentication_key_internal(
+        &core_resources, core_resources_auth_key
+    );
+    supra_coin::configure_accounts_for_test(
+        supra_framework, &core_resources, mint_cap
+    );
 }
 
@@ -825,8 +836,7 @@ Initialize the EVM genesis config.
fun initialize_evm_genesis_config(
-    supra_framework: &signer,
-    evm_genesis_config: vector<u8>,
+    supra_framework: &signer, evm_genesis_config: vector<u8>
 ) {
     evm_genesis_config::initialize(supra_framework, evm_genesis_config);
 }
@@ -834,6 +844,67 @@ Initialize the EVM genesis config.
 
 
 
+
+
+
+
+## Function `initialize_evm_config`
+
+Initialize the EVM config.
+
+
+
fun initialize_evm_config(supra_framework: &signer, contract_names: vector<string::String>, contract_addresses: vector<address>, config_keys: vector<string::String>, config_values: vector<u128>)
+
+ + + +
+Implementation + + +
fun initialize_evm_config(
+    supra_framework: &signer,
+    contract_names: vector<String>,
+    contract_addresses: vector<address>,
+    config_keys: vector<String>,
+    config_values: vector<u128>
+) {
+    evm_config::initialize(supra_framework, contract_names, contract_addresses, config_keys, config_values);
+}
+
+ + + +
+ + + +## Function `initialize_leader_ban_registry_config` + +Initialize the leader ban config + + +
fun initialize_leader_ban_registry_config(supra_framework: &signer, leader_ban_registry_config: vector<u8>)
+
+ + + +
+Implementation + + +
fun initialize_leader_ban_registry_config(
+    supra_framework: &signer, leader_ban_registry_config: vector<u8>
+) {
+    leader_ban_registry_config::initialize(
+        supra_framework, leader_ban_registry_config
+    );
+    leader_ban_registry::initialize_leader_ban_registry(supra_framework);
+}
+
+ + +
@@ -851,22 +922,27 @@ Initialize the EVM genesis config. Implementation -
fun create_accounts(supra_framework: &signer, accounts: vector<AccountMap>) {
+
fun create_accounts(
+    supra_framework: &signer, accounts: vector<AccountMap>
+) {
     let unique_accounts = vector::empty();
-    vector::for_each_ref(&accounts, |account_map| {
-        let account_map: &AccountMap = account_map;
-        assert!(
-            !vector::contains(&unique_accounts, &account_map.account_address),
-            error::already_exists(EDUPLICATE_ACCOUNT),
-        );
-        vector::push_back(&mut unique_accounts, account_map.account_address);
+    vector::for_each_ref(
+        &accounts,
+        |account_map| {
+            let account_map: &AccountMap = account_map;
+            assert!(
+                !vector::contains(&unique_accounts, &account_map.account_address),
+                error::already_exists(EDUPLICATE_ACCOUNT)
+            );
+            vector::push_back(&mut unique_accounts, account_map.account_address);
 
-        create_account(
-            supra_framework,
-            account_map.account_address,
-            account_map.balance,
-        );
-    });
+            create_account(
+                supra_framework,
+                account_map.account_address,
+                account_map.balance
+            );
+        }
+    );
 }
 
@@ -940,8 +1016,17 @@ If it exists, it just returns the signer. let counter = 0; let result = vector::empty(); while (counter < num_of_accounts) { - let account_addr = create_multisig_account_with_balance(supra_framework, owner, additional_owners, - num_signatures_required, metadata_keys, metadata_values, timeout_duration, balance); + let account_addr = + create_multisig_account_with_balance( + supra_framework, + owner, + additional_owners, + num_signatures_required, + metadata_keys, + metadata_values, + timeout_duration, + balance + ); vector::push_back(&mut result, account_addr); counter = counter + 1; }; @@ -976,11 +1061,17 @@ If it exists, it just returns the signer. metadata_keys: vector<String>, metadata_values: vector<vector<u8>>, timeout_duration: u64, - balance: u64, + balance: u64 ): address { - assert!(account::exists_at(owner), error::invalid_argument(EACCOUNT_DOES_NOT_EXIST)); assert!( - vector::all(&additional_owners, |ao_addr|{ account::exists_at(*ao_addr) }), + account::exists_at(owner), + error::invalid_argument(EACCOUNT_DOES_NOT_EXIST) + ); + assert!( + vector::all( + &additional_owners, + |ao_addr| { account::exists_at(*ao_addr) } + ), error::invalid_argument(EACCOUNT_DOES_NOT_EXIST) ); let addr = multisig_account::get_next_multisig_account_address(owner); @@ -1021,90 +1112,104 @@ If it exists, it just returns the signer.
fun create_employee_validators(
     employee_vesting_start: u64,
     employee_vesting_period_duration: u64,
-    employees: vector<EmployeeAccountMap>,
+    employees: vector<EmployeeAccountMap>
 ) {
     let unique_accounts = vector::empty();
 
-    vector::for_each_ref(&employees, |employee_group| {
-        let j = 0;
-        let employee_group: &EmployeeAccountMap = employee_group;
-        let num_employees_in_group = vector::length(&employee_group.accounts);
-
-        let buy_ins = simple_map::create();
-
-        while (j < num_employees_in_group) {
-            let account = vector::borrow(&employee_group.accounts, j);
+    vector::for_each_ref(
+        &employees,
+        |employee_group| {
+            let j = 0;
+            let employee_group: &EmployeeAccountMap = employee_group;
+            let num_employees_in_group = vector::length(&employee_group.accounts);
+
+            let buy_ins = simple_map::create();
+
+            while (j < num_employees_in_group) {
+                let account = vector::borrow(&employee_group.accounts, j);
+                assert!(
+                    !vector::contains(&unique_accounts, account),
+                    error::already_exists(EDUPLICATE_ACCOUNT)
+                );
+                vector::push_back(&mut unique_accounts, *account);
+
+                let employee = create_signer(*account);
+                let total = coin::balance<SupraCoin>(*account);
+                let coins = coin::withdraw<SupraCoin>(&employee, total);
+                simple_map::add(&mut buy_ins, *account, coins);
+
+                j = j + 1;
+            };
+
+            let j = 0;
+            let num_vesting_events = vector::length(
+                &employee_group.vesting_schedule_numerator
+            );
+            let schedule = vector::empty();
+
+            while (j < num_vesting_events) {
+                let numerator = vector::borrow(
+                    &employee_group.vesting_schedule_numerator, j
+                );
+                let event =
+                    fixed_point32::create_from_rational(
+                        *numerator,
+                        employee_group.vesting_schedule_denominator
+                    );
+                vector::push_back(&mut schedule, event);
+
+                j = j + 1;
+            };
+
+            let vesting_schedule =
+                vesting::create_vesting_schedule(
+                    schedule,
+                    employee_vesting_start,
+                    employee_vesting_period_duration
+                );
+
+            let admin = employee_group.validator.validator_config.owner_address;
+            let admin_signer = &create_signer(admin);
+            let contract_address =
+                vesting::create_vesting_contract(
+                    admin_signer,
+                    &employee_group.accounts,
+                    buy_ins,
+                    vesting_schedule,
+                    admin,
+                    employee_group.validator.validator_config.operator_address,
+                    employee_group.validator.validator_config.voter_address,
+                    employee_group.validator.commission_percentage,
+                    x""
+                );
+            let pool_address = vesting::stake_pool_address(contract_address);
+
+            if (employee_group.beneficiary_resetter != @0x0) {
+                vesting::set_beneficiary_resetter(
+                    admin_signer,
+                    contract_address,
+                    employee_group.beneficiary_resetter
+                );
+            };
+
+            let validator = &employee_group.validator.validator_config;
             assert!(
-                !vector::contains(&unique_accounts, account),
-                error::already_exists(EDUPLICATE_ACCOUNT),
+                account::exists_at(validator.owner_address),
+                error::not_found(EACCOUNT_DOES_NOT_EXIST)
             );
-            vector::push_back(&mut unique_accounts, *account);
-
-            let employee = create_signer(*account);
-            let total = coin::balance<SupraCoin>(*account);
-            let coins = coin::withdraw<SupraCoin>(&employee, total);
-            simple_map::add(&mut buy_ins, *account, coins);
-
-            j = j + 1;
-        };
-
-        let j = 0;
-        let num_vesting_events = vector::length(&employee_group.vesting_schedule_numerator);
-        let schedule = vector::empty();
-
-        while (j < num_vesting_events) {
-            let numerator = vector::borrow(&employee_group.vesting_schedule_numerator, j);
-            let event = fixed_point32::create_from_rational(
-                *numerator,
-                employee_group.vesting_schedule_denominator
+            assert!(
+                account::exists_at(validator.operator_address),
+                error::not_found(EACCOUNT_DOES_NOT_EXIST)
             );
-            vector::push_back(&mut schedule, event);
-
-            j = j + 1;
-        };
-
-        let vesting_schedule = vesting::create_vesting_schedule(
-            schedule,
-            employee_vesting_start,
-            employee_vesting_period_duration,
-        );
-
-        let admin = employee_group.validator.validator_config.owner_address;
-        let admin_signer = &create_signer(admin);
-        let contract_address = vesting::create_vesting_contract(
-            admin_signer,
-            &employee_group.accounts,
-            buy_ins,
-            vesting_schedule,
-            admin,
-            employee_group.validator.validator_config.operator_address,
-            employee_group.validator.validator_config.voter_address,
-            employee_group.validator.commission_percentage,
-            x"",
-        );
-        let pool_address = vesting::stake_pool_address(contract_address);
-
-        if (employee_group.beneficiary_resetter != @0x0) {
-            vesting::set_beneficiary_resetter(admin_signer, contract_address, employee_group.beneficiary_resetter);
-        };
-
-        let validator = &employee_group.validator.validator_config;
-        assert!(
-            account::exists_at(validator.owner_address),
-            error::not_found(EACCOUNT_DOES_NOT_EXIST),
-        );
-        assert!(
-            account::exists_at(validator.operator_address),
-            error::not_found(EACCOUNT_DOES_NOT_EXIST),
-        );
-        assert!(
-            account::exists_at(validator.voter_address),
-            error::not_found(EACCOUNT_DOES_NOT_EXIST),
-        );
-        if (employee_group.validator.join_during_genesis) {
-            initialize_validator(pool_address, validator);
-        };
-    });
+            assert!(
+                account::exists_at(validator.voter_address),
+                error::not_found(EACCOUNT_DOES_NOT_EXIST)
+            );
+            if (employee_group.validator.join_during_genesis) {
+                initialize_validator(pool_address, validator);
+            };
+        }
+    );
 }
 
@@ -1131,12 +1236,17 @@ DEPRECATED
fun create_initialize_validators_with_commission(
     supra_framework: &signer,
     use_staking_contract: bool,
-    validators: vector<ValidatorConfigurationWithCommission>,
+    validators: vector<ValidatorConfigurationWithCommission>
 ) {
-    vector::for_each_ref(&validators, |validator| {
-        let validator: &ValidatorConfigurationWithCommission = validator;
-        create_initialize_validator(supra_framework, validator, use_staking_contract);
-    });
+    vector::for_each_ref(
+        &validators,
+        |validator| {
+            let validator: &ValidatorConfigurationWithCommission = validator;
+            create_initialize_validator(
+                supra_framework, validator, use_staking_contract
+            );
+        }
+    );
 }
 
@@ -1171,18 +1281,27 @@ encoded in a single BCS byte array. Implementation -
fun create_initialize_validators(supra_framework: &signer, validators: vector<ValidatorConfiguration>) {
+
fun create_initialize_validators(
+    supra_framework: &signer, validators: vector<ValidatorConfiguration>
+) {
     let validators_with_commission = vector::empty();
-    vector::for_each_reverse(validators, |validator| {
-        let validator_with_commission = ValidatorConfigurationWithCommission {
-            validator_config: validator,
-            commission_percentage: 0,
-            join_during_genesis: true,
-        };
-        vector::push_back(&mut validators_with_commission, validator_with_commission);
-    });
+    vector::for_each_reverse(
+        validators,
+        |validator| {
+            let validator_with_commission = ValidatorConfigurationWithCommission {
+                validator_config: validator,
+                commission_percentage: 0,
+                join_during_genesis: true
+            };
+            vector::push_back(
+                &mut validators_with_commission, validator_with_commission
+            );
+        }
+    );
 
-    create_initialize_validators_with_commission(supra_framework, false, validators_with_commission);
+    create_initialize_validators_with_commission(
+        supra_framework, false, validators_with_commission
+    );
 }
 
@@ -1208,34 +1327,40 @@ encoded in a single BCS byte array.
fun create_initialize_validator(
     supra_framework: &signer,
     commission_config: &ValidatorConfigurationWithCommission,
-    use_staking_contract: bool,
+    use_staking_contract: bool
 ) {
     let validator = &commission_config.validator_config;
 
-    let owner = &create_account(supra_framework, validator.owner_address, validator.stake_amount);
+    let owner =
+        &create_account(
+            supra_framework, validator.owner_address, validator.stake_amount
+        );
     create_account(supra_framework, validator.operator_address, 0);
     create_account(supra_framework, validator.voter_address, 0);
 
     // Initialize the stake pool and join the validator set.
-    let pool_address = if (use_staking_contract) {
-        staking_contract::create_staking_contract(
-            owner,
-            validator.operator_address,
-            validator.voter_address,
-            validator.stake_amount,
-            commission_config.commission_percentage,
-            x"",
-        );
-        staking_contract::stake_pool_address(validator.owner_address, validator.operator_address)
-    } else {
-        stake::initialize_stake_owner(
-            owner,
-            validator.stake_amount,
-            validator.operator_address,
-            validator.voter_address,
-        );
-        validator.owner_address
-    };
+    let pool_address =
+        if (use_staking_contract) {
+            staking_contract::create_staking_contract(
+                owner,
+                validator.operator_address,
+                validator.voter_address,
+                validator.stake_amount,
+                commission_config.commission_percentage,
+                x""
+            );
+            staking_contract::stake_pool_address(
+                validator.owner_address, validator.operator_address
+            )
+        } else {
+            stake::initialize_stake_owner(
+                owner,
+                validator.stake_amount,
+                validator.operator_address,
+                validator.voter_address
+            );
+            validator.owner_address
+        };
 
     if (commission_config.join_during_genesis) {
         initialize_validator(pool_address, validator);
@@ -1264,20 +1389,32 @@ encoded in a single BCS byte array.
 
 
fun create_pbo_delegation_pools(
     pbo_delegator_configs: vector<PboDelegatorConfiguration>,
-    delegation_percentage: u64,
+    delegation_percentage: u64
 ) {
     let unique_accounts: vector<address> = vector::empty();
     assert!(
         delegation_percentage != 0 && delegation_percentage <= 100,
         error::invalid_argument(EPERCENTAGE_INVALID)
     );
-    vector::for_each_ref(&pbo_delegator_configs, |pbo_delegator_config| {
-        let pbo_delegator_config: &PboDelegatorConfiguration = pbo_delegator_config;
-        assert!(!vector::contains(&unique_accounts, &pbo_delegator_config.delegator_config.owner_address),
-            error::invalid_argument(EDUPLICATE_ACCOUNT));
-        vector::push_back(&mut unique_accounts, pbo_delegator_config.delegator_config.owner_address);
-        create_pbo_delegation_pool(pbo_delegator_config, delegation_percentage);
-    });
+    vector::for_each_ref(
+        &pbo_delegator_configs,
+        |pbo_delegator_config| {
+            let pbo_delegator_config: &PboDelegatorConfiguration =
+                pbo_delegator_config;
+            assert!(
+                !vector::contains(
+                    &unique_accounts,
+                    &pbo_delegator_config.delegator_config.owner_address
+                ),
+                error::invalid_argument(EDUPLICATE_ACCOUNT)
+            );
+            vector::push_back(
+                &mut unique_accounts,
+                pbo_delegator_config.delegator_config.owner_address
+            );
+            create_pbo_delegation_pool(pbo_delegator_config, delegation_percentage);
+        }
+    );
 }
 
@@ -1301,33 +1438,40 @@ encoded in a single BCS byte array.
fun create_pbo_delegation_pool(
-    pbo_delegator_config: &PboDelegatorConfiguration,
-    delegation_percentage: u64,
+    pbo_delegator_config: &PboDelegatorConfiguration, delegation_percentage: u64
 ) {
     assert!(
         delegation_percentage != 0 && delegation_percentage <= 100,
         error::invalid_argument(EPERCENTAGE_INVALID)
     );
     let unique_accounts: vector<address> = vector::empty();
-    vector::for_each_ref(&pbo_delegator_config.delegator_config.delegator_addresses, |delegator_address| {
-        let delegator_address: &address = delegator_address;
-        assert!(
-            !vector::contains(&unique_accounts, delegator_address),
-            error::already_exists(EDUPLICATE_ACCOUNT),
-        );
-        vector::push_back(&mut unique_accounts, *delegator_address);
-    });
-    let owner_signer = create_signer(pbo_delegator_config.delegator_config.owner_address);
+    vector::for_each_ref(
+        &pbo_delegator_config.delegator_config.delegator_addresses,
+        |delegator_address| {
+            let delegator_address: &address = delegator_address;
+            assert!(
+                !vector::contains(&unique_accounts, delegator_address),
+                error::already_exists(EDUPLICATE_ACCOUNT)
+            );
+            vector::push_back(&mut unique_accounts, *delegator_address);
+        }
+    );
+    let owner_signer =
+        create_signer(pbo_delegator_config.delegator_config.owner_address);
     // get a list of delegator addresses, withdraw the coin from them and merge them into a single account
-    let delegator_addresses = pbo_delegator_config.delegator_config.delegator_addresses;
+    let delegator_addresses =
+        pbo_delegator_config.delegator_config.delegator_addresses;
     let coinInitialization = coin::zero<SupraCoin>();
-    vector::for_each(delegator_addresses, |delegator_address| {
-        let delegator = &create_signer(delegator_address);
-        let total = coin::balance<SupraCoin>(delegator_address);
-        let withdraw_amount = total * delegation_percentage / 100;
-        let coins = coin::withdraw<SupraCoin>(delegator, withdraw_amount);
-        coin::merge(&mut coinInitialization, coins);
-    });
+    vector::for_each(
+        delegator_addresses,
+        |delegator_address| {
+            let delegator = &create_signer(delegator_address);
+            let total = coin::balance<SupraCoin>(delegator_address);
+            let withdraw_amount = total * delegation_percentage / 100;
+            let coins = coin::withdraw<SupraCoin>(delegator, withdraw_amount);
+            coin::merge(&mut coinInitialization, coins);
+        }
+    );
     pbo_delegation_pool::initialize_delegation_pool(
         &owner_signer,
         option::some(pbo_delegator_config.multisig_admin),
@@ -1338,13 +1482,15 @@ encoded in a single BCS byte array.
         coinInitialization,
         pbo_delegator_config.unlock_schedule_numerators,
         pbo_delegator_config.unlock_schedule_denominator,
-        pbo_delegator_config.unlock_startup_time_from_now + timestamp::now_seconds(),
-        pbo_delegator_config.unlock_period_duration,
+        pbo_delegator_config.unlock_startup_time_from_now
+            + timestamp::now_seconds(),
+        pbo_delegator_config.unlock_period_duration
     );
 
-    let pool_address = pbo_delegation_pool::get_owned_pool_address(
-        pbo_delegator_config.delegator_config.owner_address
-    );
+    let pool_address =
+        pbo_delegation_pool::get_owned_pool_address(
+            pbo_delegator_config.delegator_config.owner_address
+        );
     let validator = pbo_delegator_config.delegator_config.validator.validator_config;
     pbo_delegation_pool::set_operator(&owner_signer, validator.operator_address);
     pbo_delegation_pool::set_delegated_voter(&owner_signer, validator.voter_address);
@@ -1375,18 +1521,20 @@ encoded in a single BCS byte array.
 Implementation
 
 
-
fun assert_validator_addresses_check(validator: &ValidatorConfiguration) {
+
fun assert_validator_addresses_check(
+    validator: &ValidatorConfiguration
+) {
     assert!(
         account::exists_at(validator.owner_address),
-        error::not_found(EACCOUNT_DOES_NOT_EXIST),
+        error::not_found(EACCOUNT_DOES_NOT_EXIST)
     );
     assert!(
         account::exists_at(validator.operator_address),
-        error::not_found(EACCOUNT_DOES_NOT_EXIST),
+        error::not_found(EACCOUNT_DOES_NOT_EXIST)
     );
     assert!(
         account::exists_at(validator.voter_address),
-        error::not_found(EACCOUNT_DOES_NOT_EXIST),
+        error::not_found(EACCOUNT_DOES_NOT_EXIST)
     );
 }
 
@@ -1414,66 +1562,95 @@ encoded in a single BCS byte array. vesting_pool_map: vector<VestingPoolsMap> ) { let unique_accounts: vector<address> = vector::empty(); - vector::for_each_ref(&vesting_pool_map, |pool_config|{ - let pool_config: &VestingPoolsMap = pool_config; - let schedule = vector::empty(); - let schedule_length = vector::length(&pool_config.vesting_numerators); - assert!(schedule_length != 0, error::invalid_argument(EVESTING_SCHEDULE_IS_ZERO)); - assert!(pool_config.vesting_denominator != 0, error::invalid_argument(EDENOMINATOR_IS_ZERO)); - assert!(pool_config.vpool_locking_percentage != 0 && pool_config.vpool_locking_percentage <= 100, - error::invalid_argument(EPERCENTAGE_INVALID)); - //check the sum of numerator are <= denominator. - let sum = vector::fold(pool_config.vesting_numerators, 0, |acc, x| acc + x); - // Check that total of all fraction in `vesting_schedule` is not greater than 1 - assert!(sum <= pool_config.vesting_denominator, - error::invalid_argument(ENUMERATOR_GREATER_THAN_DENOMINATOR)); - //assert that withdrawal_address is registered to receive SupraCoin - assert!( - coin::is_account_registered<SupraCoin>(pool_config.withdrawal_address), - error::invalid_argument(EACCOUNT_NOT_REGISTERED_FOR_COIN) - ); - //assertion on admin_address? - let admin = create_signer(pool_config.admin_address); - - //Create the vesting schedule - let j = 0; - while (j < schedule_length) { - let numerator = *vector::borrow(&pool_config.vesting_numerators, j); - assert!(numerator != 0, error::invalid_argument(ENUMERATOR_IS_ZERO)); - let event = fixed_point32::create_from_rational(numerator, pool_config.vesting_denominator); - vector::push_back(&mut schedule, event); - j = j + 1; - }; - - let vesting_schedule = vesting_without_staking::create_vesting_schedule( - schedule, - timestamp::now_seconds() + pool_config.cliff_period_in_seconds, - pool_config.period_duration_in_seconds, - ); - - let buy_ins = simple_map::create(); - let num_shareholders = vector::length(&pool_config.shareholders); - assert!(num_shareholders != 0, error::invalid_argument(ENO_SHAREHOLDERS)); - let j = 0; - while (j < num_shareholders) { - let shareholder = *vector::borrow(&pool_config.shareholders, j); - assert!(!vector::contains(&unique_accounts, &shareholder), error::already_exists(EDUPLICATE_ACCOUNT)); - vector::push_back(&mut unique_accounts, shareholder); - let shareholder_signer = create_signer(shareholder); - let amount = coin::balance<SupraCoin>(shareholder); - let amount_to_extract = (amount * (pool_config.vpool_locking_percentage as u64)) / 100; - let coin_share = coin::withdraw<SupraCoin>(&shareholder_signer, amount_to_extract); - simple_map::add(&mut buy_ins, shareholder, coin_share); - j = j + 1; - }; - vesting_without_staking::create_vesting_contract( - &admin, - buy_ins, - vesting_schedule, - pool_config.withdrawal_address, - VESTING_CONTRACT_SEED - ); - }); + vector::for_each_ref( + &vesting_pool_map, + |pool_config| { + let pool_config: &VestingPoolsMap = pool_config; + let schedule = vector::empty(); + let schedule_length = vector::length(&pool_config.vesting_numerators); + assert!( + schedule_length != 0, + error::invalid_argument(EVESTING_SCHEDULE_IS_ZERO) + ); + assert!( + pool_config.vesting_denominator != 0, + error::invalid_argument(EDENOMINATOR_IS_ZERO) + ); + assert!( + pool_config.vpool_locking_percentage != 0 + && pool_config.vpool_locking_percentage <= 100, + error::invalid_argument(EPERCENTAGE_INVALID) + ); + //check the sum of numerator are <= denominator. + let sum = vector::fold( + pool_config.vesting_numerators, + 0, + |acc, x| acc + x + ); + // Check that total of all fraction in `vesting_schedule` is not greater than 1 + assert!( + sum <= pool_config.vesting_denominator, + error::invalid_argument(ENUMERATOR_GREATER_THAN_DENOMINATOR) + ); + //assert that withdrawal_address is registered to receive SupraCoin + assert!( + coin::is_account_registered<SupraCoin>(pool_config.withdrawal_address), + error::invalid_argument(EACCOUNT_NOT_REGISTERED_FOR_COIN) + ); + //assertion on admin_address? + let admin = create_signer(pool_config.admin_address); + + //Create the vesting schedule + let j = 0; + while (j < schedule_length) { + let numerator = *vector::borrow(&pool_config.vesting_numerators, j); + assert!(numerator != 0, error::invalid_argument(ENUMERATOR_IS_ZERO)); + let event = + fixed_point32::create_from_rational( + numerator, pool_config.vesting_denominator + ); + vector::push_back(&mut schedule, event); + j = j + 1; + }; + + let vesting_schedule = + vesting_without_staking::create_vesting_schedule( + schedule, + timestamp::now_seconds() + pool_config.cliff_period_in_seconds, + pool_config.period_duration_in_seconds + ); + + let buy_ins = simple_map::create(); + let num_shareholders = vector::length(&pool_config.shareholders); + assert!(num_shareholders != 0, error::invalid_argument(ENO_SHAREHOLDERS)); + let j = 0; + while (j < num_shareholders) { + let shareholder = *vector::borrow(&pool_config.shareholders, j); + assert!( + !vector::contains(&unique_accounts, &shareholder), + error::already_exists(EDUPLICATE_ACCOUNT) + ); + vector::push_back(&mut unique_accounts, shareholder); + let shareholder_signer = create_signer(shareholder); + let amount = coin::balance<SupraCoin>(shareholder); + let amount_to_extract = + (amount * (pool_config.vpool_locking_percentage as u64)) / 100; + let coin_share = + coin::withdraw<SupraCoin>( + &shareholder_signer, amount_to_extract + ); + simple_map::add(&mut buy_ins, shareholder, coin_share); + j = j + 1; + }; + vesting_without_staking::create_vesting_contract( + &admin, + buy_ins, + vesting_schedule, + pool_config.withdrawal_address, + VESTING_CONTRACT_SEED + ); + } + ); }
@@ -1496,19 +1673,21 @@ encoded in a single BCS byte array. Implementation -
fun initialize_validator(pool_address: address, validator: &ValidatorConfiguration) {
+
fun initialize_validator(
+    pool_address: address, validator: &ValidatorConfiguration
+) {
     let operator = &create_signer(validator.operator_address);
 
     stake::rotate_consensus_key_genesis(
         operator,
         pool_address,
-        validator.consensus_pubkey,
+        validator.consensus_pubkey
     );
     stake::update_network_and_fullnode_addresses(
         operator,
         pool_address,
         validator.network_addresses,
-        validator.full_node_network_addresses,
+        validator.full_node_network_addresses
     );
     stake::join_validator_set_internal(operator, pool_address);
 }
diff --git a/aptos-move/framework/supra-framework/doc/leader_ban_registry.md b/aptos-move/framework/supra-framework/doc/leader_ban_registry.md
new file mode 100644
index 00000000000..c01e741007a
--- /dev/null
+++ b/aptos-move/framework/supra-framework/doc/leader_ban_registry.md
@@ -0,0 +1,1209 @@
+
+
+
+# Module `0x1::leader_ban_registry`
+
+Maintains the list of banned validators and updates counters on every epoch.
+
+This implementation assumes that each validator is elected once every n consensus rounds on expectation,
+where n is the number of validators in the consensus committee (i.e. the ValidatorSet).
+
+
+-  [Struct `ActiveBan`](#0x1_leader_ban_registry_ActiveBan)
+-  [Struct `ValidatorBans`](#0x1_leader_ban_registry_ValidatorBans)
+-  [Resource `BanRegistry`](#0x1_leader_ban_registry_BanRegistry)
+-  [Resource `LatestView`](#0x1_leader_ban_registry_LatestView)
+-  [Struct `Banned`](#0x1_leader_ban_registry_Banned)
+-  [Struct `ReinstatedWithProbation`](#0x1_leader_ban_registry_ReinstatedWithProbation)
+-  [Struct `Reinstated`](#0x1_leader_ban_registry_Reinstated)
+-  [Constants](#@Constants_0)
+-  [Function `initialize_leader_ban_registry`](#0x1_leader_ban_registry_initialize_leader_ban_registry)
+-  [Function `get_ban_registry`](#0x1_leader_ban_registry_get_ban_registry)
+-  [Function `get_latest_view`](#0x1_leader_ban_registry_get_latest_view)
+-  [Function `get_initial_ban_duration`](#0x1_leader_ban_registry_get_initial_ban_duration)
+-  [Function `get_max_ban_duration`](#0x1_leader_ban_registry_get_max_ban_duration)
+-  [Function `get_probation_duration`](#0x1_leader_ban_registry_get_probation_duration)
+-  [Function `get_remaining_ban_duration`](#0x1_leader_ban_registry_get_remaining_ban_duration)
+-  [Function `get_remaining_probation_duration`](#0x1_leader_ban_registry_get_remaining_probation_duration)
+-  [Function `update_ban_registry`](#0x1_leader_ban_registry_update_ban_registry)
+-  [Function `ban_failed_proposers`](#0x1_leader_ban_registry_ban_failed_proposers)
+-  [Function `reinstate_expired_bans`](#0x1_leader_ban_registry_reinstate_expired_bans)
+-  [Function `on_new_epoch`](#0x1_leader_ban_registry_on_new_epoch)
+-  [Function `remaining_ban_duration`](#0x1_leader_ban_registry_remaining_ban_duration)
+-  [Function `remaining_probation_duration`](#0x1_leader_ban_registry_remaining_probation_duration)
+-  [Function `can_be_banned`](#0x1_leader_ban_registry_can_be_banned)
+-  [Function `assert_registry_initialized`](#0x1_leader_ban_registry_assert_registry_initialized)
+
+
+
use 0x1::error;
+use 0x1::event;
+use 0x1::features;
+use 0x1::leader_ban_registry_config;
+use 0x1::math64;
+use 0x1::option;
+use 0x1::stake;
+use 0x1::system_addresses;
+use 0x1::vector;
+
+ + + + + +## Struct `ActiveBan` + +Information about a ban that is currently in effect for a validator. + + +
struct ActiveBan has copy, drop, store
+
+ + + +
+Fields + + +
+
+epoch_earned: u64 +
+
+ The consensus epoch in which the current ban was issued (if on_probation is false) or + when its probation period started (if on_probation is true). +
+
+round_earned: u64 +
+
+ The consensus round in which the current ban was issued (if on_probation is false) or + when its probation period started (if on_probation is true). +
+
+rounds_served_in_previous_epochs: u64 +
+
+ Round count incremented on every epoch change +
+
+on_probation: bool +
+
+ If true then the current ban period has expired and the validator is currently on probation; i.e., it is + eligible for election but will be banned for a longer period if it once again fails to propose a canonical + block when elected. If true then the other fields of this struct denote the consensus view in which + the probation period started. +
+
+ + +
+ + + +## Struct `ValidatorBans` + +Holds validator metrics regarding duration pool address etc + + +
struct ValidatorBans has copy, drop, store
+
+ + + +
+Fields + + +
+
+active: leader_ban_registry::ActiveBan +
+
+ Information about the ban that is currently in effect. +
+
+consecutive_bans: u32 +
+
+ The number of consecutive probations that this validator has failed. +
+
+pool_address: address +
+
+ Validator's pool address +
+
+ + +
+ + + +## Resource `BanRegistry` + +Holds ban registry + + +
struct BanRegistry has drop, store, key
+
+ + + +
+Fields + + +
+
+bans: vector<leader_ban_registry::ValidatorBans> +
+
+ List of validator active bans with pool address +
+
+ + +
+ + + +## Resource `LatestView` + +Holds latest processed round and epoch + + +
struct LatestView has copy, drop, store, key
+
+ + + +
+Fields + + +
+
+epoch: u64 +
+
+ Epoch +
+
+round: u64 +
+
+ Round +
+
+ + +
+ + + +## Struct `Banned` + +Emits when validator receives a ban or consucutive ban occurred + + +
#[event]
+struct Banned has drop, store
+
+ + + +
+Fields + + +
+
+pool_address: address +
+
+ Validator's pool address +
+
+epoch: u64 +
+
+ Epoch +
+
+round: u64 +
+
+ Round +
+
+consecutive_bans: u32 +
+
+ The number of consecutive probations that this validator has failed. +
+
+ + +
+ + + +## Struct `ReinstatedWithProbation` + +Emitted when a validator's ban is lifted and its probation period starts. A validator that is on probation is +eligible for election again, but will be banned for longer if it once again fails to propose a canonical block. + + +
#[event]
+struct ReinstatedWithProbation has drop, store
+
+ + + +
+Fields + + +
+
+pool_address: address +
+
+ Validator's pool address +
+
+epoch: u64 +
+
+ Epoch +
+
+round: u64 +
+
+ Round +
+
+ + +
+ + + +## Struct `Reinstated` + +Emitted when a validator's probation period ends without the validator earning a new ban. + + +
#[event]
+struct Reinstated has drop, store
+
+ + + +
+Fields + + +
+
+pool_address: address +
+
+ Validator's pool address +
+
+epoch: u64 +
+
+ Epoch +
+
+round: u64 +
+
+ Round +
+
+ + +
+ + + +## Constants + + + + +Leader ban registry already initialized + + +
const EBAN_REGISTRY_ALREADY_EXISTS: u64 = 1;
+
+ + + + + +Leader ban registry not initialized + + +
const EBAN_REGISTRY_NOT_INITIALIZED: u64 = 2;
+
+ + + + + +Latest view already initialized + + +
const ELATEST_VIEW_ALREADY_EXISTS: u64 = 3;
+
+ + + + + +## Function `initialize_leader_ban_registry` + +Initialise leader ban registry + + +
public(friend) fun initialize_leader_ban_registry(supra_framework: &signer)
+
+ + + +
+Implementation + + +
public(friend) fun initialize_leader_ban_registry(
+    supra_framework: &signer
+) {
+    system_addresses::assert_supra_framework(supra_framework);
+    assert!(
+        !exists<BanRegistry>(@supra_framework),
+        error::already_exists(EBAN_REGISTRY_ALREADY_EXISTS)
+    );
+    assert!(
+        !exists<LatestView>(@supra_framework),
+        error::already_exists(EBAN_REGISTRY_ALREADY_EXISTS)
+    );
+    move_to(supra_framework, BanRegistry { bans: vector::empty() });
+    move_to(supra_framework, LatestView { epoch: 0, round: 0 });
+}
+
+ + + +
+ + + +## Function `get_ban_registry` + +Returns list of validators active ban with it's pool address + + +
#[view]
+public fun get_ban_registry(): vector<leader_ban_registry::ValidatorBans>
+
+ + + +
+Implementation + + +
public fun get_ban_registry(): vector<ValidatorBans> acquires BanRegistry {
+    if (!exists<BanRegistry>(@supra_framework)) {
+        return vector::empty()
+    };
+    let ban_registry = borrow_global<BanRegistry>(@supra_framework);
+    ban_registry.bans
+}
+
+ + + +
+ + + +## Function `get_latest_view` + +Return latest view + + +
#[view]
+public fun get_latest_view(): leader_ban_registry::LatestView
+
+ + + +
+Implementation + + +
public fun get_latest_view(): LatestView acquires LatestView {
+    if (!exists<LatestView>(@supra_framework)) {
+        return LatestView { epoch: 0, round: 0 }
+    };
+    let latest_view = borrow_global<LatestView>(@supra_framework);
+    *latest_view
+}
+
+ + + +
+ + + +## Function `get_initial_ban_duration` + +Returns the number of consensus rounds that a validator is banned for when it fails to propose a +canonical block when elected as leader whilst not on probation. + + +
#[view]
+public fun get_initial_ban_duration(): u64
+
+ + + +
+Implementation + + +
public fun get_initial_ban_duration(): u64 {
+    let initial_elections_denied =
+        leader_ban_registry_config::get_initial_elections_denied();
+    let committee_size = stake::get_committee_size();
+    committee_size * (initial_elections_denied as u64)
+}
+
+ + + +
+ + + +## Function `get_max_ban_duration` + +Returns the maximum number of consensus rounds that a validator may banned for when it repeatedly fails to +propose a canonical block when elected as leader whilst on probation. + + +
#[view]
+public fun get_max_ban_duration(): u64
+
+ + + +
+Implementation + + +
public fun get_max_ban_duration(): u64 {
+    let max_elections_denied = leader_ban_registry_config::get_max_elections_denied();
+    let committee_size = stake::get_committee_size();
+    committee_size * (max_elections_denied as u64)
+}
+
+ + + +
+ + + +## Function `get_probation_duration` + +Returns the number of consensus rounds that a validator is considered to be on probation for after having +served its most recent ban. + + +
#[view]
+public fun get_probation_duration(): u64
+
+ + + +
+Implementation + + +
public fun get_probation_duration(): u64 {
+    let probation_elections = leader_ban_registry_config::get_probation_elections();
+    let committee_size = stake::get_committee_size();
+    committee_size * (probation_elections as u64)
+}
+
+ + + +
+ + + +## Function `get_remaining_ban_duration` + +Returns the number of consensus rounds remaining in the ban for the validator with the given +pool address. Returns 0 if the validator is not banned (including if it is on probation). + + +
#[view]
+public fun get_remaining_ban_duration(pool_address: address): u64
+
+ + + +
+Implementation + + +
public fun get_remaining_ban_duration(
+    pool_address: address
+): u64 acquires BanRegistry, LatestView {
+    if (!exists<BanRegistry>(@supra_framework)
+        || !exists<LatestView>(@supra_framework)) {
+        return 0
+    };
+    let ban_registry = borrow_global<BanRegistry>(@supra_framework);
+    let latest_view = borrow_global<LatestView>(@supra_framework);
+    let (found, index) = vector::find(
+        &ban_registry.bans,
+        |v| {
+            let v: &ValidatorBans = v;
+            v.pool_address == pool_address && !v.active.on_probation
+        }
+    );
+    if (found) {
+        remaining_ban_duration(
+            vector::borrow(&ban_registry.bans, index), latest_view
+        )
+    } else { 0 }
+}
+
+ + + +
+ + + +## Function `get_remaining_probation_duration` + +Returns the number of consensus rounds remaining in the probation period for the validator +with the given pool address. Returns 0 if the validator is not on probation. + + +
#[view]
+public fun get_remaining_probation_duration(pool_address: address): u64
+
+ + + +
+Implementation + + +
public fun get_remaining_probation_duration(
+    pool_address: address
+): u64 acquires BanRegistry, LatestView {
+    if (!exists<BanRegistry>(@supra_framework)
+        || !exists<LatestView>(@supra_framework)) {
+        return 0
+    };
+    let ban_registry = borrow_global<BanRegistry>(@supra_framework);
+    let latest_view = borrow_global<LatestView>(@supra_framework);
+    let (found, index) = vector::find(
+        &ban_registry.bans,
+        |v| {
+            let v: &ValidatorBans = v;
+            v.pool_address == pool_address && v.active.on_probation
+        }
+    );
+    if (found) {
+        let probation_dur = get_probation_duration();
+        remaining_probation_duration(
+            vector::borrow(&ban_registry.bans, index),
+            latest_view,
+            probation_dur
+        )
+    } else { 0 }
+}
+
+ + + +
+ + + +## Function `update_ban_registry` + +Add or update the ban registry as per block metadata + + +
public(friend) fun update_ban_registry(current_epoch: u64, current_round: u64, proposer_index: option::Option<u64>, failed_proposer_indices: vector<u64>)
+
+ + + +
+Implementation + + +
public(friend) fun update_ban_registry(
+    current_epoch: u64,
+    current_round: u64,
+    proposer_index: Option<u64>,
+    failed_proposer_indices: vector<u64>
+) acquires BanRegistry, LatestView {
+    if (!exists<BanRegistry>(@supra_framework)) { return };
+    if (!exists<LatestView>(@supra_framework)) { return };
+    let ban_registry = borrow_global_mut<BanRegistry>(@supra_framework);
+    let latest_view = borrow_global_mut<LatestView>(@supra_framework);
+
+    // Save the previous view before updating. Each failed proposer failed at a
+    // distinct round between the previous commit and the current commit, so we
+    // need this to reconstruct the actual round at which each ban was earned.
+    let previous_epoch = latest_view.epoch;
+    let previous_round = latest_view.round;
+
+    // we expect that current_epoch == latest_view.epoch || current_epoch == latest_view.epoch + 1,
+    // but we don't assert this to be true here because it should be ensured by the consensus.
+    if (current_epoch < latest_view.epoch) { return };
+
+    latest_view.epoch = current_epoch;
+    latest_view.round = current_round;
+
+    // ban the failed proposers
+    ban_failed_proposers(
+        current_epoch, previous_epoch, previous_round,
+        failed_proposer_indices, ban_registry
+    );
+
+    // remove expired bans
+    reinstate_expired_bans(latest_view, ban_registry);
+}
+
+ + + +
+ + + +## Function `ban_failed_proposers` + +Adds failed proposer indices to ban registry. Each failed proposer failed at a +consecutive round between the previous commit and the current commit. The actual +failed round is reconstructed from the previous view: +- Same epoch: failed rounds start at previous_round + 1 +- Epoch boundary: failed rounds start at 0 (new epoch resets round to 0) + + +
fun ban_failed_proposers(current_epoch: u64, previous_epoch: u64, previous_round: u64, failed_proposer_indices: vector<u64>, ban_registry: &mut leader_ban_registry::BanRegistry)
+
+ + + +
+Implementation + + +
fun ban_failed_proposers(
+    current_epoch: u64,
+    previous_epoch: u64,
+    previous_round: u64,
+    failed_proposer_indices: vector<u64>,
+    ban_registry: &mut BanRegistry
+) {
+    let initial_ban_duration = get_initial_ban_duration();
+    if (initial_ban_duration == 0) { return };
+
+    // Compute the first failed round based on whether the epoch changed.
+    let first_failed_round = if (previous_epoch == current_epoch) {
+        previous_round + 1
+    } else {
+        // Epoch boundary: the last block of the previous epoch was committed
+        // successfully, so failures start from round 0 of the new epoch.
+        0
+    };
+
+    let i = 0;
+    let len = vector::length(&failed_proposer_indices);
+    while (i < len) {
+        let failed_validator_index = *vector::borrow(&failed_proposer_indices, i);
+        let failed_round = first_failed_round + i;
+
+        let validator_pool_address_opt =
+            stake::get_pool_address_from_index(failed_validator_index);
+
+        if (option::is_some(&validator_pool_address_opt)) {
+            let validator_pool_address =
+                option::extract(&mut validator_pool_address_opt);
+            let (is_banned, index) = vector::find(
+                &ban_registry.bans,
+                |v| {
+                    let v: &ValidatorBans = v;
+                    validator_pool_address == v.pool_address
+                }
+            );
+            if (is_banned) {
+                // Validator is already in registry (either banned or on probation).
+                // Re-banning resets the ban period and increases consecutive count.
+                // If the consensus code is implemented correctly then the validator should
+                // not be re-banned whilst serving a ban as it should not be eligible for election
+                // when banned (i.e. this branch should only be taken when a validator is on probation).
+                let bans = vector::borrow_mut(&mut ban_registry.bans, index);
+                bans.consecutive_bans = bans.consecutive_bans + 1;
+                bans.active.round_earned = failed_round;
+                bans.active.epoch_earned = current_epoch;
+                bans.active.rounds_served_in_previous_epochs = 0;
+                bans.active.on_probation = false; // Reset to banned state
+
+                if (features::module_event_enabled()) {
+                    event::emit(
+                        Banned {
+                            pool_address: validator_pool_address,
+                            epoch: current_epoch,
+                            round: failed_round,
+                            consecutive_bans: bans.consecutive_bans
+                        }
+                    );
+                }
+            } else {
+                let ban_registry_len = vector::length(&ban_registry.bans);
+                if (can_be_banned(ban_registry_len)) {
+                    let ban_with_address = ValidatorBans {
+                        active: ActiveBan {
+                            epoch_earned: current_epoch,
+                            round_earned: failed_round,
+                            rounds_served_in_previous_epochs: 0,
+                            on_probation: false
+                        },
+                        consecutive_bans: 0,
+                        pool_address: validator_pool_address
+                    };
+                    vector::push_back(&mut ban_registry.bans, ban_with_address);
+
+                    if (features::module_event_enabled()) {
+                        event::emit(
+                            Banned {
+                                pool_address: ban_with_address.pool_address,
+                                epoch: ban_with_address.active.epoch_earned,
+                                round: ban_with_address.active.round_earned,
+                                consecutive_bans: ban_with_address.consecutive_bans
+                            }
+                        );
+                    }
+                }
+            };
+        };
+
+        i = i + 1;
+    };
+}
+
+ + + +
+ + + +## Function `reinstate_expired_bans` + +Handles ban and probation expiry: +- When probation expires: removes from registry, emits Reinstated +- When ban expires and probation_duration > 0: transitions to probation, emits ReinstatedWithProbation +- When ban expires and probation_duration == 0: removes from registry, emits Reinstated + + +
fun reinstate_expired_bans(latest_view: &leader_ban_registry::LatestView, ban_registry: &mut leader_ban_registry::BanRegistry)
+
+ + + +
+Implementation + + +
fun reinstate_expired_bans(
+    latest_view: &LatestView, ban_registry: &mut BanRegistry
+) {
+    let probation_duration = get_probation_duration();
+
+    // First pass: remove validators whose probation has expired.
+    // Done before ban-to-probation transitions to avoid iterating just-transitioned validators.
+    // Always runs (even when probation_duration == 0) to clean up validators that were already
+    // on probation before a config change set probation_duration to 0.
+    let pool_addresses_for_full_reinstatement = vector::empty();
+    vector::for_each_ref(
+        &ban_registry.bans,
+        |v| {
+            let v: &ValidatorBans = v;
+            if (v.active.on_probation
+                && remaining_probation_duration(v, latest_view, probation_duration)
+                    == 0) {
+                vector::push_back(
+                    &mut pool_addresses_for_full_reinstatement, v.pool_address
+                );
+            }
+        }
+    );
+
+    vector::for_each_ref(
+        &pool_addresses_for_full_reinstatement,
+        |p| {
+            let (found, index) = vector::find(
+                &ban_registry.bans,
+                |v| {
+                    let v: &ValidatorBans = v;
+                    &v.pool_address == p
+                }
+            );
+            if (found) {
+                vector::swap_remove(&mut ban_registry.bans, index);
+
+                if (features::module_event_enabled()) {
+                    event::emit(
+                        Reinstated {
+                            epoch: latest_view.epoch,
+                            round: latest_view.round,
+                            pool_address: *p
+                        }
+                    )
+                }
+            }
+        }
+    );
+
+    // Second pass: handle expired bans
+    let pool_addresses_with_expired_bans = vector::empty();
+    vector::for_each_ref(
+        &ban_registry.bans,
+        |v| {
+            let v: &ValidatorBans = v;
+            if (!v.active.on_probation
+                && remaining_ban_duration(v, latest_view) == 0) {
+                vector::push_back(
+                    &mut pool_addresses_with_expired_bans, v.pool_address
+                );
+            }
+        }
+    );
+
+    if (probation_duration > 0) {
+        // Transition expired bans to probation
+        vector::for_each_ref(
+            &pool_addresses_with_expired_bans,
+            |p| {
+                let (found, index) = vector::find(
+                    &ban_registry.bans,
+                    |v| {
+                        let v: &ValidatorBans = v;
+                        &v.pool_address == p
+                    }
+                );
+                if (found) {
+                    let ban = vector::borrow_mut(&mut ban_registry.bans, index);
+                    ban.active.on_probation = true;
+                    // Reset active fields so probation duration is calculated from this point
+                    ban.active.epoch_earned = latest_view.epoch;
+                    ban.active.round_earned = latest_view.round;
+                    ban.active.rounds_served_in_previous_epochs = 0;
+
+                    if (features::module_event_enabled()) {
+                        event::emit(
+                            ReinstatedWithProbation {
+                                epoch: latest_view.epoch,
+                                round: latest_view.round,
+                                pool_address: *p
+                            }
+                        )
+                    }
+                }
+            }
+        );
+    } else {
+        // No probation period - directly remove validators whose ban expired
+        vector::for_each_ref(
+            &pool_addresses_with_expired_bans,
+            |p| {
+                let (found, index) = vector::find(
+                    &ban_registry.bans,
+                    |v| {
+                        let v: &ValidatorBans = v;
+                        &v.pool_address == p
+                    }
+                );
+                if (found) {
+                    vector::swap_remove(&mut ban_registry.bans, index);
+
+                    if (features::module_event_enabled()) {
+                        event::emit(
+                            Reinstated {
+                                epoch: latest_view.epoch,
+                                round: latest_view.round,
+                                pool_address: *p
+                            }
+                        )
+                    }
+                }
+            }
+        );
+    };
+}
+
+ + + +
+ + + +## Function `on_new_epoch` + +Increments the total number of consensus rounds served by each banned validator and removes +registry entries for validators that have left the validator set. + +The number of rounds in each epoch may vary due to network asynchrony, so we must record the +number of rounds served in previous epochs to be able to ensure that a banned validator serves its +full ban period when its ban span multiple epochs. + + +
public(friend) fun on_new_epoch()
+
+ + + +
+Implementation + + +
public(friend) fun on_new_epoch() acquires BanRegistry, LatestView {
+    if (!exists<LatestView>(@supra_framework)) { return };
+    if (!exists<BanRegistry>(@supra_framework)) { return };
+    let latest_view = borrow_global<LatestView>(@supra_framework);
+    let ban_registry = borrow_global_mut<BanRegistry>(@supra_framework);
+
+    // The pool addresses of the validators for the new epoch.
+    let new_committee_pool_addresses = stake::get_committee_pool_addresses();
+    // The pool addresses of the validators that have left the committee.
+    let retired_validators = vector::empty();
+    vector::for_each_mut(
+        &mut ban_registry.bans,
+        |v| {
+            let v: &mut ValidatorBans = v;
+            if (vector::contains(&new_committee_pool_addresses, &v.pool_address)) {
+                if (latest_view.epoch > v.active.epoch_earned) {
+                    v.active.rounds_served_in_previous_epochs =
+                        v.active.rounds_served_in_previous_epochs
+                            + latest_view.round;
+                } else if (latest_view.epoch == v.active.epoch_earned
+                    && latest_view.round > v.active.round_earned) {
+                    v.active.rounds_served_in_previous_epochs =
+                        latest_view.round - v.active.round_earned;
+                };
+                // else: The ban hasn't started yet.
+            } else {
+                vector::push_back(&mut retired_validators, v.pool_address)
+            }
+        }
+    );
+
+    vector::for_each_ref(
+        &retired_validators,
+        |p| {
+            let (is_banned, index) = vector::find(
+                &ban_registry.bans,
+                |v| {
+                    let v: &ValidatorBans = v;
+                    &v.pool_address == p
+                }
+            );
+            if (is_banned) {
+                vector::swap_remove(&mut ban_registry.bans, index);
+
+                if (features::module_event_enabled()) {
+                    event::emit(
+                        Reinstated {
+                            pool_address: *p,
+                            epoch: latest_view.epoch,
+                            round: latest_view.round
+                        }
+                    );
+                }
+            }
+        }
+    );
+}
+
+ + + +
+ + + +## Function `remaining_ban_duration` + +Calculate the number of rounds remaining in a given ban (not including probation). + + +
fun remaining_ban_duration(ban: &leader_ban_registry::ValidatorBans, latest_view: &leader_ban_registry::LatestView): u64
+
+ + + +
+Implementation + + +
fun remaining_ban_duration(
+    ban: &ValidatorBans, latest_view: &LatestView
+): u64 {
+    let initial_ban_duration = get_initial_ban_duration();
+    let max_ban_duration = get_max_ban_duration();
+    // Guard against overflow: pow(2, n) overflows u64 when n >= 64, and the
+    // subsequent multiplication can overflow for smaller exponents. In both cases
+    // the uncapped result would exceed max_ban_duration, so we short-circuit.
+    let duration = if ((ban.consecutive_bans as u64) >= 64) {
+        max_ban_duration
+    } else {
+        let scale = pow(2, (ban.consecutive_bans as u64));
+        if (initial_ban_duration > 0 && scale > max_ban_duration / initial_ban_duration) {
+            max_ban_duration
+        } else {
+            min(initial_ban_duration * scale, max_ban_duration)
+        }
+    };
+    let rounds_served =
+        if (latest_view.epoch > ban.active.epoch_earned) {
+            ban.active.rounds_served_in_previous_epochs + latest_view.round
+        } else if (latest_view.epoch == ban.active.epoch_earned
+            && latest_view.round > ban.active.round_earned) {
+            latest_view.round - ban.active.round_earned
+        } else {
+            // The ban hasn't started yet.
+            0
+        };
+    if (duration > rounds_served) {
+        duration - rounds_served
+    } else { 0 }
+}
+
+ + + +
+ + + +## Function `remaining_probation_duration` + +Calculate the number of rounds remaining in probation. +Probation duration is constant and does not scale with consecutive bans. + + +
fun remaining_probation_duration(ban: &leader_ban_registry::ValidatorBans, latest_view: &leader_ban_registry::LatestView, probation_duration: u64): u64
+
+ + + +
+Implementation + + +
fun remaining_probation_duration(
+    ban: &ValidatorBans, latest_view: &LatestView, probation_duration: u64
+): u64 {
+    let rounds_served =
+        if (latest_view.epoch > ban.active.epoch_earned) {
+            ban.active.rounds_served_in_previous_epochs + latest_view.round
+        } else if (latest_view.epoch == ban.active.epoch_earned
+            && latest_view.round > ban.active.round_earned) {
+            latest_view.round - ban.active.round_earned
+        } else {
+            // The ban hasn't started yet.
+            0
+        };
+    if (probation_duration > rounds_served) {
+        probation_duration - rounds_served
+    } else { 0 }
+}
+
+ + + +
+ + + +## Function `can_be_banned` + +Returns true until ban registry size + minimum proposers required count less than committee size + + +
fun can_be_banned(ban_registry_len: u64): bool
+
+ + + +
+Implementation + + +
fun can_be_banned(ban_registry_len: u64): bool {
+    let minimum_unbanned_proposers =
+        leader_ban_registry_config::get_minimum_unbanned_proposers();
+    let committee_size = stake::get_committee_size();
+    committee_size > ban_registry_len + (minimum_unbanned_proposers as u64)
+}
+
+ + + +
+ + + +## Function `assert_registry_initialized` + +Validates registry initialised if not aborted with EBAN_REGISTRY_NOT_INITIALIZED + + +
fun assert_registry_initialized()
+
+ + + +
+Implementation + + +
fun assert_registry_initialized() {
+    assert!(
+        exists<BanRegistry>(@supra_framework),
+        error::invalid_state(EBAN_REGISTRY_NOT_INITIALIZED)
+    );
+}
+
+ + + +
+ + +[move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/supra-framework/doc/leader_ban_registry_config.md b/aptos-move/framework/supra-framework/doc/leader_ban_registry_config.md new file mode 100644 index 00000000000..ece30fbf5e8 --- /dev/null +++ b/aptos-move/framework/supra-framework/doc/leader_ban_registry_config.md @@ -0,0 +1,541 @@ + + + +# Module `0x1::leader_ban_registry_config` + +Provides the config related to leader ban registry + + +- [Resource `BanRegistryParameters`](#0x1_leader_ban_registry_config_BanRegistryParameters) +- [Resource `BanRegistryParametersV0`](#0x1_leader_ban_registry_config_BanRegistryParametersV0) +- [Constants](#@Constants_0) +- [Function `initialize`](#0x1_leader_ban_registry_config_initialize) +- [Function `set_for_next_epoch`](#0x1_leader_ban_registry_config_set_for_next_epoch) +- [Function `on_new_epoch`](#0x1_leader_ban_registry_config_on_new_epoch) +- [Function `get_ban_registry_params`](#0x1_leader_ban_registry_config_get_ban_registry_params) +- [Function `get_ban_registry_params_v0`](#0x1_leader_ban_registry_config_get_ban_registry_params_v0) +- [Function `get_initial_elections_denied`](#0x1_leader_ban_registry_config_get_initial_elections_denied) +- [Function `get_max_elections_denied`](#0x1_leader_ban_registry_config_get_max_elections_denied) +- [Function `get_minimum_unbanned_proposers`](#0x1_leader_ban_registry_config_get_minimum_unbanned_proposers) +- [Function `get_probation_elections`](#0x1_leader_ban_registry_config_get_probation_elections) +- [Function `deserialise_v0_params`](#0x1_leader_ban_registry_config_deserialise_v0_params) + + +
use 0x1::config_buffer;
+use 0x1::decode_bcs;
+use 0x1::error;
+use 0x1::option;
+use 0x1::system_addresses;
+
+ + + + + +## Resource `BanRegistryParameters` + +Holds ban registry parameters bytes and it's version + + +
struct BanRegistryParameters has drop, store, key
+
+ + + +
+Fields + + +
+
+config: vector<u8> +
+
+ Denotes config bcs bytes +
+
+version: u8 +
+
+ Denotes config version +
+
+ + +
+ + + +## Resource `BanRegistryParametersV0` + +Ban registry parameters v0 + + +
struct BanRegistryParametersV0 has drop, store, key
+
+ + + +
+Fields + + +
+
+initial_elections_denied: u8 +
+
+ Denotes initial election count denied +
+
+max_elections_denied: u32 +
+
+ Denotes max election count denied +
+
+minimum_unbanned_proposers: u8 +
+
+ Denotes the minimum number of validators that must remain eligible for proposal. This + helps to preserve liveness in the presence of extended periods of network asynchrony. +
+
+probation_elections: u8 +
+
+ Denotes the number of elections a validator must serve on probation after ban expires. + The ban duration compounds each time a validator is banned whilst on probation, and + resets to the base duration if the validator passes probation. +
+
+ + +
+ + + +## Constants + + + + +The BanRegistryParameters already initialised + + +
const EALREADY_INITIALISED: u64 = 4;
+
+ + + + + +The provided on chain config bytes are empty or invalid + + +
const EINVALID_CONFIG: u64 = 1;
+
+ + + + + +The provided on chain config version should be equal or greater than existing + + +
const EINVALID_VERSION: u64 = 2;
+
+ + + + + +Decoding from version bytes failed + + +
const EINVALID_VERSION_BYTES: u64 = 3;
+
+ + + + + +## Function `initialize` + +Publishes the BanRegistryParameters config. + + +
public(friend) fun initialize(supra_framework: &signer, config: vector<u8>)
+
+ + + +
+Implementation + + +
public(friend) fun initialize(
+    supra_framework: &signer, config: vector<u8>
+) {
+    system_addresses::assert_supra_framework(supra_framework);
+    assert!(vector::length(&config) != 0, error::invalid_argument(EINVALID_CONFIG));
+    assert!(
+        !exists<BanRegistryParameters>(@supra_framework),
+        error::already_exists(EALREADY_INITIALISED)
+    );
+    let v0 = deserialise_v0_params(config);
+    if (option::is_none(&v0)) {
+        abort error::invalid_argument(EINVALID_VERSION_BYTES)
+    };
+    // we always init with version 0
+    move_to(supra_framework, BanRegistryParameters { config, version: 0 });
+    let v0_params = option::extract(&mut v0);
+    move_to(supra_framework, v0_params);
+}
+
+ + + +
+ + + +## Function `set_for_next_epoch` + +This can be called by on-chain governance to update on-chain configs for the next epoch. +Example usage: +``` +supra_framework::leader_ban_registry_config::set_for_next_epoch(&framework_signer, some_config_bytes, version); +supra_framework::supra_governance::reconfigure(&framework_signer); +``` + + +
public fun set_for_next_epoch(account: &signer, config: vector<u8>, version: u8)
+
+ + + +
+Implementation + + +
public fun set_for_next_epoch(
+    account: &signer, config: vector<u8>, version: u8
+) acquires BanRegistryParameters {
+    system_addresses::assert_supra_framework(account);
+    assert!(vector::length(&config) != 0, error::invalid_argument(EINVALID_CONFIG));
+    if (exists<BanRegistryParameters>(@supra_framework)) {
+        let ban_registry_params =
+            borrow_global<BanRegistryParameters>(@supra_framework);
+        assert!(
+            version >= ban_registry_params.version,
+            error::invalid_argument(EINVALID_VERSION)
+        );
+    };
+    std::config_buffer::upsert<BanRegistryParameters>(
+        BanRegistryParameters { config, version }
+    );
+}
+
+ + + +
+ + + +## Function `on_new_epoch` + +Only used in reconfigurations to apply the pending BanRegistryParameters, if there is any. + + +
public(friend) fun on_new_epoch(framework: &signer)
+
+ + + +
+Implementation + + +
public(friend) fun on_new_epoch(
+    framework: &signer
+) acquires BanRegistryParameters, BanRegistryParametersV0 {
+    system_addresses::assert_supra_framework(framework);
+    if (config_buffer::does_exist<BanRegistryParameters>()) {
+        let new_config = config_buffer::extract_v2<BanRegistryParameters>();
+        if (exists<BanRegistryParameters>(@supra_framework)) {
+            *borrow_global_mut<BanRegistryParameters>(@supra_framework) = new_config;
+        } else {
+            move_to(framework, new_config);
+        };
+        let params = borrow_global<BanRegistryParameters>(@supra_framework);
+        if (params.version == 0) {
+            let v0 = deserialise_v0_params(params.config);
+            // This is to prevent abort on new epoch if deserialise failed.
+            if (option::is_some(&v0)) {
+                let ban_registry_params = option::extract(&mut v0);
+                if (exists<BanRegistryParametersV0>(@supra_framework)) {
+                    *borrow_global_mut<BanRegistryParametersV0>(@supra_framework) = ban_registry_params;
+                } else {
+                    move_to(framework, ban_registry_params);
+                }
+            }
+        }
+        // later version can be assigned here
+    }
+}
+
+ + + +
+ + + +## Function `get_ban_registry_params` + + + +
#[view]
+public fun get_ban_registry_params(): (vector<u8>, u8)
+
+ + + +
+Implementation + + +
public fun get_ban_registry_params(): (vector<u8>, u8) acquires BanRegistryParameters {
+    if (exists<BanRegistryParameters>(@supra_framework)) {
+        let ban_registry_config =
+            borrow_global<BanRegistryParameters>(@supra_framework);
+        return (ban_registry_config.config, ban_registry_config.version)
+    };
+    (vector::empty(), 0)
+}
+
+ + + +
+ + + +## Function `get_ban_registry_params_v0` + + + +
#[view]
+public fun get_ban_registry_params_v0(): (u8, u32, u8, u8)
+
+ + + +
+Implementation + + +
public fun get_ban_registry_params_v0(): (u8, u32, u8, u8) acquires BanRegistryParameters, BanRegistryParametersV0 {
+    if (exists<BanRegistryParameters>(@supra_framework)) {
+        let ban_registry_config =
+            borrow_global<BanRegistryParameters>(@supra_framework);
+        if (ban_registry_config.version == 0) {
+            let ban_registry_params =
+                borrow_global<BanRegistryParametersV0>(@supra_framework);
+            return (
+                ban_registry_params.initial_elections_denied,
+                ban_registry_params.max_elections_denied,
+                ban_registry_params.minimum_unbanned_proposers,
+                ban_registry_params.probation_elections
+            )
+        }
+    };
+    (0, 0, 0, 0)
+}
+
+ + + +
+ + + +## Function `get_initial_elections_denied` + +Provide initial election denied value + + +
public fun get_initial_elections_denied(): u8
+
+ + + +
+Implementation + + +
public fun get_initial_elections_denied(): u8 acquires BanRegistryParameters, BanRegistryParametersV0 {
+    if (exists<BanRegistryParameters>(@supra_framework)) {
+        let ban_registry_config =
+            borrow_global<BanRegistryParameters>(@supra_framework);
+        if (ban_registry_config.version == 0) {
+            let ban_registry_params =
+                borrow_global<BanRegistryParametersV0>(@supra_framework);
+            return ban_registry_params.initial_elections_denied
+        }
+    };
+    0
+}
+
+ + + +
+ + + +## Function `get_max_elections_denied` + +Provide max election denied value + + +
public fun get_max_elections_denied(): u32
+
+ + + +
+Implementation + + +
public fun get_max_elections_denied(): u32 acquires BanRegistryParameters, BanRegistryParametersV0 {
+    if (exists<BanRegistryParameters>(@supra_framework)) {
+        let ban_registry_config =
+            borrow_global<BanRegistryParameters>(@supra_framework);
+        if (ban_registry_config.version == 0) {
+            let ban_registry_params =
+                borrow_global<BanRegistryParametersV0>(@supra_framework);
+            return ban_registry_params.max_elections_denied
+        }
+    };
+    0
+}
+
+ + + +
+ + + +## Function `get_minimum_unbanned_proposers` + +Provide minimum unbanned proposers value + + +
public fun get_minimum_unbanned_proposers(): u8
+
+ + + +
+Implementation + + +
public fun get_minimum_unbanned_proposers(): u8 acquires BanRegistryParameters, BanRegistryParametersV0 {
+    if (exists<BanRegistryParameters>(@supra_framework)) {
+        let ban_registry_config =
+            borrow_global<BanRegistryParameters>(@supra_framework);
+        if (ban_registry_config.version == 0) {
+            let ban_registry_params =
+                borrow_global<BanRegistryParametersV0>(@supra_framework);
+            return ban_registry_params.minimum_unbanned_proposers
+        }
+    };
+    0
+}
+
+ + + +
+ + + +## Function `get_probation_elections` + +Provide probation elections value + + +
public fun get_probation_elections(): u8
+
+ + + +
+Implementation + + +
public fun get_probation_elections(): u8 acquires BanRegistryParameters, BanRegistryParametersV0 {
+    if (exists<BanRegistryParameters>(@supra_framework)) {
+        let ban_registry_config =
+            borrow_global<BanRegistryParameters>(@supra_framework);
+        if (ban_registry_config.version == 0) {
+            let ban_registry_params =
+                borrow_global<BanRegistryParametersV0>(@supra_framework);
+            return ban_registry_params.probation_elections
+        }
+    };
+    0
+}
+
+ + + +
+ + + +## Function `deserialise_v0_params` + +Decoding bytes to BanRegistryParametersV0 using bcs + + +
fun deserialise_v0_params(bytes: vector<u8>): option::Option<leader_ban_registry_config::BanRegistryParametersV0>
+
+ + + +
+Implementation + + +
fun deserialise_v0_params(bytes: vector<u8>): Option<BanRegistryParametersV0> {
+    let bcs_bytes = decode_bcs::new(bytes);
+    let initial_elections_denied: u8 = decode_bcs::peel_u8(&mut bcs_bytes);
+    let max_elections_denied: u32 = decode_bcs::peel_u32(&mut bcs_bytes);
+    let minimum_unbanned_proposers: u8 = decode_bcs::peel_u8(&mut bcs_bytes);
+    let probation_elections: u8 = decode_bcs::peel_u8(&mut bcs_bytes);
+    // making sure no bytes left to decode means correct parameter version
+    if (vector::length(&decode_bcs::into_remainder_bytes(bcs_bytes)) == 0) {
+        return option::some(
+            BanRegistryParametersV0 {
+                initial_elections_denied,
+                max_elections_denied,
+                minimum_unbanned_proposers,
+                probation_elections
+            }
+        )
+    };
+    option::none<BanRegistryParametersV0>()
+}
+
+ + + +
+ + +[move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/supra-framework/doc/multisig_voting.md b/aptos-move/framework/supra-framework/doc/multisig_voting.md index 313d6cd509d..f222d783c16 100644 --- a/aptos-move/framework/supra-framework/doc/multisig_voting.md +++ b/aptos-move/framework/supra-framework/doc/multisig_voting.md @@ -1557,7 +1557,11 @@ Return the state of the proposal with given id. ): u64 acquires VotingForum { if (is_voting_closed<ProposalType>(voting_forum_address, proposal_id)) { let proposal = get_proposal<ProposalType>(voting_forum_address, proposal_id); - if (proposal.yes_votes >= proposal.min_vote_threshold) { + let yes_votes = proposal.yes_votes; + let no_votes = proposal.no_votes; + + if (yes_votes > no_votes && + yes_votes + no_votes >= proposal.min_vote_threshold) { PROPOSAL_STATE_SUCCEEDED } else { PROPOSAL_STATE_FAILED diff --git a/aptos-move/framework/supra-framework/doc/overview.md b/aptos-move/framework/supra-framework/doc/overview.md index 2d7a5480b67..fadf4d0fb69 100644 --- a/aptos-move/framework/supra-framework/doc/overview.md +++ b/aptos-move/framework/supra-framework/doc/overview.md @@ -33,8 +33,11 @@ This is the reference documentation of the Supra framework. - [`0x1::create_signer`](create_signer.md#0x1_create_signer) - [`0x1::dispatchable_fungible_asset`](dispatchable_fungible_asset.md#0x1_dispatchable_fungible_asset) - [`0x1::dkg`](dkg.md#0x1_dkg) +- [`0x1::dkg_committee`](dkg_committee.md#0x1_dkg_committee) +- [`0x1::dkg_config`](dkg_config.md#0x1_dkg_config) - [`0x1::ethereum_derivable_account`](ethereum_derivable_account.md#0x1_ethereum_derivable_account) - [`0x1::event`](event.md#0x1_event) +- [`0x1::evm_config`](evm_config.md#0x1_evm_config) - [`0x1::evm_genesis_config`](evm_genesis_config.md#0x1_evm_genesis_config) - [`0x1::execution_config`](execution_config.md#0x1_execution_config) - [`0x1::function_info`](function_info.md#0x1_function_info) @@ -46,6 +49,8 @@ This is the reference documentation of the Supra framework. - [`0x1::jwk_consensus_config`](jwk_consensus_config.md#0x1_jwk_consensus_config) - [`0x1::jwks`](jwks.md#0x1_jwks) - [`0x1::keyless_account`](keyless_account.md#0x1_keyless_account) +- [`0x1::leader_ban_registry`](leader_ban_registry.md#0x1_leader_ban_registry) +- [`0x1::leader_ban_registry_config`](leader_ban_registry_config.md#0x1_leader_ban_registry_config) - [`0x1::managed_coin`](managed_coin.md#0x1_managed_coin) - [`0x1::multisig_account`](multisig_account.md#0x1_multisig_account) - [`0x1::multisig_voting`](multisig_voting.md#0x1_multisig_voting) @@ -77,6 +82,7 @@ This is the reference documentation of the Supra framework. - [`0x1::supra_account`](supra_account.md#0x1_supra_account) - [`0x1::supra_coin`](supra_coin.md#0x1_supra_coin) - [`0x1::supra_config`](supra_config.md#0x1_supra_config) +- [`0x1::supra_dkg`](supra_dkg.md#0x1_supra_dkg) - [`0x1::supra_governance`](supra_governance.md#0x1_supra_governance) - [`0x1::system_addresses`](system_addresses.md#0x1_system_addresses) - [`0x1::timestamp`](timestamp.md#0x1_timestamp) @@ -85,6 +91,7 @@ This is the reference documentation of the Supra framework. - [`0x1::transaction_validation`](transaction_validation.md#0x1_transaction_validation) - [`0x1::util`](util.md#0x1_util) - [`0x1::validator_consensus_info`](validator_consensus_info.md#0x1_validator_consensus_info) +- [`0x1::validator_public_keys`](validator_public_keys.md#0x1_validator_public_keys) - [`0x1::version`](version.md#0x1_version) - [`0x1::vesting`](vesting.md#0x1_vesting) - [`0x1::vesting_without_staking`](vesting_without_staking.md#0x1_vesting_without_staking) diff --git a/aptos-move/framework/supra-framework/doc/pbo_delegation_pool.md b/aptos-move/framework/supra-framework/doc/pbo_delegation_pool.md index 61cad7d2ead..43ee7360912 100644 --- a/aptos-move/framework/supra-framework/doc/pbo_delegation_pool.md +++ b/aptos-move/framework/supra-framework/doc/pbo_delegation_pool.md @@ -163,6 +163,7 @@ transferred to A - [Function `initialize_delegation_pool_with_amount_without_multisig_admin`](#0x1_pbo_delegation_pool_initialize_delegation_pool_with_amount_without_multisig_admin) - [Function `get_unlock_schedule`](#0x1_pbo_delegation_pool_get_unlock_schedule) - [Function `create_schedule_fractions`](#0x1_pbo_delegation_pool_create_schedule_fractions) +- [Function `update_unlocking_schedule_unchecked`](#0x1_pbo_delegation_pool_update_unlocking_schedule_unchecked) - [Function `update_unlocking_schedule`](#0x1_pbo_delegation_pool_update_unlocking_schedule) - [Function `validate_unlock_schedule_params`](#0x1_pbo_delegation_pool_validate_unlock_schedule_params) - [Function `initialize_delegation_pool`](#0x1_pbo_delegation_pool_initialize_delegation_pool) @@ -203,6 +204,7 @@ transferred to A - [Function `replace_in_smart_tables`](#0x1_pbo_delegation_pool_replace_in_smart_tables) - [Function `authorized_reactivate_stake`](#0x1_pbo_delegation_pool_authorized_reactivate_stake) - [Function `admin_withdraw`](#0x1_pbo_delegation_pool_admin_withdraw) +- [Function `admin_increase_last_unlock_period`](#0x1_pbo_delegation_pool_admin_increase_last_unlock_period) - [Function `lock_delegators_stakes`](#0x1_pbo_delegation_pool_lock_delegators_stakes) - [Function `replace_delegator`](#0x1_pbo_delegation_pool_replace_delegator) - [Function `is_principle_stakeholder`](#0x1_pbo_delegation_pool_is_principle_stakeholder) @@ -241,6 +243,7 @@ transferred to A use 0x1::features; use 0x1::fixed_point64; use 0x1::math128; +use 0x1::math64; use 0x1::multisig_account; use 0x1::option; use 0x1::pool_u64_unbound; @@ -1589,6 +1592,16 @@ amount of stake available in the specified stake pool. + + +Can not increase last unlock period if not at the last element of schedule + + +
const EINVALID_STATE_FOR_OPERATION: u64 = 42;
+
+ + + Minimum amount of coins to be unlocked. @@ -1720,6 +1733,7 @@ Commission percentage change is too late in this lockup period, and should be do +Unlocking has already started, so unlock schedule can not be updated
const EUNLOCKING_ALREADY_STARTED: u64 = 41;
@@ -1911,8 +1925,9 @@ Return whether a delegation pool has already enabled partial govnernance voting.
 
 
 
public fun partial_governance_voting_enabled(pool_address: address): bool {
-    exists<GovernanceRecords>(pool_address)
-        && stake::get_delegated_voter(pool_address) == pool_address
+    exists<GovernanceRecords>(pool_address) && stake::get_delegated_voter(
+        pool_address
+    ) == pool_address
 }
 
@@ -1967,9 +1982,8 @@ Return whether the commission percentage for the next lockup cycle is effective.
public fun is_next_commission_percentage_effective(
     pool_address: address
 ): bool acquires NextCommissionPercentage {
-    exists<NextCommissionPercentage>(pool_address)
-        && timestamp::now_seconds()
-            >= borrow_global<NextCommissionPercentage>(pool_address).effective_after_secs
+    exists<NextCommissionPercentage>(pool_address) && timestamp::now_seconds() >= borrow_global<
+        NextCommissionPercentage>(pool_address).effective_after_secs
 }
 
@@ -1994,9 +2008,7 @@ Return the operator commission percentage set on the delegation pool pool_ Implementation -
public fun operator_commission_percentage(
-    pool_address: address
-): u64 acquires DelegationPool, NextCommissionPercentage {
+
public fun operator_commission_percentage(pool_address: address): u64 acquires DelegationPool, NextCommissionPercentage {
     assert_delegation_pool_exists(pool_address);
     if (is_next_commission_percentage_effective(pool_address)) {
         operator_commission_percentage_next_lockup_cycle(pool_address)
@@ -2063,7 +2075,7 @@ Return the number of delegators owning active stake within pool_addresspublic fun shareholders_count_active_pool(pool_address: address): u64 acquires DelegationPool {
     assert_delegation_pool_exists(pool_address);
     pool_u64::shareholders_count(
-        &borrow_global<DelegationPool>(pool_address).active_shares
+        &borrow_global<DelegationPool>(pool_address).active_shares,
     )
 }
 
@@ -2123,11 +2135,13 @@ some stake and the stake pool's lockup cycle has not ended, their coins are not ): (bool, u64) acquires DelegationPool { assert_delegation_pool_exists(pool_address); let pool = borrow_global<DelegationPool>(pool_address); - let (lockup_cycle_ended, _, pending_inactive, _, commission_pending_inactive) = - calculate_stake_pool_drift(pool); + let (lockup_cycle_ended, _, pending_inactive, _, commission_pending_inactive) = calculate_stake_pool_drift( + pool + ); - let (withdrawal_exists, withdrawal_olc) = - pending_withdrawal_exists(pool, delegator_address); + let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists( + pool, delegator_address + ); if (!withdrawal_exists) { // if no pending withdrawal, there is neither inactive nor pending_inactive stake (false, 0) @@ -2142,7 +2156,7 @@ some stake and the stake pool's lockup cycle has not ended, their coins are not inactive_shares, pool_u64::shares(inactive_shares, delegator_address), // exclude operator pending_inactive rewards not converted to shares yet - pending_inactive - commission_pending_inactive + pending_inactive - commission_pending_inactive, ); // if withdrawal's lockup cycle ended ONLY on stake pool then it is also inactive (lockup_cycle_ended, pending_inactive) @@ -2179,19 +2193,20 @@ in each of its individual states: (active,inactive,assert_delegation_pool_exists(pool_address); let pool = borrow_global<DelegationPool>(pool_address); let (lockup_cycle_ended, active, _, commission_active, commission_pending_inactive) = - - calculate_stake_pool_drift(pool); + calculate_stake_pool_drift(pool); let total_active_shares = pool_u64::total_shares(&pool.active_shares); - let delegator_active_shares = - pool_u64::shares(&pool.active_shares, delegator_address); + let delegator_active_shares = pool_u64::shares( + &pool.active_shares, delegator_address + ); let (_, _, pending_active, _) = stake::get_stake(pool_address); if (pending_active == 0) { // zero `pending_active` stake indicates that either there are no `add_stake` fees or // previous epoch has ended and should identify shares owning these fees as released - total_active_shares = total_active_shares - - pool_u64::shares(&pool.active_shares, NULL_SHAREHOLDER); + total_active_shares = total_active_shares - pool_u64::shares( + &pool.active_shares, NULL_SHAREHOLDER + ); if (delegator_address == NULL_SHAREHOLDER) { delegator_active_shares = 0 } @@ -2201,16 +2216,16 @@ in each of its individual states: (active,inactive,to shares yet active - commission_active, - total_active_shares + total_active_shares, ); // get state and stake (0 if there is none) of the pending withdrawal - let (withdrawal_inactive, withdrawal_stake) = - get_pending_withdrawal(pool_address, delegator_address); + let (withdrawal_inactive, withdrawal_stake) = get_pending_withdrawal( + pool_address, delegator_address + ); // report non-active stakes accordingly to the state of the pending withdrawal let (inactive, pending_inactive) = - if (withdrawal_inactive) (withdrawal_stake, 0) - else (0, withdrawal_stake); + if (withdrawal_inactive) (withdrawal_stake, 0) else (0, withdrawal_stake); // should also include commission rewards in case of the operator account // operator rewards are actually used to buy shares which is introducing @@ -2258,21 +2273,24 @@ extracted-fee = (amount - extracted-fee) * reward-rate% * (100% - operator-commi Implementation -
public fun get_add_stake_fee(
-    pool_address: address, amount: u64
-): u64 acquires DelegationPool, NextCommissionPercentage {
+
public fun get_add_stake_fee(pool_address: address, amount: u64): u64 acquires DelegationPool, NextCommissionPercentage {
     if (stake::is_current_epoch_validator(pool_address)) {
-        let (rewards_rate, rewards_rate_denominator) =
-            staking_config::get_reward_rate(&staking_config::get());
+        let (rewards_rate, rewards_rate_denominator) = staking_config::get_reward_rate(
+            &staking_config::get()
+        );
         if (rewards_rate_denominator != 0) {
             assert_delegation_pool_exists(pool_address);
 
-            rewards_rate = rewards_rate
-                * (MAX_FEE - operator_commission_percentage(pool_address));
+            rewards_rate = rewards_rate * (
+                MAX_FEE - operator_commission_percentage(pool_address)
+            );
             rewards_rate_denominator = rewards_rate_denominator * MAX_FEE;
             (
-                (((amount as u128) * (rewards_rate as u128))
-                    / ((rewards_rate as u128) + (rewards_rate_denominator as u128))) as u64
+                (
+                    ((amount as u128) * (rewards_rate as u128)) / (
+                        (rewards_rate as u128) + (rewards_rate_denominator as u128)
+                    )
+                ) as u64
             )
         } else { 0 }
     } else { 0 }
@@ -2303,8 +2321,8 @@ the validator had gone inactive before its lockup expired.
 
 
 
public fun can_withdraw_pending_inactive(pool_address: address): bool {
-    stake::get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE
-        && timestamp::now_seconds() >= stake::get_lockup_secs(pool_address)
+    stake::get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE && timestamp::now_seconds()
+        >= stake::get_lockup_secs(pool_address)
 }
 
@@ -2339,8 +2357,9 @@ latest state. synchronize_delegation_pool(pool_address); let pool = borrow_global<DelegationPool>(pool_address); let governance_records = borrow_global_mut<GovernanceRecords>(pool_address); - let latest_delegated_votes = - update_and_borrow_mut_delegated_votes(pool, governance_records, voter); + let latest_delegated_votes = update_and_borrow_mut_delegated_votes( + pool, governance_records, voter + ); calculate_total_voting_power(pool, latest_delegated_votes) }
@@ -2374,7 +2393,7 @@ latest state. calculate_and_update_delegator_voter_internal( borrow_global<DelegationPool>(pool_address), borrow_global_mut<GovernanceRecords>(pool_address), - delegator_address + delegator_address, ) }
@@ -2470,7 +2489,7 @@ Initialize a delegation pool without actual coin but withdraw from the owner's a ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { assert!( coin::balance<SupraCoin>(signer::address_of(owner)) >= amount, - error::invalid_argument(EBALANCE_NOT_SUFFICIENT) + error::invalid_argument(EBALANCE_NOT_SUFFICIENT), ); let coin = coin::withdraw<SupraCoin>(owner, amount); @@ -2485,7 +2504,7 @@ Initialize a delegation pool without actual coin but withdraw from the owner's a unlock_numerators, unlock_denominator, unlock_start_time, - unlock_duration + unlock_duration, ) }
@@ -2524,7 +2543,7 @@ Initialize a delegation pool without actual coin but withdraw from the owner's a ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { assert!( coin::balance<SupraCoin>(signer::address_of(owner)) >= amount, - error::invalid_argument(EBALANCE_NOT_SUFFICIENT) + error::invalid_argument(EBALANCE_NOT_SUFFICIENT), ); let coin = coin::withdraw<SupraCoin>(owner, amount); @@ -2539,7 +2558,7 @@ Initialize a delegation pool without actual coin but withdraw from the owner's a unlock_numerators, unlock_denominator, unlock_start_time, - unlock_duration + unlock_duration, ) }
@@ -2565,11 +2584,11 @@ Return the unlock schedule of the pool as (schedule, start_time, period_duration Implementation -
public fun get_unlock_schedule(
-    pool_address: address
-): (vector<FixedPoint64>, u64, u64, u64, FixedPoint64) acquires DelegationPool {
-    let uschedule =
-        borrow_global<DelegationPool>(pool_address).principle_unlock_schedule;
+
public fun get_unlock_schedule(pool_address: address)
+    : (
+    vector<FixedPoint64>, u64, u64, u64, FixedPoint64
+) acquires DelegationPool {
+    let uschedule = borrow_global<DelegationPool>(pool_address).principle_unlock_schedule;
     (
         uschedule.schedule,
         uschedule.start_timestamp_secs,
@@ -2600,19 +2619,21 @@ Return the unlock schedule of the pool as (schedule, start_time, period_duration
 Implementation
 
 
-
fun create_schedule_fractions(unlock_numerators: &vector<u64>, unlock_denominator: u64) : vector<FixedPoint64> {
+
fun create_schedule_fractions(
+    unlock_numerators: &vector<u64>, unlock_denominator: u64
+): vector<FixedPoint64> {
 
-//Create unlock schedule
+    //Create unlock schedule
     let schedule = vector::empty();
     vector::for_each_ref(
         unlock_numerators,
         |e| {
-            let fraction =
-                fixed_point64::create_from_rational(
-                    (*e as u128), (unlock_denominator as u128)
-                );
+            let fraction = fixed_point64::create_from_rational(
+                (*e as u128),
+                (unlock_denominator as u128),
+            );
             vector::push_back(&mut schedule, fraction);
-        }
+        },
     );
 
     schedule
@@ -2622,6 +2643,70 @@ Return the unlock schedule of the pool as (schedule, start_time, period_duration
 
 
 
+
+
+
+
+## Function `update_unlocking_schedule_unchecked`
+
+
+
+
public entry fun update_unlocking_schedule_unchecked(multisig_admin: &signer, pool_address: address, unlock_numerators: vector<u64>, unlock_denominator: u64, unlock_start_time: u64, unlock_duration: u64, last_unlock_period: u64)
+
+ + + +
+Implementation + + +
public entry fun update_unlocking_schedule_unchecked(
+    multisig_admin: &signer,
+    pool_address: address,
+    unlock_numerators: vector<u64>,
+    unlock_denominator: u64,
+    unlock_start_time: u64,
+    unlock_duration: u64,
+    last_unlock_period: u64
+) acquires DelegationPool {
+    assert!(
+        is_admin(signer::address_of(multisig_admin), pool_address),
+        error::permission_denied(ENOT_AUTHORIZED),
+    );
+    let pool = borrow_global_mut<DelegationPool>(pool_address);
+
+    validate_unlock_schedule_params(
+        &unlock_numerators,
+        unlock_denominator,
+        unlock_start_time,
+        unlock_duration,
+    );
+
+    //Create unlock schedule fractions
+    let schedule = create_schedule_fractions(&unlock_numerators, unlock_denominator);
+
+    pool.principle_unlock_schedule = UnlockSchedule {
+        schedule: schedule,
+        start_timestamp_secs: unlock_start_time,
+        period_duration: unlock_duration,
+        last_unlock_period: last_unlock_period,
+        cumulative_unlocked_fraction: pool.principle_unlock_schedule.cumulative_unlocked_fraction
+    };
+    event::emit(
+        UnlockScheduleUpdated {
+            pool_address,
+            unlock_numerators,
+            unlock_denominator,
+            unlock_start_time,
+            unlock_duration
+        },
+    );
+
+}
+
+ + +
@@ -2655,25 +2740,25 @@ before external validators are allowed to join the validator set. ) acquires DelegationPool { assert!( is_admin(signer::address_of(multisig_admin), pool_address), - error::permission_denied(ENOT_AUTHORIZED) + error::permission_denied(ENOT_AUTHORIZED), ); let pool = borrow_global_mut<DelegationPool>(pool_address); assert!( fixed_point64::is_zero( pool.principle_unlock_schedule.cumulative_unlocked_fraction ), - error::invalid_state(EUNLOCKING_ALREADY_STARTED) + error::invalid_state(EUNLOCKING_ALREADY_STARTED), ); validate_unlock_schedule_params( &unlock_numerators, unlock_denominator, unlock_start_time, - unlock_duration + unlock_duration, ); //Create unlock schedule fractions - let schedule = create_schedule_fractions(&unlock_numerators,unlock_denominator); + let schedule = create_schedule_fractions(&unlock_numerators, unlock_denominator); pool.principle_unlock_schedule = UnlockSchedule { schedule: schedule, @@ -2689,7 +2774,7 @@ before external validators are allowed to join the validator set. unlock_denominator, unlock_start_time, unlock_duration - } + }, ); } @@ -2728,23 +2813,23 @@ before external validators are allowed to join the validator set. //Fraction numerators can not be empty assert!( numerator_length != 0, - error::invalid_argument(EEMPTY_UNLOCK_SCHEDULE) + error::invalid_argument(EEMPTY_UNLOCK_SCHEDULE), ); //First and last numerator can not be zero assert!( *vector::borrow(unlock_numerators, 0) != 0, - error::invalid_argument(ESCHEDULE_WITH_ZERO_FRACTION) + error::invalid_argument(ESCHEDULE_WITH_ZERO_FRACTION), ); assert!( *vector::borrow(unlock_numerators, numerator_length - 1) != 0, - error::invalid_argument(ESCHEDULE_WITH_ZERO_FRACTION) + error::invalid_argument(ESCHEDULE_WITH_ZERO_FRACTION), ); let sum = vector::foldr(*unlock_numerators, 0, |e, a| { e + a }); //Sum of numerators can not be greater than denominators assert!( sum <= unlock_denominator, - error::invalid_argument(ENUMERATORS_GRATER_THAN_DENOMINATOR) + error::invalid_argument(ENUMERATORS_GRATER_THAN_DENOMINATOR), ); } @@ -2793,53 +2878,53 @@ Ownership over setting the operator/voter is granted to owner who h let ms_admin = option::get_with_default<address>(&multisig_admin, @0x0); assert!( ms_admin != @0x0, - error::invalid_argument(EADMIN_ADDRESS_CANNOT_BE_ZERO) + error::invalid_argument(EADMIN_ADDRESS_CANNOT_BE_ZERO), ); assert!( multisig_account::num_signatures_required(ms_admin) >= 2, - EADMIN_NOT_MULTISIG + EADMIN_NOT_MULTISIG, ); }; // fail if the length of delegator_address and principle_stake is not the same assert!( vector::length(&delegator_address) == vector::length(&principle_stake), - error::invalid_argument(EVECTOR_LENGTH_NOT_SAME) + error::invalid_argument(EVECTOR_LENGTH_NOT_SAME), ); //Delegation pool must be enabled assert!( features::delegation_pools_enabled(), - error::invalid_state(EDELEGATION_POOLS_DISABLED) + error::invalid_state(EDELEGATION_POOLS_DISABLED), ); - validate_unlock_schedule_params( &unlock_numerators, unlock_denominator, unlock_start_time, - unlock_duration + unlock_duration, ); let owner_address = signer::address_of(owner); assert!( !owner_cap_exists(owner_address), - error::already_exists(EOWNER_CAP_ALREADY_EXISTS) + error::already_exists(EOWNER_CAP_ALREADY_EXISTS), ); assert!( operator_commission_percentage <= MAX_FEE, - error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE) + error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE), ); let sum = vector::fold(principle_stake, 0, |a, e| { a + e }); // fail if the value of coin and the sum of principle_stake is not the same assert!( coin::value(&coin) == sum, - error::invalid_state(ECOIN_VALUE_NOT_SAME_AS_PRINCIPAL_STAKE) + error::invalid_state(ECOIN_VALUE_NOT_SAME_AS_PRINCIPAL_STAKE), ); // generate a seed to be used to create the resource account hosting the delegation pool let seed = create_resource_account_seed(delegation_pool_creation_seed); - let (stake_pool_signer, stake_pool_signer_cap) = - account::create_resource_account(owner, seed); + let (stake_pool_signer, stake_pool_signer_cap) = account::create_resource_account( + owner, seed + ); coin::register<SupraCoin>(&stake_pool_signer); // stake_pool_signer will be owner of the stake pool and have its `stake::OwnerCapability` @@ -2848,7 +2933,7 @@ Ownership over setting the operator/voter is granted to owner who h &stake_pool_signer, 0, owner_address, - owner_address + owner_address, ); coin::deposit(pool_address, coin); @@ -2856,7 +2941,7 @@ Ownership over setting the operator/voter is granted to owner who h table::add( &mut inactive_shares, olc_with_index(0), - pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR) + pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR), ); let delegator_address_copy = copy delegator_address; @@ -2871,7 +2956,7 @@ Ownership over setting the operator/voter is granted to owner who h }; //Create unlock schedule - let schedule = create_schedule_fractions(&unlock_numerators,unlock_denominator); + let schedule = create_schedule_fractions(&unlock_numerators, unlock_denominator); move_to( &stake_pool_signer, @@ -2908,7 +2993,7 @@ Ownership over setting the operator/voter is granted to owner who h ), distribute_commission_events: account::new_event_handle< DistributeCommissionEvent>(&stake_pool_signer) - } + }, ); // save delegation pool ownership and resource account address (inner stake pool address) on `owner` @@ -2923,15 +3008,13 @@ Ownership over setting the operator/voter is granted to owner who h let (active_stake, _, _, _) = stake::get_stake(pool_address); // fail if coin in StakePool.active does not match with the balance in active_shares pool. assert!( - active_stake - == pool_u64::total_coins( - &borrow_global<DelegationPool>(pool_address).active_shares - ), - error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL) + active_stake == pool_u64::total_coins( + &borrow_global<DelegationPool>(pool_address).active_shares, + ), + error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL), ); // All delegation pool enable partial governace voting by default once the feature flag is enabled. - if (features::partial_governance_voting_enabled() - && features::delegation_pool_partial_governance_voting_enabled()) { + if (features::partial_governance_voting_enabled() && features::delegation_pool_partial_governance_voting_enabled()) { enable_partial_governance_voting(pool_address); } } @@ -2965,11 +3048,12 @@ Ownership over setting the operator/voter is granted to owner who h { assert!( is_admin(signer::address_of(funder), pool_address), - error::permission_denied(ENOT_AUTHORIZED) + error::permission_denied(ENOT_AUTHORIZED), ); }; - let principle_stake_table = - &mut (borrow_global_mut<DelegationPool>(pool_address).principle_stake); + let principle_stake_table = &mut ( + borrow_global_mut<DelegationPool>(pool_address).principle_stake + ); vector::zip_reverse( delegators, @@ -2980,8 +3064,9 @@ Ownership over setting the operator/voter is granted to owner who h // Compute the actual stake that would be added, `principle_stake` has to be // populated in the table accordingly if (table::contains(principle_stake_table, delegator)) { - let stake_amount = - table::borrow_mut(principle_stake_table, delegator); + let stake_amount = table::borrow_mut( + principle_stake_table, delegator + ); *stake_amount = *stake_amount + stake; } else { table::add(principle_stake_table, delegator, stake); @@ -2993,7 +3078,7 @@ Ownership over setting the operator/voter is granted to owner who h UnlockScheduleApplied { pool_address, delegator, amount: stake } ); } - } + }, ); fund_delegators_with_stake(funder, pool_address, delegators, stakes); @@ -3031,7 +3116,7 @@ Ownership over setting the operator/voter is granted to owner who h stakes, |delegator, stake| { fund_delegator_stake(funder, pool_address, delegator, stake); - } + }, ); }
@@ -3115,9 +3200,7 @@ Return the beneficiary address of the operator.
public fun beneficiary_for_operator(operator: address): address acquires BeneficiaryForOperator {
     if (exists<BeneficiaryForOperator>(operator)) {
         return borrow_global<BeneficiaryForOperator>(operator).beneficiary_for_operator
-    } else {
-        operator
-    }
+    } else { operator }
 }
 
@@ -3147,11 +3230,11 @@ THe existing voter will be replaced. The function is permissionless. ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { assert!( features::partial_governance_voting_enabled(), - error::invalid_state(EDISABLED_FUNCTION) + error::invalid_state(EDISABLED_FUNCTION), ); assert!( features::delegation_pool_partial_governance_voting_enabled(), - error::invalid_state(EDISABLED_FUNCTION) + error::invalid_state(EDISABLED_FUNCTION), ); assert_delegation_pool_exists(pool_address); // synchronize delegation and stake pools before any user operation. @@ -3178,7 +3261,7 @@ THe existing voter will be replaced. The function is permissionless. ), delegate_voting_power_events: account::new_event_handle< DelegateVotingPowerEvent>(&stake_pool_signer) - } + }, ); }
@@ -3229,7 +3312,7 @@ THe existing voter will be replaced. The function is permissionless.
fun assert_delegation_pool_exists(pool_address: address) {
     assert!(
         delegation_pool_exists(pool_address),
-        error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST)
+        error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST),
     );
 }
 
@@ -3259,7 +3342,7 @@ THe existing voter will be replaced. The function is permissionless. let balance = pool_u64::balance(&pool.active_shares, delegator_address); assert!( balance >= MIN_COINS_ON_SHARES_POOL, - error::invalid_argument(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW) + error::invalid_argument(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW), ); }
@@ -3286,11 +3369,12 @@ THe existing voter will be replaced. The function is permissionless.
fun assert_min_pending_inactive_balance(
     pool: &DelegationPool, delegator_address: address
 ) {
-    let balance =
-        pool_u64::balance(pending_inactive_shares_pool(pool), delegator_address);
+    let balance = pool_u64::balance(
+        pending_inactive_shares_pool(pool), delegator_address
+    );
     assert!(
         balance >= MIN_COINS_ON_SHARES_POOL,
-        error::invalid_argument(EDELEGATOR_PENDING_INACTIVE_BALANCE_TOO_LOW)
+        error::invalid_argument(EDELEGATOR_PENDING_INACTIVE_BALANCE_TOO_LOW),
     );
 }
 
@@ -3318,7 +3402,7 @@ THe existing voter will be replaced. The function is permissionless. assert_delegation_pool_exists(pool_address); assert!( partial_governance_voting_enabled(pool_address), - error::invalid_state(EPARTIAL_GOVERNANCE_VOTING_NOT_ENABLED) + error::invalid_state(EPARTIAL_GOVERNANCE_VOTING_NOT_ENABLED), ); }
@@ -3346,11 +3430,10 @@ THe existing voter will be replaced. The function is permissionless. src_shares_pool: &pool_u64::Pool, shareholder: address, amount: u64 ): u64 { // find how many coins would be redeemed if supplying `amount` - let redeemed_coins = - pool_u64::shares_to_amount( - src_shares_pool, - amount_to_shares_to_redeem(src_shares_pool, shareholder, amount) - ); + let redeemed_coins = pool_u64::shares_to_amount( + src_shares_pool, + amount_to_shares_to_redeem(src_shares_pool, shareholder, amount), + ); // if balance drops under threshold then redeem it entirely let src_balance = pool_u64::balance(src_shares_pool, shareholder); if (src_balance - redeemed_coins < MIN_COINS_ON_SHARES_POOL) { @@ -3386,11 +3469,10 @@ THe existing voter will be replaced. The function is permissionless. amount: u64 ): u64 { // find how many coins would be redeemed from source if supplying `amount` - let redeemed_coins = - pool_u64::shares_to_amount( - src_shares_pool, - amount_to_shares_to_redeem(src_shares_pool, shareholder, amount) - ); + let redeemed_coins = pool_u64::shares_to_amount( + src_shares_pool, + amount_to_shares_to_redeem(src_shares_pool, shareholder, amount), + ); // if balance on destination would be less than threshold then redeem difference to threshold let dst_balance = pool_u64::balance(dst_shares_pool, shareholder); if (dst_balance + redeemed_coins < MIN_COINS_ON_SHARES_POOL) { @@ -3618,9 +3700,7 @@ Update VoteDelegation of a delegator to up-to-date then borrow_mut it.
fun update_and_borrow_mut_delegator_vote_delegation(
-    pool: &DelegationPool,
-    governance_records: &mut GovernanceRecords,
-    delegator: address
+    pool: &DelegationPool, governance_records: &mut GovernanceRecords, delegator: address
 ): &mut VoteDelegation {
     let pool_address = get_pool_address(pool);
     let locked_until_secs = stake::get_lockup_secs(pool_address);
@@ -3636,14 +3716,14 @@ Update VoteDelegation of a delegator to up-to-date then borrow_mut it.
                 voter: delegator,
                 last_locked_until_secs: locked_until_secs,
                 pending_voter: delegator
-            }
+            },
         )
     };
 
     let vote_delegation = smart_table::borrow_mut(vote_delegation_table, delegator);
     // A lockup period has passed since last time `vote_delegation` was updated. Pending voter takes effect.
-    if (vote_delegation.last_locked_until_secs < locked_until_secs
-        && vote_delegation.voter != vote_delegation.pending_voter) {
+    if (vote_delegation.last_locked_until_secs < locked_until_secs && vote_delegation.voter != vote_delegation
+        .pending_voter) {
         vote_delegation.voter = vote_delegation.pending_voter;
     };
     vote_delegation
@@ -3690,7 +3770,7 @@ Update DelegatedVotes of a voter to up-to-date then borrow_mut it.
                 pending_inactive_shares: inactive_shares,
                 active_shares_next_lockup: active_shares,
                 last_locked_until_secs: locked_until_secs
-            }
+            },
         )
     };
 
@@ -3753,15 +3833,13 @@ power, which equals to the sum of the coin amounts.
 
fun calculate_total_voting_power(
     delegation_pool: &DelegationPool, latest_delegated_votes: &DelegatedVotes
 ): u64 {
-    let active_amount =
-        pool_u64::shares_to_amount(
-            &delegation_pool.active_shares, latest_delegated_votes.active_shares
-        );
-    let pending_inactive_amount =
-        pool_u64::shares_to_amount(
-            pending_inactive_shares_pool(delegation_pool),
-            latest_delegated_votes.pending_inactive_shares
-        );
+    let active_amount = pool_u64::shares_to_amount(
+        &delegation_pool.active_shares, latest_delegated_votes.active_shares
+    );
+    let pending_inactive_amount = pool_u64::shares_to_amount(
+        pending_inactive_shares_pool(delegation_pool),
+        latest_delegated_votes.pending_inactive_shares,
+    );
     active_amount + pending_inactive_amount
 }
 
@@ -3787,14 +3865,11 @@ Update VoteDelegation of a delegator to up-to-date then return the latest voter.
fun calculate_and_update_delegator_voter_internal(
-    pool: &DelegationPool,
-    governance_records: &mut GovernanceRecords,
-    delegator: address
+    pool: &DelegationPool, governance_records: &mut GovernanceRecords, delegator: address
 ): address {
-    let vote_delegation =
-        update_and_borrow_mut_delegator_vote_delegation(
-            pool, governance_records, delegator
-        );
+    let vote_delegation = update_and_borrow_mut_delegator_vote_delegation(
+        pool, governance_records, delegator
+    );
     vote_delegation.voter
 }
 
@@ -3822,8 +3897,9 @@ Update DelegatedVotes of a voter to up-to-date then return the total voting powe
fun calculate_and_update_delegated_votes(
     pool: &DelegationPool, governance_records: &mut GovernanceRecords, voter: address
 ): u64 {
-    let delegated_votes =
-        update_and_borrow_mut_delegated_votes(pool, governance_records, voter);
+    let delegated_votes = update_and_borrow_mut_delegated_votes(
+        pool, governance_records, voter
+    );
     calculate_total_voting_power(pool, delegated_votes)
 }
 
@@ -3848,16 +3924,14 @@ Allows an owner to change the operator of the underlying stake pool. Implementation -
public entry fun set_operator(
-    owner: &signer, new_operator: address
-) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage {
+
public entry fun set_operator(owner: &signer, new_operator: address) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage {
     let pool_address = get_owned_pool_address(signer::address_of(owner));
     // synchronize delegation and stake pools before any user operation
     // ensure the old operator is paid its uncommitted commission rewards
     synchronize_delegation_pool(pool_address);
     stake::set_operator(
         &retrieve_stake_pool_owner(borrow_global<DelegationPool>(pool_address)),
-        new_operator
+        new_operator,
     );
 }
 
@@ -3890,7 +3964,7 @@ one for each pool. ) acquires BeneficiaryForOperator { assert!( features::operator_beneficiary_change_enabled(), - std::error::invalid_state(EOPERATOR_BENEFICIARY_CHANGE_NOT_SUPPORTED) + std::error::invalid_state(EOPERATOR_BENEFICIARY_CHANGE_NOT_SUPPORTED), ); // The beneficiay address of an operator is stored under the operator's address. // So, the operator does not need to be validated with respect to a staking pool. @@ -3898,11 +3972,11 @@ one for each pool. let old_beneficiary = beneficiary_for_operator(operator_addr); if (exists<BeneficiaryForOperator>(operator_addr)) { borrow_global_mut<BeneficiaryForOperator>(operator_addr).beneficiary_for_operator = - new_beneficiary; + new_beneficiary; } else { move_to( operator, - BeneficiaryForOperator { beneficiary_for_operator: new_beneficiary } + BeneficiaryForOperator { beneficiary_for_operator: new_beneficiary }, ); }; @@ -3911,7 +3985,7 @@ one for each pool. operator: operator_addr, old_beneficiary, new_beneficiary - } + }, ); }
@@ -3941,23 +4015,21 @@ Allows an owner to update the commission percentage for the operator of the unde ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { assert!( features::commission_change_delegation_pool_enabled(), - error::invalid_state(ECOMMISSION_RATE_CHANGE_NOT_SUPPORTED) + error::invalid_state(ECOMMISSION_RATE_CHANGE_NOT_SUPPORTED), ); assert!( new_commission_percentage <= MAX_FEE, - error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE) + error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE), ); let owner_address = signer::address_of(owner); let pool_address = get_owned_pool_address(owner_address); assert!( - operator_commission_percentage(pool_address) + MAX_COMMISSION_INCREASE - >= new_commission_percentage, - error::invalid_argument(ETOO_LARGE_COMMISSION_INCREASE) + operator_commission_percentage(pool_address) + MAX_COMMISSION_INCREASE >= new_commission_percentage, + error::invalid_argument(ETOO_LARGE_COMMISSION_INCREASE), ); assert!( - stake::get_remaining_lockup_secs(pool_address) - >= min_remaining_secs_for_commission_change(), - error::invalid_state(ETOO_LATE_COMMISSION_CHANGE) + stake::get_remaining_lockup_secs(pool_address) >= min_remaining_secs_for_commission_change(), + error::invalid_state(ETOO_LATE_COMMISSION_CHANGE), ); // synchronize delegation and stake pools before any user operation. this ensures: @@ -3966,24 +4038,24 @@ Allows an owner to update the commission percentage for the operator of the unde synchronize_delegation_pool(pool_address); if (exists<NextCommissionPercentage>(pool_address)) { - let commission_percentage = - borrow_global_mut<NextCommissionPercentage>(pool_address); + let commission_percentage = borrow_global_mut<NextCommissionPercentage>( + pool_address + ); commission_percentage.commission_percentage_next_lockup_cycle = new_commission_percentage; commission_percentage.effective_after_secs = stake::get_lockup_secs( pool_address ); } else { let delegation_pool = borrow_global<DelegationPool>(pool_address); - let pool_signer = - account::create_signer_with_capability( - &delegation_pool.stake_pool_signer_cap - ); + let pool_signer = account::create_signer_with_capability( + &delegation_pool.stake_pool_signer_cap + ); move_to( &pool_signer, NextCommissionPercentage { commission_percentage_next_lockup_cycle: new_commission_percentage, effective_after_secs: stake::get_lockup_secs(pool_address) - } + }, ); }; @@ -3992,7 +4064,7 @@ Allows an owner to update the commission percentage for the operator of the unde pool_address, owner: owner_address, commission_percentage_next_lockup_cycle: new_commission_percentage - } + }, ); }
@@ -4023,14 +4095,14 @@ Allows an owner to change the delegated voter of the underlying stake pool. // No one can change delegated_voter once the partial governance voting feature is enabled. assert!( !features::delegation_pool_partial_governance_voting_enabled(), - error::invalid_state(EDEPRECATED_FUNCTION) + error::invalid_state(EDEPRECATED_FUNCTION), ); let pool_address = get_owned_pool_address(signer::address_of(owner)); // synchronize delegation and stake pools before any user operation synchronize_delegation_pool(pool_address); stake::set_delegated_voter( &retrieve_stake_pool_owner(borrow_global<DelegationPool>(pool_address)), - new_voter + new_voter, ); }
@@ -4067,30 +4139,28 @@ this change won't take effects until the next lockup period. let delegator_address = signer::address_of(delegator); let delegation_pool = borrow_global<DelegationPool>(pool_address); let governance_records = borrow_global_mut<GovernanceRecords>(pool_address); - let delegator_vote_delegation = - update_and_borrow_mut_delegator_vote_delegation( - delegation_pool, governance_records, delegator_address - ); + let delegator_vote_delegation = update_and_borrow_mut_delegator_vote_delegation( + delegation_pool, governance_records, delegator_address + ); let pending_voter: address = delegator_vote_delegation.pending_voter; // No need to update if the voter doesn't really change. if (pending_voter != new_voter) { delegator_vote_delegation.pending_voter = new_voter; - let active_shares = - get_delegator_active_shares(delegation_pool, delegator_address); + let active_shares = get_delegator_active_shares( + delegation_pool, delegator_address + ); // <active shares> of <pending voter of shareholder> -= <active_shares> // <active shares> of <new voter of shareholder> += <active_shares> - let pending_delegated_votes = - update_and_borrow_mut_delegated_votes( - delegation_pool, governance_records, pending_voter - ); + let pending_delegated_votes = update_and_borrow_mut_delegated_votes( + delegation_pool, governance_records, pending_voter + ); pending_delegated_votes.active_shares_next_lockup = pending_delegated_votes.active_shares_next_lockup - active_shares; - let new_delegated_votes = - update_and_borrow_mut_delegated_votes( - delegation_pool, governance_records, new_voter - ); + let new_delegated_votes = update_and_borrow_mut_delegated_votes( + delegation_pool, governance_records, new_voter + ); new_delegated_votes.active_shares_next_lockup = new_delegated_votes.active_shares_next_lockup + active_shares; }; @@ -4101,7 +4171,7 @@ this change won't take effects until the next lockup period. pool_address, delegator: delegator_address, voter: new_voter - } + }, ); }
@@ -4171,7 +4241,7 @@ Add amount of coins to the delegation pool pool_addressMIN_COINS_ON_SHARES_POOL` assert!( amount >= MIN_COINS_ON_SHARES_POOL, - error::invalid_argument(EMINIMUM_UNLOCK_AMOUNT) + error::invalid_argument(EMINIMUM_UNLOCK_AMOUNT), ); // synchronize delegation and stake pools before any user operation synchronize_delegation_pool(pool_address); @@ -4202,7 +4272,7 @@ Add amount of coins to the delegation pool pool_addressamount
of coins to the delegation pool pool_addresssigner::address_of(delegator), - amount + amount, ) }
@@ -4309,7 +4379,7 @@ authorized to reactivate their own stake. // fail unlock of less than `MIN_COINS_ON_SHARES_POOL` assert!( amount >= MIN_COINS_ON_SHARES_POOL, - error::invalid_argument(EMINIMUM_UNLOCK_AMOUNT) + error::invalid_argument(EMINIMUM_UNLOCK_AMOUNT), ); // synchronize delegation and stake pools before any user operation synchronize_delegation_pool(pool_address); @@ -4320,7 +4390,7 @@ authorized to reactivate their own stake. pending_inactive_shares_pool(pool), &pool.active_shares, delegator, - amount + amount, ); let observed_lockup_cycle = pool.observed_lockup_cycle; amount = redeem_inactive_shares(pool, delegator, amount, observed_lockup_cycle); @@ -4336,7 +4406,7 @@ authorized to reactivate their own stake. pool_address, delegator_address: delegator, amount_reactivated: amount - } + }, ); }
@@ -4377,7 +4447,7 @@ validator-owners to prevent it from being abused. { assert!( is_admin(signer::address_of(multisig_admin), pool_address), - error::permission_denied(ENOT_AUTHORIZED) + error::permission_denied(ENOT_AUTHORIZED), ); }; assert!(amount != 0, error::invalid_argument(EWITHDRAW_ZERO_STAKE)); @@ -4385,8 +4455,54 @@ validator-owners to prevent it from being abused. borrow_global_mut<DelegationPool>(pool_address), delegator_address, amount, - signer::address_of(multisig_admin) + signer::address_of(multisig_admin), + ); +} +
+ + + + + + + +## Function `admin_increase_last_unlock_period` + + + +
public entry fun admin_increase_last_unlock_period(multisig_admin: &signer, pool_address: address, additional_periods: u64)
+
+ + + +
+Implementation + + +
public entry fun admin_increase_last_unlock_period(
+    multisig_admin: &signer, pool_address: address, additional_periods: u64
+) acquires DelegationPool {
+    // Ensure that the caller is the admin of the delegation pool.
+    {
+        assert!(
+            is_admin(signer::address_of(multisig_admin), pool_address),
+            error::permission_denied(ENOT_AUTHORIZED),
+        );
+    };
+
+    let delegation_pool = borrow_global_mut<DelegationPool>(pool_address);
+    let last_unlocked_period = delegation_pool.principle_unlock_schedule.last_unlock_period;
+    let schedule_length = vector::length(
+        &delegation_pool.principle_unlock_schedule.schedule
     );
+    // Current last_unlock_period must be greater or equal to schedule_length -1, this is because
+    // last_unlock_period is used as index into schedule vector. If we are not already at the last index or beyond
+    // increasing this would have undesirable effect. For example if schedule is [20%, 30%, 10%] and
+    // last_unlock_period = 1, increasing it by two would directly go to 10% unlock skipping 30% unlock part
+    assert!(schedule_length - 1 <= last_unlocked_period, EINVALID_STATE_FOR_OPERATION);
+    delegation_pool.principle_unlock_schedule.last_unlock_period = delegation_pool.principle_unlock_schedule
+        .last_unlock_period + additional_periods;
+
 }
 
@@ -4428,7 +4544,7 @@ validator-owners to prevent it from being abused. { assert!( is_admin(signer::address_of(multisig_admin), pool_address), - error::permission_denied(ENOT_AUTHORIZED) + error::permission_denied(ENOT_AUTHORIZED), ); }; @@ -4441,8 +4557,9 @@ validator-owners to prevent it from being abused. delegators, new_principle_stakes, |delegator, principle_stake| { - let (active, inactive, pending_inactive) = - get_stake(pool_address, delegator); + let (active, inactive, pending_inactive) = get_stake( + pool_address, delegator + ); // Ensure that all stake to be locked is made `active`. if (active < principle_stake) { @@ -4469,8 +4586,7 @@ validator-owners to prevent it from being abused. if (active_and_pending_inactive < principle_stake) { // Need to reactivate some of the `inactive` stake. - let amount_to_withdraw = - principle_stake - active_and_pending_inactive; + let amount_to_withdraw = principle_stake - active_and_pending_inactive; // Ensure that we do not try to withdraw more stake than the `inactive` stake. if (amount_to_withdraw > inactive) { @@ -4483,14 +4599,14 @@ validator-owners to prevent it from being abused. multisig_admin, pool_address, delegator, - amount_to_withdraw + amount_to_withdraw, ); // Then allocate it to the delegator again. fund_delegator_stake( multisig_admin, pool_address, delegator, - amount_to_withdraw + amount_to_withdraw, ); } } @@ -4498,17 +4614,18 @@ validator-owners to prevent it from being abused. // else: The amount to lock can be covered by the currently `active` stake. // Update the delegator's principle stake and record the details of the lockup event. - let principle_stake_table = - &mut (borrow_global_mut<DelegationPool>(pool_address).principle_stake); + let principle_stake_table = &mut ( + borrow_global_mut<DelegationPool>(pool_address).principle_stake + ); table::upsert(principle_stake_table, delegator, principle_stake); event::emit( UnlockScheduleApplied { pool_address, delegator, amount: principle_stake - } + }, ); - } + }, ); }
@@ -4552,24 +4669,24 @@ validator-owners to prevent it from being abused. let admin_addr = signer::address_of(multisig_admin); assert!( is_admin(admin_addr, pool_address), - error::permission_denied(ENOT_AUTHORIZED) + error::permission_denied(ENOT_AUTHORIZED), ); //Ensure replacement address is different assert!( old_delegator != new_delegator, - error::invalid_argument(ENEW_IS_SAME_AS_OLD_DELEGATOR) + error::invalid_argument(ENEW_IS_SAME_AS_OLD_DELEGATOR), ); //Ensure it is a valid `pool_addres` assert!( exists<DelegationPool>(pool_address), - error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST) + error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST), ); let pool: &mut DelegationPool = borrow_global_mut<DelegationPool>(pool_address); //Ensure `old_delegator` is part of original principle stakers before commencing the replacement assert!( table::contains(&pool.principle_stake, old_delegator), - error::unavailable(EDELEGATOR_DOES_NOT_EXIST) + error::unavailable(EDELEGATOR_DOES_NOT_EXIST), ); //replace in `active_shares` pool @@ -4580,22 +4697,24 @@ validator-owners to prevent it from being abused. active_pool, old_delegator, new_delegator, - active_shares + active_shares, ); }; //replace in `inactive_shares` pool - let (withdrawal_exists, withdrawal_olc) = - pending_withdrawal_exists(pool, old_delegator); + let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists( + pool, old_delegator + ); if (withdrawal_exists) { - let inactive_pool = - table::borrow_mut(&mut pool.inactive_shares, withdrawal_olc); + let inactive_pool = table::borrow_mut( + &mut pool.inactive_shares, withdrawal_olc + ); let inactive_shares = pool_u64::shares(inactive_pool, old_delegator); pool_u64::transfer_shares( inactive_pool, old_delegator, new_delegator, - inactive_shares + inactive_shares, ); //replace in `pending_withdrawals` @@ -4629,12 +4748,12 @@ validator-owners to prevent it from being abused. VotingRecordKey { voter: new_delegator, proposal_id: proposal_id - } + }, ); vector::push_back(&mut old_keys, *key); }; - } + }, ); vector::zip_ref( @@ -4642,7 +4761,7 @@ validator-owners to prevent it from being abused. &new_keys, |old, new| { replace_in_smart_tables(&mut grecords.votes, *old, *new); - } + }, ); } }; @@ -4746,31 +4865,31 @@ accurate as time passes ): u64 acquires DelegationPool { assert!( exists<DelegationPool>(pool_addr), - error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST) + error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST), ); let pool = borrow_global<DelegationPool>(pool_addr); - let delegator_active_balance = - pool_u64::balance(&pool.active_shares, delegator_addr); - let unlockable_fraction = - pool.principle_unlock_schedule.cumulative_unlocked_fraction; - let delegator_principle_stake = - *table::borrow(&pool.principle_stake, delegator_addr); + let delegator_active_balance = pool_u64::balance( + &pool.active_shares, delegator_addr + ); + let unlockable_fraction = pool.principle_unlock_schedule.cumulative_unlocked_fraction; + let delegator_principle_stake = *table::borrow( + &pool.principle_stake, delegator_addr + ); //To avoid problem even if fraction is slightly above 1 - let unlockable_principle_stake = - ( - math128::min( - fixed_point64::multiply_u128( - (delegator_principle_stake as u128), unlockable_fraction - ), - (delegator_principle_stake as u128) - ) as u64 - ); + let unlockable_principle_stake = ( + math128::min( + fixed_point64::multiply_u128( + (delegator_principle_stake as u128), unlockable_fraction + ), + (delegator_principle_stake as u128), + ) as u64 + ); let locked_amount = delegator_principle_stake - unlockable_principle_stake; assert!( delegator_active_balance >= locked_amount, - error::invalid_state(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW) + error::invalid_state(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW), ); delegator_active_balance - locked_amount @@ -4801,58 +4920,62 @@ Note: this does not synchronize with stake pool, therefore the answer may be con delegator_addr: address, pool_address: address, amount: u64 ): bool acquires DelegationPool { - let principle_stake_table = - &borrow_global<DelegationPool>(pool_address).principle_stake; + let principle_stake_table = &borrow_global<DelegationPool>(pool_address).principle_stake; if (!table::contains(principle_stake_table, delegator_addr)) { return false }; - let unlock_schedule = - &mut borrow_global_mut<DelegationPool>(pool_address).principle_unlock_schedule; + let unlock_schedule = &mut borrow_global_mut<DelegationPool>(pool_address).principle_unlock_schedule; let one = fixed_point64::create_from_rational(1, 1); if (fixed_point64::greater_or_equal( - unlock_schedule.cumulative_unlocked_fraction, one - )) { + unlock_schedule.cumulative_unlocked_fraction, one + )) { return true }; if (unlock_schedule.start_timestamp_secs > timestamp::now_seconds()) { - let unlockable_amount = - cached_unlockable_balance(delegator_addr, pool_address); + let unlockable_amount = cached_unlockable_balance( + delegator_addr, pool_address + ); return amount <= unlockable_amount }; //subtraction safety due to check above - let unlock_periods_passed = - (timestamp::now_seconds() - unlock_schedule.start_timestamp_secs) - / unlock_schedule.period_duration; + let unlock_periods_passed = ( + timestamp::now_seconds() - unlock_schedule.start_timestamp_secs + ) / unlock_schedule.period_duration; let last_unlocked_period = unlock_schedule.last_unlock_period; let schedule_length = vector::length(&unlock_schedule.schedule); let cfraction = unlock_schedule.cumulative_unlocked_fraction; while (last_unlocked_period < unlock_periods_passed && fixed_point64::less(cfraction, one) && last_unlocked_period < schedule_length) { - let next_fraction = - *vector::borrow(&unlock_schedule.schedule, last_unlocked_period); + let next_fraction = *vector::borrow( + &unlock_schedule.schedule, last_unlocked_period + ); cfraction = fixed_point64::add(cfraction, next_fraction); last_unlocked_period = last_unlocked_period + 1; }; - if (last_unlocked_period < unlock_periods_passed - && fixed_point64::less(cfraction, one)) { - let final_fraction = - *vector::borrow(&unlock_schedule.schedule, schedule_length - 1); + if (last_unlocked_period < unlock_periods_passed && fixed_point64::less( + cfraction, one + )) { + let final_fraction = *vector::borrow( + &unlock_schedule.schedule, schedule_length - 1 + ); // Acclerate calculation to current period and don't update last_unlocked_period since it is not used anymore cfraction = fixed_point64::add( cfraction, fixed_point64::multiply_u128_return_fixpoint64( (unlock_periods_passed - last_unlocked_period as u128), - final_fraction - ) + final_fraction, + ), ); cfraction = fixed_point64::min(cfraction, one); }; unlock_schedule.cumulative_unlocked_fraction = cfraction; - unlock_schedule.last_unlock_period = unlock_periods_passed; + unlock_schedule.last_unlock_period = math64::max( + unlock_periods_passed, last_unlocked_period + ); let unlockable_amount = cached_unlockable_balance(delegator_addr, pool_address); amount <= unlockable_amount } @@ -4887,13 +5010,13 @@ at most how much active stake there is on the stake pool. // fail unlock of less than `MIN_COINS_ON_SHARES_POOL` assert!( amount >= MIN_COINS_ON_SHARES_POOL, - error::invalid_argument(EMINIMUM_UNLOCK_AMOUNT) + error::invalid_argument(EMINIMUM_UNLOCK_AMOUNT), ); // fail unlock of more stake than `active` on the stake pool let (active, _, _, _) = stake::get_stake(pool_address); assert!( amount <= active, - error::invalid_argument(ENOT_ENOUGH_ACTIVE_STAKE_TO_UNLOCK) + error::invalid_argument(ENOT_ENOUGH_ACTIVE_STAKE_TO_UNLOCK), ); // synchronize delegation and stake pools before any user operation @@ -4904,7 +5027,7 @@ at most how much active stake there is on the stake pool. if (is_principle_stakeholder(delegator_address, pool_address)) { assert!( can_principle_unlock(delegator_address, pool_address, amount), - error::invalid_argument(EAMOUNT_REQUESTED_NOT_UNLOCKABLE) + error::invalid_argument(EAMOUNT_REQUESTED_NOT_UNLOCKABLE), ); }; let pool = borrow_global_mut<DelegationPool>(pool_address); @@ -4912,7 +5035,7 @@ at most how much active stake there is on the stake pool. &pool.active_shares, pending_inactive_shares_pool(pool), delegator_address, - amount + amount, ); amount = redeem_active_shares(pool, delegator_address, amount); stake::unlock(&retrieve_stake_pool_owner(pool), amount); @@ -4922,12 +5045,12 @@ at most how much active stake there is on the stake pool. event::emit_event( &mut pool.unlock_stake_events, - UnlockStakeEvent { pool_address, delegator_address, amount_unlocked: amount } + UnlockStakeEvent { pool_address, delegator_address, amount_unlocked: amount }, ); let (active_stake, _, pending_active, _) = stake::get_stake(pool_address); assert!( active_stake + pending_active == pool_u64::total_coins(&pool.active_shares), - error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL) + error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL), ); }
@@ -4991,7 +5114,7 @@ Withdraw amount of owned inactive stake from the delegation pool at borrow_global_mut<DelegationPool>(pool_address), delegator_address, amount, - delegator_address + delegator_address, ); }
@@ -5026,29 +5149,31 @@ Withdraw amount of owned inactive stake from the delegation pool at if (amount == 0) { return }; let pool_address = get_pool_address(pool); - let (withdrawal_exists, withdrawal_olc) = - pending_withdrawal_exists(pool, delegator_address); + let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists( + pool, delegator_address + ); // exit if no withdrawal or (it is pending and cannot withdraw pending_inactive stake from stake pool) if (!( - withdrawal_exists + withdrawal_exists && ( - withdrawal_olc.index < pool.observed_lockup_cycle.index - || can_withdraw_pending_inactive(pool_address) + withdrawal_olc.index < pool.observed_lockup_cycle.index || can_withdraw_pending_inactive( + pool_address + ) ) - )) { return }; + )) { return }; if (withdrawal_olc.index == pool.observed_lockup_cycle.index) { amount = coins_to_redeem_to_ensure_min_stake( pending_inactive_shares_pool(pool), delegator_address, - amount + amount, ) }; amount = redeem_inactive_shares( pool, delegator_address, amount, - withdrawal_olc + withdrawal_olc, ); let stake_pool_owner = &retrieve_stake_pool_owner(pool); @@ -5080,7 +5205,7 @@ Withdraw amount of owned inactive stake from the delegation pool at event::emit_event( &mut pool.withdraw_stake_events, - WithdrawStakeEvent { pool_address, delegator_address, amount_withdrawn: amount } + WithdrawStakeEvent { pool_address, delegator_address, amount_withdrawn: amount }, ); }
@@ -5112,9 +5237,7 @@ A bool is returned to signal if a pending withdrawal exists at all. ): (bool, ObservedLockupCycle) { if (table::contains(&pool.pending_withdrawals, delegator_address)) { (true, *table::borrow(&pool.pending_withdrawals, delegator_address)) - } else { - (false, olc_with_index(0)) - } + } else { (false, olc_with_index(0)) } }
@@ -5195,15 +5318,15 @@ be explicitly withdrawn by delegator
fun execute_pending_withdrawal(
     pool: &mut DelegationPool, delegator_address: address
 ) acquires GovernanceRecords {
-    let (withdrawal_exists, withdrawal_olc) =
-        pending_withdrawal_exists(pool, delegator_address);
-    if (withdrawal_exists
-        && withdrawal_olc.index < pool.observed_lockup_cycle.index) {
+    let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists(
+        pool, delegator_address
+    );
+    if (withdrawal_exists && withdrawal_olc.index < pool.observed_lockup_cycle.index) {
         withdraw_internal(
             pool,
             delegator_address,
             MAX_U64,
-            delegator_address
+            delegator_address,
         );
     }
 }
@@ -5278,10 +5401,9 @@ to ensure there is always only one withdrawal request.
 
fun buy_in_pending_inactive_shares(
     pool: &mut DelegationPool, shareholder: address, coins_amount: u64
 ): u128 acquires GovernanceRecords {
-    let new_shares =
-        pool_u64::amount_to_shares(
-            pending_inactive_shares_pool(pool), coins_amount
-        );
+    let new_shares = pool_u64::amount_to_shares(
+        pending_inactive_shares_pool(pool), coins_amount
+    );
     // never create a new pending withdrawal unless delegator owns some pending_inactive shares
     if (new_shares == 0) {
         return 0
@@ -5309,7 +5431,7 @@ to ensure there is always only one withdrawal request.
         *table::borrow_mut_with_default(
             &mut pool.pending_withdrawals, shareholder, observed_lockup_cycle
         ) == observed_lockup_cycle,
-        error::invalid_state(EPENDING_WITHDRAWAL_EXISTS)
+        error::invalid_state(EPENDING_WITHDRAWAL_EXISTS),
     );
 
     new_shares
@@ -5375,8 +5497,9 @@ be available for withdrawal when current OLC ends.
 
fun redeem_active_shares(
     pool: &mut DelegationPool, shareholder: address, coins_amount: u64
 ): u64 acquires GovernanceRecords {
-    let shares_to_redeem =
-        amount_to_shares_to_redeem(&pool.active_shares, shareholder, coins_amount);
+    let shares_to_redeem = amount_to_shares_to_redeem(
+        &pool.active_shares, shareholder, coins_amount
+    );
     // silently exit if not a shareholder otherwise redeem would fail with `ESHAREHOLDER_NOT_FOUND`
     if (shares_to_redeem == 0) return 0;
 
@@ -5387,7 +5510,7 @@ be available for withdrawal when current OLC ends.
             pool,
             pool_address,
             shares_to_redeem,
-            shareholder
+            shareholder,
         );
     };
 
@@ -5426,32 +5549,32 @@ escape inactivation when current lockup ends.
     coins_amount: u64,
     lockup_cycle: ObservedLockupCycle
 ): u64 acquires GovernanceRecords {
-    let shares_to_redeem =
-        amount_to_shares_to_redeem(
-            table::borrow(&pool.inactive_shares, lockup_cycle),
-            shareholder,
-            coins_amount
-        );
+    let shares_to_redeem = amount_to_shares_to_redeem(
+        table::borrow(&pool.inactive_shares, lockup_cycle),
+        shareholder,
+        coins_amount,
+    );
     // silently exit if not a shareholder otherwise redeem would fail with `ESHAREHOLDER_NOT_FOUND`
     if (shares_to_redeem == 0) return 0;
 
     // Always update governance records before any change to the shares pool.
     let pool_address = get_pool_address(pool);
     // Only redeem shares from the pending_inactive pool at `lockup_cycle` == current OLC.
-    if (partial_governance_voting_enabled(pool_address)
-        && lockup_cycle.index == pool.observed_lockup_cycle.index) {
+    if (partial_governance_voting_enabled(pool_address) && lockup_cycle.index == pool.observed_lockup_cycle
+        .index) {
         update_governanace_records_for_redeem_pending_inactive_shares(
             pool,
             pool_address,
             shares_to_redeem,
-            shareholder
+            shareholder,
         );
     };
 
     let inactive_shares = table::borrow_mut(&mut pool.inactive_shares, lockup_cycle);
     // 1. reaching here means delegator owns inactive/pending_inactive shares at OLC `lockup_cycle`
-    let redeemed_coins =
-        pool_u64::redeem_shares(inactive_shares, shareholder, shares_to_redeem);
+    let redeemed_coins = pool_u64::redeem_shares(
+        inactive_shares, shareholder, shares_to_redeem
+    );
 
     // if entirely reactivated pending_inactive stake or withdrawn inactive one,
     // re-enable unlocking for delegator by deleting this pending withdrawal
@@ -5461,8 +5584,9 @@ escape inactivation when current lockup ends.
         table::remove(&mut pool.pending_withdrawals, shareholder);
     };
     // destroy inactive shares pool of past OLC if all its stake has been withdrawn
-    if (lockup_cycle.index < pool.observed_lockup_cycle.index
-        && total_coins(inactive_shares) == 0) {
+    if (lockup_cycle.index < pool.observed_lockup_cycle.index && total_coins(
+            inactive_shares
+        ) == 0) {
         pool_u64::destroy_empty(
             table::remove(&mut pool.inactive_shares, lockup_cycle)
         );
@@ -5495,11 +5619,12 @@ whether the lockup expired on the stake pool.
 
 
 
fun calculate_stake_pool_drift(pool: &DelegationPool): (bool, u64, u64, u64, u64) {
-    let (active, inactive, pending_active, pending_inactive) =
-        stake::get_stake(get_pool_address(pool));
+    let (active, inactive, pending_active, pending_inactive) = stake::get_stake(
+        get_pool_address(pool)
+    );
     assert!(
         inactive >= pool.total_coins_inactive,
-        error::invalid_state(ESLASHED_INACTIVE_STAKE_ON_PAST_OLC)
+        error::invalid_state(ESLASHED_INACTIVE_STAKE_ON_PAST_OLC),
     );
     // determine whether a new lockup cycle has been ended on the stake pool and
     // inactivated SOME `pending_inactive` stake which should stop earning rewards now,
@@ -5530,8 +5655,7 @@ whether the lockup expired on the stake pool.
             )
         } else {
             // handle any slashing applied to `active` stake
-            0
-        };
+            0 };
     // operator `pending_inactive` rewards not persisted yet to the pending_inactive shares pool
     let pool_pending_inactive = total_coins(pending_inactive_shares_pool(pool));
     let commission_pending_inactive =
@@ -5539,12 +5663,11 @@ whether the lockup expired on the stake pool.
             math64::mul_div(
                 pending_inactive - pool_pending_inactive,
                 pool.operator_commission_percentage,
-                MAX_FEE
+                MAX_FEE,
             )
         } else {
             // handle any slashing applied to `pending_inactive` stake
-            0
-        };
+            0 };
 
     (
         lockup_cycle_ended,
@@ -5577,9 +5700,7 @@ shares pools, assign commission to operator and eventually prepare delegation po
 Implementation
 
 
-
public entry fun synchronize_delegation_pool(
-    pool_address: address
-) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage {
+
public entry fun synchronize_delegation_pool(pool_address: address) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage {
     assert_delegation_pool_exists(pool_address);
     let pool = borrow_global_mut<DelegationPool>(pool_address);
     let (
@@ -5605,25 +5726,24 @@ shares pools, assign commission to operator and eventually prepare delegation po
 
     // update total coins accumulated by `active` + `pending_active` shares
     // redeemed `add_stake` fees are restored and distributed to the rest of the pool as rewards
-    pool_u64::update_total_coins(&mut pool.active_shares, active
-        - commission_active);
+    pool_u64::update_total_coins(&mut pool.active_shares, active - commission_active);
     // update total coins accumulated by `pending_inactive` shares at current observed lockup cycle
     pool_u64::update_total_coins(
         pending_inactive_shares_pool_mut(pool),
-        pending_inactive - commission_pending_inactive
+        pending_inactive - commission_pending_inactive,
     );
 
     // reward operator its commission out of uncommitted active rewards (`add_stake` fees already excluded)
     buy_in_active_shares(
         pool,
         beneficiary_for_operator(stake::get_operator(pool_address)),
-        commission_active
+        commission_active,
     );
     // reward operator its commission out of uncommitted pending_inactive rewards
     buy_in_pending_inactive_shares(
         pool,
         beneficiary_for_operator(stake::get_operator(pool_address)),
-        commission_pending_inactive
+        commission_pending_inactive,
     );
 
     event::emit_event(
@@ -5633,7 +5753,7 @@ shares pools, assign commission to operator and eventually prepare delegation po
             operator: stake::get_operator(pool_address),
             commission_active,
             commission_pending_inactive
-        }
+        },
     );
 
     if (features::operator_beneficiary_change_enabled()) {
@@ -5646,7 +5766,7 @@ shares pools, assign commission to operator and eventually prepare delegation po
                 ),
                 commission_active,
                 commission_pending_inactive
-            }
+            },
         )
     };
 
@@ -5662,7 +5782,7 @@ shares pools, assign commission to operator and eventually prepare delegation po
         table::add(
             &mut pool.inactive_shares,
             pool.observed_lockup_cycle,
-            pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR)
+            pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR),
         );
     };
 
@@ -5703,26 +5823,22 @@ shares pools, assign commission to operator and eventually prepare delegation po
     // <active shares> of <current voter of shareholder> += <new_shares>
     // <active shares> of <next voter of shareholder> += <new_shares>
     let governance_records = borrow_global_mut<GovernanceRecords>(pool_address);
-    let vote_delegation =
-        update_and_borrow_mut_delegator_vote_delegation(
-            pool, governance_records, shareholder
-        );
+    let vote_delegation = update_and_borrow_mut_delegator_vote_delegation(
+        pool, governance_records, shareholder
+    );
     let current_voter = vote_delegation.voter;
     let pending_voter = vote_delegation.pending_voter;
-    let current_delegated_votes =
-        update_and_borrow_mut_delegated_votes(
-            pool, governance_records, current_voter
-        );
-    current_delegated_votes.active_shares = current_delegated_votes.active_shares
-        + new_shares;
+    let current_delegated_votes = update_and_borrow_mut_delegated_votes(
+        pool, governance_records, current_voter
+    );
+    current_delegated_votes.active_shares = current_delegated_votes.active_shares + new_shares;
     if (pending_voter == current_voter) {
         current_delegated_votes.active_shares_next_lockup = current_delegated_votes.active_shares_next_lockup
             + new_shares;
     } else {
-        let pending_delegated_votes =
-            update_and_borrow_mut_delegated_votes(
-                pool, governance_records, pending_voter
-            );
+        let pending_delegated_votes = update_and_borrow_mut_delegated_votes(
+            pool, governance_records, pending_voter
+        );
         pending_delegated_votes.active_shares_next_lockup = pending_delegated_votes.active_shares_next_lockup
             + new_shares;
     };
@@ -5758,14 +5874,12 @@ shares pools, assign commission to operator and eventually prepare delegation po
     // <pending inactive shares> of <current voter of shareholder> += <new_shares>
     // no impact on <pending inactive shares> of <next voter of shareholder>
     let governance_records = borrow_global_mut<GovernanceRecords>(pool_address);
-    let current_voter =
-        calculate_and_update_delegator_voter_internal(
-            pool, governance_records, shareholder
-        );
-    let current_delegated_votes =
-        update_and_borrow_mut_delegated_votes(
-            pool, governance_records, current_voter
-        );
+    let current_voter = calculate_and_update_delegator_voter_internal(
+        pool, governance_records, shareholder
+    );
+    let current_delegated_votes = update_and_borrow_mut_delegated_votes(
+        pool, governance_records, current_voter
+    );
     current_delegated_votes.pending_inactive_shares = current_delegated_votes.pending_inactive_shares
         + new_shares;
 }
@@ -5800,26 +5914,22 @@ shares pools, assign commission to operator and eventually prepare delegation po
     // <active shares> of <current voter of shareholder> -= <shares_to_redeem>
     // <active shares> of <next voter of shareholder> -= <shares_to_redeem>
     let governance_records = borrow_global_mut<GovernanceRecords>(pool_address);
-    let vote_delegation =
-        update_and_borrow_mut_delegator_vote_delegation(
-            pool, governance_records, shareholder
-        );
+    let vote_delegation = update_and_borrow_mut_delegator_vote_delegation(
+        pool, governance_records, shareholder
+    );
     let current_voter = vote_delegation.voter;
     let pending_voter = vote_delegation.pending_voter;
-    let current_delegated_votes =
-        update_and_borrow_mut_delegated_votes(
-            pool, governance_records, current_voter
-        );
-    current_delegated_votes.active_shares = current_delegated_votes.active_shares
-        - shares_to_redeem;
+    let current_delegated_votes = update_and_borrow_mut_delegated_votes(
+        pool, governance_records, current_voter
+    );
+    current_delegated_votes.active_shares = current_delegated_votes.active_shares - shares_to_redeem;
     if (current_voter == pending_voter) {
         current_delegated_votes.active_shares_next_lockup = current_delegated_votes.active_shares_next_lockup
             - shares_to_redeem;
     } else {
-        let pending_delegated_votes =
-            update_and_borrow_mut_delegated_votes(
-                pool, governance_records, pending_voter
-            );
+        let pending_delegated_votes = update_and_borrow_mut_delegated_votes(
+            pool, governance_records, pending_voter
+        );
         pending_delegated_votes.active_shares_next_lockup = pending_delegated_votes.active_shares_next_lockup
             - shares_to_redeem;
     };
@@ -5855,14 +5965,12 @@ shares pools, assign commission to operator and eventually prepare delegation po
     // <pending inactive shares> of <current voter of shareholder> -= <shares_to_redeem>
     // no impact on <pending inactive shares> of <next voter of shareholder>
     let governance_records = borrow_global_mut<GovernanceRecords>(pool_address);
-    let current_voter =
-        calculate_and_update_delegator_voter_internal(
-            pool, governance_records, shareholder
-        );
-    let current_delegated_votes =
-        update_and_borrow_mut_delegated_votes(
-            pool, governance_records, current_voter
-        );
+    let current_voter = calculate_and_update_delegator_voter_internal(
+        pool, governance_records, shareholder
+    );
+    let current_delegated_votes = update_and_borrow_mut_delegated_votes(
+        pool, governance_records, current_voter
+    );
     current_delegated_votes.pending_inactive_shares = current_delegated_votes.pending_inactive_shares
         - shares_to_redeem;
 }
diff --git a/aptos-move/framework/supra-framework/doc/randomness.md b/aptos-move/framework/supra-framework/doc/randomness.md
index fcf3f18fff6..7cf189e90c5 100644
--- a/aptos-move/framework/supra-framework/doc/randomness.md
+++ b/aptos-move/framework/supra-framework/doc/randomness.md
@@ -219,11 +219,10 @@ Must be called in tests to initialize the initialize(framework: &signer) {
     system_addresses::assert_supra_framework(framework);
     if (!exists<PerBlockRandomness>(@supra_framework)) {
-        move_to(framework, PerBlockRandomness {
-            epoch: 0,
-            round: 0,
-            seed: option::none(),
-        });
+        move_to(
+            framework,
+            PerBlockRandomness { epoch: 0, round: 0, seed: option::none() }
+        );
     }
 }
 
@@ -248,7 +247,12 @@ Invoked in block prologues to update the block-level randomness seed. Implementation -
public(friend) fun on_new_block(vm: &signer, epoch: u64, round: u64, seed_for_new_block: Option<vector<u8>>) acquires PerBlockRandomness {
+
public(friend) fun on_new_block(
+    vm: &signer,
+    epoch: u64,
+    round: u64,
+    seed_for_new_block: Option<vector<u8>>
+) acquires PerBlockRandomness {
     system_addresses::assert_vm(vm);
     if (exists<PerBlockRandomness>(@supra_framework)) {
         let randomness = borrow_global_mut<PerBlockRandomness>(@supra_framework);
@@ -830,7 +834,7 @@ If n is 0, returns the empty vector.
 
     let values = vector[];
 
-    if(n == 0) {
+    if (n == 0) {
         return vector[]
     };
 
@@ -894,7 +898,15 @@ Compute (a + b) % m, assuming m >= 1, 0 <= a < m, 0&
     let a_clone = a;
     let neg_b = m - b;
     let a_less = a < neg_b;
-    take_first(if (a_less) { a + b } else { a_clone - neg_b }, if (!a_less) { a_clone - neg_b } else { a + b })
+    take_first(
+        if (a_less) { a + b }
+        else {
+            a_clone - neg_b
+        },
+        if (!a_less) {
+            a_clone - neg_b
+        } else { a + b }
+    )
 }
 
@@ -917,7 +929,9 @@ Compute (a + b) % m, assuming m >= 1, 0 <= a < m, 0& Implementation -
fun take_first(x: u256, _y: u256 ): u256 { x }
+
fun take_first(x: u256, _y: u256): u256 {
+    x
+}
 
diff --git a/aptos-move/framework/supra-framework/doc/randomness_config.md b/aptos-move/framework/supra-framework/doc/randomness_config.md index 113a5ff9fd2..d94521285e9 100644 --- a/aptos-move/framework/supra-framework/doc/randomness_config.md +++ b/aptos-move/framework/supra-framework/doc/randomness_config.md @@ -224,7 +224,9 @@ This can be called by on-chain governance to update on-chain consensus configs f Implementation -
public fun set_for_next_epoch(framework: &signer, new_config: RandomnessConfig) {
+
public fun set_for_next_epoch(
+    framework: &signer, new_config: RandomnessConfig
+) {
     system_addresses::assert_supra_framework(framework);
     config_buffer::upsert(new_config);
 }
@@ -274,7 +276,6 @@ Only used in reconfigurations to apply the pending consensus_config::validator_txn_enabled() && randomness_config::enabled().
 
 
 
public fun enabled(): bool
@@ -289,11 +290,10 @@ The feature works if and only if enabled(): bool acquires RandomnessConfig {
     if (exists<RandomnessConfig>(@supra_framework)) {
         let config = borrow_global<RandomnessConfig>(@supra_framework);
-        let variant_type_name = *string::bytes(copyable_any::type_name(&config.variant));
+        let variant_type_name =
+            *string::bytes(copyable_any::type_name(&config.variant));
         variant_type_name != b"0x1::randomness_config::ConfigOff"
-    } else {
-        false
-    }
+    } else { false }
 }
 
@@ -319,7 +319,7 @@ Create a Co
public fun new_off(): RandomnessConfig {
     RandomnessConfig {
-        variant: copyable_any::pack( ConfigOff {} )
+        variant: copyable_any::pack(ConfigOff {})
     }
 }
 
@@ -344,12 +344,13 @@ Create a Con Implementation -
public fun new_v1(secrecy_threshold: FixedPoint64, reconstruction_threshold: FixedPoint64): RandomnessConfig {
+
public fun new_v1(
+    secrecy_threshold: FixedPoint64, reconstruction_threshold: FixedPoint64
+): RandomnessConfig {
     RandomnessConfig {
-        variant: copyable_any::pack( ConfigV1 {
-            secrecy_threshold,
-            reconstruction_threshold
-        } )
+        variant: copyable_any::pack(
+            ConfigV1 { secrecy_threshold, reconstruction_threshold }
+        )
     }
 }
 
@@ -377,14 +378,16 @@ Create a Con
public fun new_v2(
     secrecy_threshold: FixedPoint64,
     reconstruction_threshold: FixedPoint64,
-    fast_path_secrecy_threshold: FixedPoint64,
+    fast_path_secrecy_threshold: FixedPoint64
 ): RandomnessConfig {
     RandomnessConfig {
-        variant: copyable_any::pack( ConfigV2 {
-            secrecy_threshold,
-            reconstruction_threshold,
-            fast_path_secrecy_threshold,
-        } )
+        variant: copyable_any::pack(
+            ConfigV2 {
+                secrecy_threshold,
+                reconstruction_threshold,
+                fast_path_secrecy_threshold
+            }
+        )
     }
 }
 
diff --git a/aptos-move/framework/supra-framework/doc/reconfiguration.md b/aptos-move/framework/supra-framework/doc/reconfiguration.md index 8a2e4582881..b9ff1c3c5fd 100644 --- a/aptos-move/framework/supra-framework/doc/reconfiguration.md +++ b/aptos-move/framework/supra-framework/doc/reconfiguration.md @@ -38,6 +38,7 @@ to synchronize configuration changes for the validators. use 0x1::error; use 0x1::event; use 0x1::features; +use 0x1::leader_ban_registry; use 0x1::reconfiguration_state; use 0x1::signer; use 0x1::stake; @@ -400,6 +401,7 @@ Signal validators to start using new configuration. Must be called from friend c // Call stake to compute the new validator set and distribute rewards and transaction fees. stake::on_new_epoch(); + leader_ban_registry::on_new_epoch(); storage_gas::on_reconfig(); assert!(current_time > config_ref.last_reconfiguration_time, error::invalid_state(EINVALID_BLOCK_TIME)); diff --git a/aptos-move/framework/supra-framework/doc/reconfiguration_with_dkg.md b/aptos-move/framework/supra-framework/doc/reconfiguration_with_dkg.md index 09bc60dc551..772b1b2a310 100644 --- a/aptos-move/framework/supra-framework/doc/reconfiguration_with_dkg.md +++ b/aptos-move/framework/supra-framework/doc/reconfiguration_with_dkg.md @@ -7,6 +7,7 @@ Reconfiguration with DKG helper functions. - [Function `try_start`](#0x1_reconfiguration_with_dkg_try_start) +- [Function `set_dkg_meta`](#0x1_reconfiguration_with_dkg_set_dkg_meta) - [Function `finish`](#0x1_reconfiguration_with_dkg_finish) - [Function `finish_with_dkg_result`](#0x1_reconfiguration_with_dkg_finish_with_dkg_result) - [Specification](#@Specification_0) @@ -17,7 +18,9 @@ Reconfiguration with DKG helper functions.
use 0x1::automation_registry;
 use 0x1::consensus_config;
-use 0x1::dkg;
+use 0x1::dkg_committee;
+use 0x1::dkg_config;
+use 0x1::evm_config;
 use 0x1::evm_genesis_config;
 use 0x1::execution_config;
 use 0x1::features;
@@ -25,7 +28,9 @@ Reconfiguration with DKG helper functions.
 use 0x1::jwk_consensus_config;
 use 0x1::jwks;
 use 0x1::keyless_account;
+use 0x1::leader_ban_registry_config;
 use 0x1::option;
+use 0x1::randomness;
 use 0x1::randomness_api_v0_config;
 use 0x1::randomness_config;
 use 0x1::randomness_config_seqnum;
@@ -33,8 +38,10 @@ Reconfiguration with DKG helper functions.
 use 0x1::reconfiguration_state;
 use 0x1::stake;
 use 0x1::supra_config;
+use 0x1::supra_dkg;
 use 0x1::system_addresses;
 use 0x1::validator_consensus_info;
+use 0x1::validator_public_keys;
 use 0x1::version;
 
@@ -58,26 +65,79 @@ Do nothing if one is already in progress.
public(friend) fun try_start() {
-    let incomplete_dkg_session = dkg::incomplete_session();
+    let incomplete_dkg_session = supra_dkg::incomplete_session();
     if (option::is_some(&incomplete_dkg_session)) {
         let session = option::borrow(&incomplete_dkg_session);
-        if (dkg::session_dealer_epoch(session) == reconfiguration::current_epoch()) {
-            return
-        }
+        if (supra_dkg::session_dealer_epoch(session)
+            == reconfiguration::current_epoch()) { return }
     };
     reconfiguration_state::on_reconfig_start();
     let cur_epoch = reconfiguration::current_epoch();
-    dkg::start(
+    let randomness_seed = randomness::bytes(32);
+
+    // Get DKG configuration (dealer threshold type and receiver committee configs)
+    let config = dkg_config::current();
+    let receiver_configs = dkg_config::get_receiver_committee_configs(&config);
+
+    // Build receiver committees from config
+    let receiver_committees = vector[];
+    let i = 0;
+    let len = vector::length(&receiver_configs);
+    while (i < len) {
+        let rc = vector::borrow(&receiver_configs, i);
+        vector::push_back(
+            &mut receiver_committees,
+            new_receiver_committee(
+                dkg_config::get_is_resharing(rc),
+                dkg_config::get_dkg_threshold_type(rc),
+                new_dkg_committee_from_validator_consensus_info(
+                    stake::next_epoch_validator_consensus_infos_for_dkg(),
+                    dkg_config::get_committee_threshold_type(rc)
+                )
+            )
+        );
+        i = i + 1;
+    };
+
+    // DKG for configured receiver committees
+    supra_dkg::start(
         cur_epoch,
-        randomness_config::current(),
-        stake::cur_validator_consensus_infos(),
-        stake::next_validator_consensus_infos()
+        randomness_seed,
+        new_dkg_committee_from_validator_consensus_info(
+            stake::cur_validator_consensus_infos(),
+            dkg_config::get_dealer_committee_threshold_type(&config)
+        ),
+        receiver_committees
     );
 }
 
+ + + + +## Function `set_dkg_meta` + + + +
fun set_dkg_meta(dkg_meta: vector<u8>)
+
+ + + +
+Implementation + + +
fun set_dkg_meta(dkg_meta: vector<u8>) {
+    supra_dkg::set_dkg_meta(dkg_meta);
+}
+
+ + +
@@ -101,7 +161,7 @@ Run the default reconfiguration to enter the new epoch.
public(friend) fun finish(framework: &signer) {
     system_addresses::assert_supra_framework(framework);
-    dkg::try_clear_incomplete_session(framework);
+    supra_dkg::try_clear_incomplete_session(framework);
     consensus_config::on_new_epoch(framework);
     execution_config::on_new_epoch(framework);
     supra_config::on_new_epoch(framework);
@@ -112,10 +172,13 @@ Run the default reconfiguration to enter the new epoch.
     jwk_consensus_config::on_new_epoch(framework);
     jwks::on_new_epoch(framework);
     keyless_account::on_new_epoch(framework);
+    leader_ban_registry_config::on_new_epoch(framework);
     randomness_config_seqnum::on_new_epoch(framework);
     randomness_config::on_new_epoch(framework);
     randomness_api_v0_config::on_new_epoch(framework);
     evm_genesis_config::on_new_epoch(framework);
+    dkg_config::on_new_epoch(framework);
+    evm_config::on_new_epoch(framework);
     reconfiguration::reconfigure();
 }
 
@@ -142,7 +205,7 @@ Abort if no DKG is in progress.
fun finish_with_dkg_result(account: &signer, dkg_result: vector<u8>) {
-    dkg::finish(dkg_result);
+    supra_dkg::finish(dkg_result);
     finish(account);
 }
 
@@ -178,8 +241,8 @@ Abort if no DKG is in progress. requires chain_status::is_operating(); include stake::ResourceRequirement; include stake::GetReconfigStartTimeRequirement; -include features::spec_periodical_reward_rate_decrease_enabled( -) ==> staking_config::StakingRewardsConfigEnabledRequirement; +include features::spec_periodical_reward_rate_decrease_enabled() ==> + staking_config::StakingRewardsConfigEnabledRequirement; aborts_if false; pragma verify_duration_estimate = 600;
@@ -245,10 +308,8 @@ Abort if no DKG is in progress.
pragma verify_duration_estimate = 1500;
-include FinishRequirement {
-    framework: account
-};
-requires dkg::has_incomplete_session();
+include FinishRequirement { framework: account };
+requires supra_dkg::has_incomplete_session();
 aborts_if false;
 
diff --git a/aptos-move/framework/supra-framework/doc/stake.md b/aptos-move/framework/supra-framework/doc/stake.md index 272be58be80..c5ebeff902f 100644 --- a/aptos-move/framework/supra-framework/doc/stake.md +++ b/aptos-move/framework/supra-framework/doc/stake.md @@ -83,11 +83,21 @@ or if their stake drops below the min required, they would get removed at the en - [Function `get_pending_transaction_fee`](#0x1_stake_get_pending_transaction_fee) - [Function `initialize`](#0x1_stake_initialize) - [Function `store_supra_coin_mint_cap`](#0x1_stake_store_supra_coin_mint_cap) +- [Function `get_pool_address_from_index`](#0x1_stake_get_pool_address_from_index) +- [Function `get_committee_size`](#0x1_stake_get_committee_size) +- [Function `get_committee_pool_addresses`](#0x1_stake_get_committee_pool_addresses) - [Function `remove_validators`](#0x1_stake_remove_validators) - [Function `initialize_pending_transaction_fee`](#0x1_stake_initialize_pending_transaction_fee) - [Function `record_fee`](#0x1_stake_record_fee) - [Function `initialize_stake_owner`](#0x1_stake_initialize_stake_owner) - [Function `initialize_validator`](#0x1_stake_initialize_validator) +- [Function `initialize_validator_genesis`](#0x1_stake_initialize_validator_genesis) +- [Function `initialize_validator_internal`](#0x1_stake_initialize_validator_internal) +- [Function `validate_consensus_public_key`](#0x1_stake_validate_consensus_public_key) +- [Function `assert_consensus_pubkey_unique_in_next_validator_set`](#0x1_stake_assert_consensus_pubkey_unique_in_next_validator_set) +- [Function `assert_consensus_pubkey_unique_in_validator_list`](#0x1_stake_assert_consensus_pubkey_unique_in_validator_list) +- [Function `assert_network_addresses_unique_in_next_validator_set`](#0x1_stake_assert_network_addresses_unique_in_next_validator_set) +- [Function `assert_network_addresses_unique_in_validator_list`](#0x1_stake_assert_network_addresses_unique_in_validator_list) - [Function `initialize_owner`](#0x1_stake_initialize_owner) - [Function `extract_owner_cap`](#0x1_stake_extract_owner_cap) - [Function `deposit_owner_cap`](#0x1_stake_deposit_owner_cap) @@ -101,6 +111,7 @@ or if their stake drops below the min required, they would get removed at the en - [Function `reactivate_stake`](#0x1_stake_reactivate_stake) - [Function `reactivate_stake_with_cap`](#0x1_stake_reactivate_stake_with_cap) - [Function `rotate_consensus_key_internal`](#0x1_stake_rotate_consensus_key_internal) +- [Function `set_dkg_output_keys`](#0x1_stake_set_dkg_output_keys) - [Function `rotate_consensus_key_genesis`](#0x1_stake_rotate_consensus_key_genesis) - [Function `rotate_consensus_key`](#0x1_stake_rotate_consensus_key) - [Function `update_network_and_fullnode_addresses`](#0x1_stake_update_network_and_fullnode_addresses) @@ -118,6 +129,9 @@ or if their stake drops below the min required, they would get removed at the en - [Function `on_new_epoch`](#0x1_stake_on_new_epoch) - [Function `cur_validator_consensus_infos`](#0x1_stake_cur_validator_consensus_infos) - [Function `next_validator_consensus_infos`](#0x1_stake_next_validator_consensus_infos) +- [Function `next_epoch_validator_consensus_infos_for_dkg`](#0x1_stake_next_epoch_validator_consensus_infos_for_dkg) +- [Function `compute_next_validator_set_internal`](#0x1_stake_compute_next_validator_set_internal) +- [Function `calculate_candidate_reward`](#0x1_stake_calculate_candidate_reward) - [Function `validator_consensus_infos_from_validator_set`](#0x1_stake_validator_consensus_infos_from_validator_set) - [Function `addresses_from_validator_infos`](#0x1_stake_addresses_from_validator_infos) - [Function `update_stake_pool`](#0x1_stake_update_stake_pool) @@ -179,8 +193,10 @@ or if their stake drops below the min required, they would get removed at the en
use 0x1::account;
 use 0x1::aggregator_v2;
 use 0x1::big_ordered_map;
+use 0x1::bls12381;
 use 0x1::chain_status;
 use 0x1::coin;
+use 0x1::dkg_committee;
 use 0x1::ed25519;
 use 0x1::error;
 use 0x1::event;
@@ -197,6 +213,7 @@ or if their stake drops below the min required, they would get removed at the en
 use 0x1::table;
 use 0x1::timestamp;
 use 0x1::validator_consensus_info;
+use 0x1::validator_public_keys;
 use 0x1::vector;
 
@@ -1755,6 +1772,36 @@ Account is already a validator or pending validator. + + +Invalid DKG public key shares. + + +
const EDKG_INVALID_PK_SHARES: u64 = 21;
+
+ + + + + +Another validator in the next validator set already uses this consensus public key. + + +
const EDUPLICATE_CONSENSUS_PUBKEY: u64 = 22;
+
+ + + + + +Another validator in the next validator set already uses these network addresses. + + +
const EDUPLICATE_NETWORK_ADDRESSES: u64 = 23;
+
+ + + Table to store collected transaction fees for each validator already exists. @@ -1785,6 +1832,16 @@ Cannot update stake pool's lockup to earlier than current lockup. + + +The submitted BLS multisig proof-of-possession does not verify against the multisig key. + + +
const EINVALID_PROOF_OF_POSSESSION: u64 = 24;
+
+ + + Invalid consensus public key @@ -1840,7 +1897,7 @@ Validators cannot join or leave post genesis on this test network. Signer does not have permission to perform stake logic. -
const ENO_STAKE_PERMISSION: u64 = 28;
+
const ENO_STAKE_PERMISSION: u64 = 25;
 
@@ -1920,7 +1977,7 @@ Not enough stake to join validator set. Transaction fee is not fully distributed at epoch ending. -
const ETRANSACTION_FEE_NOT_FULLY_DISTRIBUTED: u64 = 29;
+
const ETRANSACTION_FEE_NOT_FULLY_DISTRIBUTED: u64 = 26;
 
@@ -2105,9 +2162,8 @@ This will throw an error if there's no stake pool at pool_address.
public fun get_remaining_lockup_secs(pool_address: address): u64 acquires StakePool {
     assert_stake_pool_exists(pool_address);
     let lockup_time = borrow_global<StakePool>(pool_address).locked_until_secs;
-    if (lockup_time <= timestamp::now_seconds()) {
-        0
-    } else {
+    if (lockup_time <= timestamp::now_seconds()) { 0 }
+    else {
         lockup_time - timestamp::now_seconds()
     }
 }
@@ -2142,7 +2198,7 @@ The returned amounts are for (active, inactive, pending_active, pending_inactive
         coin::value(&stake_pool.active),
         coin::value(&stake_pool.inactive),
         coin::value(&stake_pool.pending_active),
-        coin::value(&stake_pool.pending_inactive),
+        coin::value(&stake_pool.pending_inactive)
     )
 }
 
@@ -2170,11 +2226,17 @@ Returns the validator's state.
public fun get_validator_state(pool_address: address): u64 acquires ValidatorSet {
     let validator_set = borrow_global<ValidatorSet>(@supra_framework);
-    if (option::is_some(&find_validator(&validator_set.pending_active, pool_address))) {
+    if (option::is_some(
+        &find_validator(&validator_set.pending_active, pool_address)
+    )) {
         VALIDATOR_STATUS_PENDING_ACTIVE
-    } else if (option::is_some(&find_validator(&validator_set.active_validators, pool_address))) {
+    } else if (option::is_some(
+        &find_validator(&validator_set.active_validators, pool_address)
+    )) {
         VALIDATOR_STATUS_ACTIVE
-    } else if (option::is_some(&find_validator(&validator_set.pending_inactive, pool_address))) {
+    } else if (option::is_some(
+        &find_validator(&validator_set.pending_inactive, pool_address)
+    )) {
         VALIDATOR_STATUS_PENDING_INACTIVE
     } else {
         VALIDATOR_STATUS_INACTIVE
@@ -2204,17 +2266,20 @@ This is the same as the validator's total active and pending_inactive stake.
 Implementation
 
 
-
public fun get_current_epoch_voting_power(pool_address: address): u64 acquires StakePool, ValidatorSet {
+
public fun get_current_epoch_voting_power(
+    pool_address: address
+): u64 acquires StakePool, ValidatorSet {
     assert_stake_pool_exists(pool_address);
     let validator_state = get_validator_state(pool_address);
     // Both active and pending inactive validators can still vote in the current epoch.
-    if (validator_state == VALIDATOR_STATUS_ACTIVE || validator_state == VALIDATOR_STATUS_PENDING_INACTIVE) {
-        let active_stake = coin::value(&borrow_global<StakePool>(pool_address).active);
-        let pending_inactive_stake = coin::value(&borrow_global<StakePool>(pool_address).pending_inactive);
+    if (validator_state == VALIDATOR_STATUS_ACTIVE
+        || validator_state == VALIDATOR_STATUS_PENDING_INACTIVE) {
+        let active_stake =
+            coin::value(&borrow_global<StakePool>(pool_address).active);
+        let pending_inactive_stake =
+            coin::value(&borrow_global<StakePool>(pool_address).pending_inactive);
         active_stake + pending_inactive_stake
-    } else {
-        0
-    }
+    } else { 0 }
 }
 
@@ -2345,10 +2410,18 @@ Return the number of successful and failed proposals for the proposal at the giv Implementation -
public fun get_current_epoch_proposal_counts(validator_index: u64): (u64, u64) acquires ValidatorPerformance {
-    let validator_performances = &borrow_global<ValidatorPerformance>(@supra_framework).validators;
-    let validator_performance = vector::borrow(validator_performances, validator_index);
-    (validator_performance.successful_proposals, validator_performance.failed_proposals)
+
public fun get_current_epoch_proposal_counts(
+    validator_index: u64
+): (u64, u64) acquires ValidatorPerformance {
+    let validator_performances =
+        &borrow_global<ValidatorPerformance>(@supra_framework).validators;
+    let validator_performance = vector::borrow(
+        validator_performances, validator_index
+    );
+    (
+        validator_performance.successful_proposals,
+        validator_performance.failed_proposals
+    )
 }
 
@@ -2378,7 +2451,11 @@ Return the validator's config. ): (vector<u8>, vector<u8>, vector<u8>) acquires ValidatorConfig { assert_stake_pool_exists(pool_address); let validator_config = borrow_global<ValidatorConfig>(pool_address); - (validator_config.consensus_pubkey, validator_config.network_addresses, validator_config.fullnode_addresses) + ( + validator_config.consensus_pubkey, + validator_config.network_addresses, + validator_config.fullnode_addresses + ) }
@@ -2465,18 +2542,19 @@ Initialize validator set to the core resource account.
public(friend) fun initialize(supra_framework: &signer) {
     system_addresses::assert_supra_framework(supra_framework);
 
-    move_to(supra_framework, ValidatorSet {
-        consensus_scheme: 0,
-        active_validators: vector::empty(),
-        pending_active: vector::empty(),
-        pending_inactive: vector::empty(),
-        total_voting_power: 0,
-        total_joining_power: 0,
-    });
-
-    move_to(supra_framework, ValidatorPerformance {
-        validators: vector::empty(),
-    });
+    move_to(
+        supra_framework,
+        ValidatorSet {
+            consensus_scheme: 0,
+            active_validators: vector::empty(),
+            pending_active: vector::empty(),
+            pending_inactive: vector::empty(),
+            total_voting_power: 0,
+            total_joining_power: 0
+        }
+    );
+
+    move_to(supra_framework, ValidatorPerformance { validators: vector::empty() });
 }
 
@@ -2501,7 +2579,9 @@ Beyond genesis, no one can create SupraCoin mint/burn capabilities. Implementation -
public(friend) fun store_supra_coin_mint_cap(supra_framework: &signer, mint_cap: MintCapability<SupraCoin>) {
+
public(friend) fun store_supra_coin_mint_cap(
+    supra_framework: &signer, mint_cap: MintCapability<SupraCoin>
+) {
     system_addresses::assert_supra_framework(supra_framework);
     move_to(supra_framework, SupraCoinCapabilities { mint_cap })
 }
@@ -2509,6 +2589,135 @@ Beyond genesis, no one can create SupraCoin mint/burn capabilities.
 
 
 
+
+
+
+
+## Function `get_pool_address_from_index`
+
+To get validator pool address from validator index
+
+
+
public(friend) fun get_pool_address_from_index(index: u64): option::Option<address>
+
+ + + +
+Implementation + + +
public(friend) fun get_pool_address_from_index(
+    index: u64
+): Option<address> acquires ValidatorSet {
+    if (exists<ValidatorSet>(@supra_framework)) {
+        let validator_set = borrow_global<ValidatorSet>(@supra_framework);
+        // it can happen that some validator may added a leave request in between
+        // this can change the order of indexes in active validator
+        // so need to iterate through all until find pool address in active and  pending_active
+        let (is_index_exist, i) = vector::find(
+            &validator_set.active_validators,
+            |v| {
+                let v: &ValidatorInfo = v;
+                v.config.validator_index == index
+            }
+        );
+        if (is_index_exist) {
+            let v_info = vector::borrow(&validator_set.active_validators, i);
+            return option::some(v_info.addr)
+        };
+        let (is_index_exist, i) = vector::find(
+            &validator_set.pending_inactive,
+            |v| {
+                let v: &ValidatorInfo = v;
+                v.config.validator_index == index
+            }
+        );
+        if (is_index_exist) {
+            let v_info = vector::borrow(&validator_set.pending_inactive, i);
+            return option::some(v_info.addr)
+        };
+    };
+    option::none()
+}
+
+ + + +
+ + + +## Function `get_committee_size` + +Returns committee size + + +
public(friend) fun get_committee_size(): u64
+
+ + + +
+Implementation + + +
public(friend) fun get_committee_size(): u64 acquires ValidatorSet {
+    let commitee_size = 0;
+    if (exists<ValidatorSet>(@supra_framework)) {
+        let validator_set = borrow_global<ValidatorSet>(@supra_framework);
+        commitee_size = vector::length(&validator_set.active_validators)
+            + vector::length(&validator_set.pending_inactive);
+    };
+    commitee_size
+}
+
+ + + +
+ + + +## Function `get_committee_pool_addresses` + +Returns pool addresses of current committee including pending inactive + + +
public(friend) fun get_committee_pool_addresses(): vector<address>
+
+ + + +
+Implementation + + +
public(friend) fun get_committee_pool_addresses(): vector<address> acquires ValidatorSet {
+    let pool_addresses = vector::empty();
+    if (exists<ValidatorSet>(@supra_framework)) {
+        let validator_set = borrow_global<ValidatorSet>(@supra_framework);
+        vector::for_each_ref(
+            &validator_set.active_validators,
+            |validator_info| {
+                let validator_info: &ValidatorInfo = validator_info;
+                vector::push_back(&mut pool_addresses, validator_info.addr);
+            }
+        );
+        vector::for_each_ref(
+            &validator_set.pending_inactive,
+            |validator_info| {
+                let validator_info: &ValidatorInfo = validator_info;
+                vector::push_back(&mut pool_addresses, validator_info.addr);
+            }
+        );
+    };
+    pool_addresses
+}
+
+ + +
@@ -2528,8 +2737,7 @@ Allow on chain governance to remove validators from the validator set.
public fun remove_validators(
-    supra_framework: &signer,
-    validators: &vector<address>,
+    supra_framework: &signer, validators: &vector<address>
 ) acquires ValidatorSet {
     assert_reconfig_not_in_progress();
     system_addresses::assert_supra_framework(supra_framework);
@@ -2550,14 +2758,17 @@ Allow on chain governance to remove validators from the validator set.
             invariant spec_validator_indices_are_valid(active_validators);
             invariant spec_validators_are_initialized(pending_inactive);
             invariant spec_validator_indices_are_valid(pending_inactive);
-            invariant ghost_active_num + ghost_pending_inactive_num == len(active_validators) + len(pending_inactive);
+            invariant ghost_active_num + ghost_pending_inactive_num
+                == len(active_validators) + len(pending_inactive);
         };
         i < len_validators
     }) {
         let validator = *vector::borrow(validators, i);
         let validator_index = find_validator(active_validators, validator);
         if (option::is_some(&validator_index)) {
-            let validator_info = vector::swap_remove(active_validators, *option::borrow(&validator_index));
+            let validator_info = vector::swap_remove(
+                active_validators, *option::borrow(&validator_index)
+            );
             vector::push_back(pending_inactive, validator_info);
             spec {
                 update ghost_active_num = ghost_active_num - 1;
@@ -2669,16 +2880,19 @@ to set later.
     owner: &signer,
     initial_stake_amount: u64,
     operator: address,
-    voter: address,
+    voter: address
 ) acquires AllowedValidators, OwnerCapability, StakePool, ValidatorSet {
     check_stake_permission(owner);
     initialize_owner(owner);
-    move_to(owner, ValidatorConfig {
-        consensus_pubkey: vector::empty(),
-        network_addresses: vector::empty(),
-        fullnode_addresses: vector::empty(),
-        validator_index: 0,
-    });
+    move_to(
+        owner,
+        ValidatorConfig {
+            consensus_pubkey: vector::empty(),
+            network_addresses: vector::empty(),
+            fullnode_addresses: vector::empty(),
+            validator_index: 0
+        }
+    );
 
     if (initial_stake_amount != 0) {
         add_stake(owner, initial_stake_amount);
@@ -2718,20 +2932,318 @@ Initialize the validator account and give ownership to the signing account.
     account: &signer,
     consensus_pubkey: vector<u8>,
     network_addresses: vector<u8>,
-    fullnode_addresses: vector<u8>,
-) acquires AllowedValidators {
+    fullnode_addresses: vector<u8>
+) acquires AllowedValidators, ValidatorSet, ValidatorConfig {
     check_stake_permission(account);
-    // Checks the public key is valid to prevent rogue-key attacks.
-    let valid_public_key = ed25519::new_validated_public_key_from_bytes(consensus_pubkey);
-    assert!(option::is_some(&valid_public_key), error::invalid_argument(EINVALID_PUBLIC_KEY));
+    initialize_validator_internal(
+        account,
+        consensus_pubkey,
+        network_addresses,
+        fullnode_addresses,
+        false
+    );
+}
+
- initialize_owner(account); - move_to(account, ValidatorConfig { + + + + + + +## Function `initialize_validator_genesis` + +Initialize a validator during genesis. Identical to initialize_validator except that the +consensus key blob is trusted genesis output and therefore carries no operator +proof-of-possession (mirrors rotate_consensus_key / rotate_consensus_key_genesis). + + +
public(friend) fun initialize_validator_genesis(account: &signer, consensus_pubkey: vector<u8>, network_addresses: vector<u8>, fullnode_addresses: vector<u8>)
+
+ + + +
+Implementation + + +
public(friend) fun initialize_validator_genesis(
+    account: &signer,
+    consensus_pubkey: vector<u8>,
+    network_addresses: vector<u8>,
+    fullnode_addresses: vector<u8>
+) acquires AllowedValidators, ValidatorSet, ValidatorConfig {
+    initialize_validator_internal(
+        account,
         consensus_pubkey,
         network_addresses,
         fullnode_addresses,
-        validator_index: 0,
-    });
+        true
+    );
+}
+
+ + + +
+ + + +## Function `initialize_validator_internal` + + + +
fun initialize_validator_internal(account: &signer, consensus_pubkey: vector<u8>, network_addresses: vector<u8>, fullnode_addresses: vector<u8>, genesis: bool)
+
+ + + +
+Implementation + + +
fun initialize_validator_internal(
+    account: &signer,
+    consensus_pubkey: vector<u8>,
+    network_addresses: vector<u8>,
+    fullnode_addresses: vector<u8>,
+    genesis: bool
+) acquires AllowedValidators, ValidatorSet, ValidatorConfig {
+    // Verify the keys (and, for operator submissions, the appended BLS multisig PoP) and keep
+    // only the canonical key bytes (any appended PoP is stripped before storage).
+    let consensus_pubkey = validate_consensus_public_key(consensus_pubkey, genesis);
+    let account_addr = signer::address_of(account);
+    assert_consensus_pubkey_unique_in_next_validator_set(
+        account_addr, &consensus_pubkey
+    );
+    assert_network_addresses_unique_in_next_validator_set(
+        account_addr, &network_addresses
+    );
+    initialize_owner(account);
+    move_to(
+        account,
+        ValidatorConfig {
+            consensus_pubkey,
+            network_addresses,
+            fullnode_addresses,
+            validator_index: 0
+        }
+    );
+}
+
+ + + +
+ + + +## Function `validate_consensus_public_key` + + + +
fun validate_consensus_public_key(consensus_pubkey: vector<u8>, genesis: bool): vector<u8>
+
+ + + +
+Implementation + + +
fun validate_consensus_public_key(
+    consensus_pubkey: vector<u8>, genesis: bool
+): vector<u8> {
+    // Legacy format (only acceptable before v2): a bare ed25519 key with no aggregatable BLS
+    // key, hence no PoP. Accept and store it unchanged.
+    if (!std::features::supra_validator_identity_v2_enabled()) {
+        let maybe_legacy =
+            ed25519::new_validated_public_key_from_bytes(consensus_pubkey);
+        if (option::is_some(&maybe_legacy)) {
+            return consensus_pubkey
+        };
+    };
+
+    // New identity format (v2, or a pre-v2 early-migration submission). Operator (non-genesis)
+    // submissions carry an appended BLS multisig PoP; verify and strip it. Genesis is exempt.
+    let (keys_bytes, maybe_pop) =
+        if (genesis) {
+            (consensus_pubkey, option::none<vector<u8>>())
+        } else {
+            let (keys_bytes, pop) =
+                validator_public_keys::split_consensus_key_and_pop(consensus_pubkey);
+            (keys_bytes, option::some(pop))
+        };
+
+    let valid_public_keys =
+        validator_public_keys::validator_public_keys_from_bytes(keys_bytes);
+
+    if (option::is_some(&maybe_pop)) {
+        assert!(
+            validator_public_keys::verify_bls_multisig_pop(
+                &valid_public_keys, option::extract(&mut maybe_pop)
+            ),
+            error::invalid_argument(EINVALID_PROOF_OF_POSSESSION)
+        );
+    };
+
+    assert!(
+        validator_public_keys::validate_static_keys(&valid_public_keys),
+        error::invalid_argument(EINVALID_PUBLIC_KEY)
+    );
+
+    keys_bytes
+}
+
+ + + +
+ + + +## Function `assert_consensus_pubkey_unique_in_next_validator_set` + +Aborts if any validator other than self_addr in the next validator set +(the union of active_validators and pending_active) already uses +consensus_pubkey as its latest on-chain consensus key. + + +
fun assert_consensus_pubkey_unique_in_next_validator_set(self_addr: address, consensus_pubkey: &vector<u8>)
+
+ + + +
+Implementation + + +
fun assert_consensus_pubkey_unique_in_next_validator_set(
+    self_addr: address, consensus_pubkey: &vector<u8>
+) acquires ValidatorSet, ValidatorConfig {
+    let validator_set = borrow_global<ValidatorSet>(@supra_framework);
+    assert_consensus_pubkey_unique_in_validator_list(
+        self_addr, consensus_pubkey, &validator_set.active_validators
+    );
+    assert_consensus_pubkey_unique_in_validator_list(
+        self_addr, consensus_pubkey, &validator_set.pending_active
+    );
+}
+
+ + + +
+ + + +## Function `assert_consensus_pubkey_unique_in_validator_list` + + + +
fun assert_consensus_pubkey_unique_in_validator_list(self_addr: address, consensus_pubkey: &vector<u8>, validators: &vector<stake::ValidatorInfo>)
+
+ + + +
+Implementation + + +
fun assert_consensus_pubkey_unique_in_validator_list(
+    self_addr: address,
+    consensus_pubkey: &vector<u8>,
+    validators: &vector<ValidatorInfo>
+) acquires ValidatorConfig {
+    let len = vector::length(validators);
+    let i = 0;
+    while (i < len) {
+        let other = vector::borrow(validators, i);
+        if (other.addr != self_addr && exists<ValidatorConfig>(other.addr)) {
+            let other_config = borrow_global<ValidatorConfig>(other.addr);
+            assert!(
+                other_config.consensus_pubkey != *consensus_pubkey,
+                error::invalid_argument(EDUPLICATE_CONSENSUS_PUBKEY)
+            );
+        };
+        i = i + 1;
+    };
+}
+
+ + + +
+ + + +## Function `assert_network_addresses_unique_in_next_validator_set` + +Aborts if any validator other than self_addr in the next validator set +already uses network_addresses. Empty network_addresses is treated +as "unset" and skips the check. + + +
fun assert_network_addresses_unique_in_next_validator_set(self_addr: address, network_addresses: &vector<u8>)
+
+ + + +
+Implementation + + +
fun assert_network_addresses_unique_in_next_validator_set(
+    self_addr: address, network_addresses: &vector<u8>
+) acquires ValidatorSet, ValidatorConfig {
+    if (vector::is_empty(network_addresses)) { return };
+    let validator_set = borrow_global<ValidatorSet>(@supra_framework);
+    assert_network_addresses_unique_in_validator_list(
+        self_addr, network_addresses, &validator_set.active_validators
+    );
+    assert_network_addresses_unique_in_validator_list(
+        self_addr, network_addresses, &validator_set.pending_active
+    );
+}
+
+ + + +
+ + + +## Function `assert_network_addresses_unique_in_validator_list` + + + +
fun assert_network_addresses_unique_in_validator_list(self_addr: address, network_addresses: &vector<u8>, validators: &vector<stake::ValidatorInfo>)
+
+ + + +
+Implementation + + +
fun assert_network_addresses_unique_in_validator_list(
+    self_addr: address,
+    network_addresses: &vector<u8>,
+    validators: &vector<ValidatorInfo>
+) acquires ValidatorConfig {
+    let len = vector::length(validators);
+    let i = 0;
+    while (i < len) {
+        let other = vector::borrow(validators, i);
+        if (other.addr != self_addr && exists<ValidatorConfig>(other.addr)) {
+            let other_config = borrow_global<ValidatorConfig>(other.addr);
+            assert!(
+                other_config.network_addresses != *network_addresses,
+                error::invalid_argument(EDUPLICATE_NETWORK_ADDRESSES)
+            );
+        };
+        i = i + 1;
+    };
 }
 
@@ -2758,32 +3270,48 @@ Initialize the validator account and give ownership to the signing account. check_stake_permission(owner); let owner_address = signer::address_of(owner); assert!(is_allowed(owner_address), error::not_found(EINELIGIBLE_VALIDATOR)); - assert!(!stake_pool_exists(owner_address), error::already_exists(EALREADY_REGISTERED)); - - move_to(owner, StakePool { - active: coin::zero<SupraCoin>(), - pending_active: coin::zero<SupraCoin>(), - pending_inactive: coin::zero<SupraCoin>(), - inactive: coin::zero<SupraCoin>(), - locked_until_secs: 0, - operator_address: owner_address, - delegated_voter: owner_address, - // Events. - initialize_validator_events: account::new_event_handle<RegisterValidatorCandidateEvent>(owner), - set_operator_events: account::new_event_handle<SetOperatorEvent>(owner), - add_stake_events: account::new_event_handle<AddStakeEvent>(owner), - reactivate_stake_events: account::new_event_handle<ReactivateStakeEvent>(owner), - rotate_consensus_key_events: account::new_event_handle<RotateConsensusKeyEvent>(owner), - update_network_and_fullnode_addresses_events: account::new_event_handle<UpdateNetworkAndFullnodeAddressesEvent>( - owner - ), - increase_lockup_events: account::new_event_handle<IncreaseLockupEvent>(owner), - join_validator_set_events: account::new_event_handle<JoinValidatorSetEvent>(owner), - distribute_rewards_events: account::new_event_handle<DistributeRewardsEvent>(owner), - unlock_stake_events: account::new_event_handle<UnlockStakeEvent>(owner), - withdraw_stake_events: account::new_event_handle<WithdrawStakeEvent>(owner), - leave_validator_set_events: account::new_event_handle<LeaveValidatorSetEvent>(owner), - }); + assert!( + !stake_pool_exists(owner_address), + error::already_exists(EALREADY_REGISTERED) + ); + + move_to( + owner, + StakePool { + active: coin::zero<SupraCoin>(), + pending_active: coin::zero<SupraCoin>(), + pending_inactive: coin::zero<SupraCoin>(), + inactive: coin::zero<SupraCoin>(), + locked_until_secs: 0, + operator_address: owner_address, + delegated_voter: owner_address, + // Events. + initialize_validator_events: account::new_event_handle< + RegisterValidatorCandidateEvent>(owner), + set_operator_events: account::new_event_handle<SetOperatorEvent>(owner), + add_stake_events: account::new_event_handle<AddStakeEvent>(owner), + reactivate_stake_events: account::new_event_handle<ReactivateStakeEvent>( + owner + ), + rotate_consensus_key_events: account::new_event_handle< + RotateConsensusKeyEvent>(owner), + update_network_and_fullnode_addresses_events: account::new_event_handle< + UpdateNetworkAndFullnodeAddressesEvent>(owner), + increase_lockup_events: account::new_event_handle<IncreaseLockupEvent>( + owner + ), + join_validator_set_events: account::new_event_handle<JoinValidatorSetEvent>( + owner + ), + distribute_rewards_events: account::new_event_handle<DistributeRewardsEvent>( + owner + ), + unlock_stake_events: account::new_event_handle<UnlockStakeEvent>(owner), + withdraw_stake_events: account::new_event_handle<WithdrawStakeEvent>(owner), + leave_validator_set_events: account::new_event_handle< + LeaveValidatorSetEvent>(owner) + } + ); move_to(owner, OwnerCapability { pool_address: owner_address }); } @@ -2838,9 +3366,14 @@ staking pool. Implementation -
public fun deposit_owner_cap(owner: &signer, owner_cap: OwnerCapability) {
+
public fun deposit_owner_cap(
+    owner: &signer, owner_cap: OwnerCapability
+) {
     check_stake_permission(owner);
-    assert!(!exists<OwnerCapability>(signer::address_of(owner)), error::not_found(EOWNER_CAP_ALREADY_EXISTS));
+    assert!(
+        !exists<OwnerCapability>(signer::address_of(owner)),
+        error::not_found(EOWNER_CAP_ALREADY_EXISTS)
+    );
     move_to(owner, owner_cap);
 }
 
@@ -2890,7 +3423,9 @@ Allows an owner to change the operator of the stake pool. Implementation -
public entry fun set_operator(owner: &signer, new_operator: address) acquires OwnerCapability, StakePool {
+
public entry fun set_operator(
+    owner: &signer, new_operator: address
+) acquires OwnerCapability, StakePool {
     check_stake_permission(owner);
     let owner_address = signer::address_of(owner);
     assert_owner_cap_exists(owner_address);
@@ -2919,7 +3454,9 @@ Allows an account with ownership capability to change the operator of the stake
 Implementation
 
 
-
public fun set_operator_with_cap(owner_cap: &OwnerCapability, new_operator: address) acquires StakePool {
+
public fun set_operator_with_cap(
+    owner_cap: &OwnerCapability, new_operator: address
+) acquires StakePool {
     let pool_address = owner_cap.pool_address;
     assert_stake_pool_exists(pool_address);
     let stake_pool = borrow_global_mut<StakePool>(pool_address);
@@ -2967,7 +3504,9 @@ Allows an owner to change the delegated voter of the stake pool.
 Implementation
 
 
-
public entry fun set_delegated_voter(owner: &signer, new_voter: address) acquires OwnerCapability, StakePool {
+
public entry fun set_delegated_voter(
+    owner: &signer, new_voter: address
+) acquires OwnerCapability, StakePool {
     check_stake_permission(owner);
     let owner_address = signer::address_of(owner);
     assert_owner_cap_exists(owner_address);
@@ -2996,7 +3535,9 @@ Allows an owner to change the delegated voter of the stake pool.
 Implementation
 
 
-
public fun set_delegated_voter_with_cap(owner_cap: &OwnerCapability, new_voter: address) acquires StakePool {
+
public fun set_delegated_voter_with_cap(
+    owner_cap: &OwnerCapability, new_voter: address
+) acquires StakePool {
     let pool_address = owner_cap.pool_address;
     assert_stake_pool_exists(pool_address);
     let stake_pool = borrow_global_mut<StakePool>(pool_address);
@@ -3024,7 +3565,9 @@ Add amount of coins from the Implementation
 
 
-
public entry fun add_stake(owner: &signer, amount: u64) acquires OwnerCapability, StakePool, ValidatorSet {
+
public entry fun add_stake(
+    owner: &signer, amount: u64
+) acquires OwnerCapability, StakePool, ValidatorSet {
     check_stake_permission(owner);
     let owner_address = signer::address_of(owner);
     assert_owner_cap_exists(owner_address);
@@ -3053,7 +3596,9 @@ Add coins into pool_address. this requires the corresp
 Implementation
 
 
-
public fun add_stake_with_cap(owner_cap: &OwnerCapability, coins: Coin<SupraCoin>) acquires StakePool, ValidatorSet {
+
public fun add_stake_with_cap(
+    owner_cap: &OwnerCapability, coins: Coin<SupraCoin>
+) acquires StakePool, ValidatorSet {
     assert_reconfig_not_in_progress();
     let pool_address = owner_cap.pool_address;
     assert_stake_pool_exists(pool_address);
@@ -3069,8 +3614,11 @@ Add coins into pool_address. this requires the corresp
     // Inactive validator's total stake will be tracked when they join the validator set.
     let validator_set = borrow_global<ValidatorSet>(@supra_framework);
     // Search directly rather using get_validator_state to save on unnecessary loops.
-    if (option::is_some(&find_validator(&validator_set.active_validators, pool_address)) ||
-        option::is_some(&find_validator(&validator_set.pending_active, pool_address))) {
+    if (option::is_some(
+        &find_validator(&validator_set.active_validators, pool_address)
+    ) || option::is_some(
+        &find_validator(&validator_set.pending_active, pool_address)
+    )) {
         update_voting_power_increase(amount);
     };
 
@@ -3083,9 +3631,12 @@ Add coins into pool_address. this requires the corresp
         coin::merge<SupraCoin>(&mut stake_pool.active, coins);
     };
 
-    let (_, maximum_stake) = staking_config::get_required_stake(&staking_config::get());
+    let (_, maximum_stake) =
+        staking_config::get_required_stake(&staking_config::get());
     let voting_power = get_next_epoch_voting_power(stake_pool);
-    assert!(voting_power <= maximum_stake, error::invalid_argument(ESTAKE_EXCEEDS_MAX));
+    assert!(
+        voting_power <= maximum_stake, error::invalid_argument(ESTAKE_EXCEEDS_MAX)
+    );
 
     if (std::features::module_event_migration_enabled()) {
         event::emit(
@@ -3155,7 +3706,9 @@ Move amount of coins from pending_inactive to active.
 Implementation
 
 
-
public fun reactivate_stake_with_cap(owner_cap: &OwnerCapability, amount: u64) acquires StakePool {
+
public fun reactivate_stake_with_cap(
+    owner_cap: &OwnerCapability, amount: u64
+) acquires StakePool {
     assert_reconfig_not_in_progress();
     let pool_address = owner_cap.pool_address;
     assert_stake_pool_exists(pool_address);
@@ -3213,26 +3766,66 @@ Move amount of coins from pending_inactive to active.
     operator: &signer,
     pool_address: address,
     new_consensus_pubkey: vector<u8>,
-    genesis: bool,
-) acquires StakePool, ValidatorConfig {
+    genesis: bool
+) acquires StakePool, ValidatorConfig, ValidatorSet {
     check_stake_permission(operator);
     assert_reconfig_not_in_progress();
     assert_stake_pool_exists(pool_address);
 
     let stake_pool = borrow_global_mut<StakePool>(pool_address);
-    assert!(signer::address_of(operator) == stake_pool.operator_address, error::unauthenticated(ENOT_OPERATOR));
+    assert!(
+        signer::address_of(operator) == stake_pool.operator_address,
+        error::unauthenticated(ENOT_OPERATOR)
+    );
 
-    assert!(exists<ValidatorConfig>(pool_address), error::not_found(EVALIDATOR_CONFIG));
+    assert!(
+        exists<ValidatorConfig>(pool_address),
+        error::not_found(EVALIDATOR_CONFIG)
+    );
+    // Verify the keys (and, for operator submissions, the appended BLS multisig PoP) and keep
+    // only the canonical key bytes (any appended PoP is stripped before storage/merge).
+    let new_consensus_pubkey =
+        validate_consensus_public_key(new_consensus_pubkey, genesis);
+    assert_consensus_pubkey_unique_in_next_validator_set(
+        pool_address, &new_consensus_pubkey
+    );
     let validator_info = borrow_global_mut<ValidatorConfig>(pool_address);
     let old_consensus_pubkey = validator_info.consensus_pubkey;
-    // Checks the public key is valid to prevent rogue-key attacks.
-    if (!genesis) {
-        let validated_public_key = ed25519::new_validated_public_key_from_bytes(new_consensus_pubkey);
-        assert!(option::is_some(&validated_public_key), error::invalid_argument(EINVALID_PUBLIC_KEY));
-    } else {
-        let validated_public_key = ed25519::new_validated_public_key_from_bytes(new_consensus_pubkey);
-        assert!(option::is_some(&validated_public_key), error::invalid_argument(EINVALID_PUBLIC_KEY));
-    };
+
+    // Preserve the DKG-managed BLS threshold keys: an operator rotation must only change the
+    // static keys. We load the current on-chain keys and copy in only the operator-supplied
+    // static keys, leaving the threshold keys (written by `set_dkg_output_keys`) intact.
+    //
+    // The merge is skipped (and the incoming blob stored verbatim, preserving the original
+    // behavior) when there is nothing to preserve or the stored blob cannot be parsed:
+    //  - before v2: the stored blob may be a legacy ed25519 key with no threshold keys;
+    //  - genesis: no DKG threshold keys exist yet;
+    //  - an empty stored key: a validator initialized via `initialize_stake_owner` sets its key
+    //    for the first time here, so there is no prior `ValidatorPublicKeys` to merge into
+    //    (parsing the empty blob would abort).
+    // Under v2 a non-empty stored blob is guaranteed to be a valid `ValidatorPublicKeys` (the
+    // feature is only enabled once all validators have migrated to the new format), and
+    // `validate_consensus_public_key` has already verified the incoming blob, so both
+    // deserializations are safe.
+    let new_consensus_pubkey =
+        if (!genesis
+            && std::features::supra_validator_identity_v2_enabled()
+            && !vector::is_empty(&old_consensus_pubkey)) {
+            let current_keys =
+                validator_public_keys::validator_public_keys_from_bytes(
+                    old_consensus_pubkey
+                );
+            let incoming_keys =
+                validator_public_keys::validator_public_keys_from_bytes(
+                    new_consensus_pubkey
+                );
+            validator_public_keys::replace_static_keys(
+                &mut current_keys, &incoming_keys
+            );
+            validator_public_keys::public_key_to_bytes(current_keys)
+        } else {
+            new_consensus_pubkey
+        };
     validator_info.consensus_pubkey = new_consensus_pubkey;
 
     if (std::features::module_event_migration_enabled()) {
@@ -3240,8 +3833,8 @@ Move amount of coins from pending_inactive to active.
             RotateConsensusKey {
                 pool_address,
                 old_consensus_pubkey,
-                new_consensus_pubkey,
-            },
+                new_consensus_pubkey
+            }
         );
     } else {
         event::emit_event(
@@ -3249,9 +3842,122 @@ Move amount of coins from pending_inactive to active.
             RotateConsensusKeyEvent {
                 pool_address,
                 old_consensus_pubkey,
-                new_consensus_pubkey,
-            },
+                new_consensus_pubkey
+            }
         );
+    }
+}
+
+ + + +
+ + + +## Function `set_dkg_output_keys` + +Set DKG output keys for all provided threshold types. +Each DkgCommitteeOutput contains a threshold_type and corresponding keys for all validators. + + +
public(friend) fun set_dkg_output_keys(committee_outputs: vector<dkg_committee::DkgCommitteeOutput>)
+
+ + + +
+Implementation + + +
public(friend) fun set_dkg_output_keys(
+    committee_outputs: vector<dkg_committee::DkgCommitteeOutput>
+) acquires ValidatorConfig, ValidatorPerformance, ValidatorSet, StakePool {
+    if (vector::is_empty(&committee_outputs)) { return };
+
+    let next_validator_infos = next_validator_consensus_infos();
+    let num_validators = vector::length(&next_validator_infos);
+
+    // Validate all committee outputs have correct number of keys
+    let num_outputs = vector::length(&committee_outputs);
+    let j = 0;
+    while (j < num_outputs) {
+        let output = vector::borrow(&committee_outputs, j);
+        assert!(
+            num_validators
+                == vector::length(
+                    &dkg_committee::get_dkg_committee_output_keys(output)
+                ),
+            error::invalid_argument(EDKG_INVALID_PK_SHARES)
+        );
+        j = j + 1;
+    };
+
+    // Iterate over each validator
+    let i = 0;
+    while (i < num_validators) {
+        let val_info = vector::borrow(&next_validator_infos, i);
+        let addr = validator_consensus_info::get_addr(val_info);
+        let validator_config = borrow_global_mut<ValidatorConfig>(addr);
+        let old_consensus_pubkey = validator_config.consensus_pubkey;
+
+        // Load current public keys
+        let pub_keys =
+            validator_public_keys::validator_public_keys_from_bytes(
+                old_consensus_pubkey
+            );
+
+        // Apply all threshold key updates for this validator
+        let k = 0;
+        while (k < num_outputs) {
+            let output = vector::borrow(&committee_outputs, k);
+            let output_keys = dkg_committee::get_dkg_committee_output_keys(output);
+            let key_bytes = vector::borrow(&output_keys, i);
+
+            // Deserialize the key
+            let key_opt = aptos_std::bls12381::public_key_from_bytes(*key_bytes);
+            assert!(
+                option::is_some(&key_opt),
+                error::invalid_argument(EINVALID_PUBLIC_KEY)
+            );
+            let new_key = option::extract(&mut key_opt);
+
+            // Rotate the key based on threshold type
+            validator_public_keys::rotate_supra_bls_threshold_key_by_type(
+                &mut pub_keys,
+                dkg_committee::get_dkg_committee_output_threshold_type(output),
+                new_key
+            );
+            k = k + 1;
+        };
+
+        // Serialize and save updated keys
+        let new_consensus_pubkey =
+            validator_public_keys::public_key_to_bytes(pub_keys);
+        validator_config.consensus_pubkey = new_consensus_pubkey;
+
+        // Emit events
+        let stake_pool = borrow_global_mut<StakePool>(addr);
+        if (std::features::module_event_migration_enabled()) {
+            event::emit(
+                RotateConsensusKey {
+                    pool_address: addr,
+                    old_consensus_pubkey,
+                    new_consensus_pubkey
+                }
+            );
+        } else {
+            event::emit_event(
+                &mut stake_pool.rotate_consensus_key_events,
+                RotateConsensusKeyEvent {
+                    pool_address: addr,
+                    old_consensus_pubkey,
+                    new_consensus_pubkey
+                }
+            );
+        };
+
+        i = i + 1;
     };
 }
 
@@ -3279,11 +3985,14 @@ only for genesis
public(friend) fun rotate_consensus_key_genesis(
-    operator: &signer,
-    pool_address: address,
-    new_consensus_pubkey: vector<u8>,
-) acquires StakePool, ValidatorConfig {
-    rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, true);
+    operator: &signer, pool_address: address, new_consensus_pubkey: vector<u8>
+) acquires StakePool, ValidatorConfig, ValidatorSet {
+    rotate_consensus_key_internal(
+        operator,
+        pool_address,
+        new_consensus_pubkey,
+        true
+    );
 }
 
@@ -3308,11 +4017,14 @@ Rotate the consensus key of the validator, it'll take effect in next epoch.
public entry fun rotate_consensus_key(
-    operator: &signer,
-    pool_address: address,
-    new_consensus_pubkey: vector<u8>,
-) acquires StakePool, ValidatorConfig {
-    rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, false);
+    operator: &signer, pool_address: address, new_consensus_pubkey: vector<u8>
+) acquires StakePool, ValidatorConfig, ValidatorSet {
+    rotate_consensus_key_internal(
+        operator,
+        pool_address,
+        new_consensus_pubkey,
+        false
+    );
 }
 
@@ -3340,14 +4052,23 @@ Update the network and full node addresses of the validator. This only takes eff operator: &signer, pool_address: address, new_network_addresses: vector<u8>, - new_fullnode_addresses: vector<u8>, -) acquires StakePool, ValidatorConfig { + new_fullnode_addresses: vector<u8> +) acquires StakePool, ValidatorConfig, ValidatorSet { check_stake_permission(operator); assert_reconfig_not_in_progress(); assert_stake_pool_exists(pool_address); let stake_pool = borrow_global_mut<StakePool>(pool_address); - assert!(signer::address_of(operator) == stake_pool.operator_address, error::unauthenticated(ENOT_OPERATOR)); - assert!(exists<ValidatorConfig>(pool_address), error::not_found(EVALIDATOR_CONFIG)); + assert!( + signer::address_of(operator) == stake_pool.operator_address, + error::unauthenticated(ENOT_OPERATOR) + ); + assert!( + exists<ValidatorConfig>(pool_address), + error::not_found(EVALIDATOR_CONFIG) + ); + assert_network_addresses_unique_in_next_validator_set( + pool_address, &new_network_addresses + ); let validator_info = borrow_global_mut<ValidatorConfig>(pool_address); let old_network_addresses = validator_info.network_addresses; validator_info.network_addresses = new_network_addresses; @@ -3361,8 +4082,8 @@ Update the network and full node addresses of the validator. This only takes eff old_network_addresses, new_network_addresses, old_fullnode_addresses, - new_fullnode_addresses, - }, + new_fullnode_addresses + } ); } else { event::emit_event( @@ -3372,8 +4093,8 @@ Update the network and full node addresses of the validator. This only takes eff old_network_addresses, new_network_addresses, old_fullnode_addresses, - new_fullnode_addresses, - }, + new_fullnode_addresses + } ); }; } @@ -3436,8 +4157,13 @@ directly inactive if it's not from an active validator. let stake_pool = borrow_global_mut<StakePool>(pool_address); let old_locked_until_secs = stake_pool.locked_until_secs; - let new_locked_until_secs = timestamp::now_seconds() + staking_config::get_recurring_lockup_duration(&config); - assert!(old_locked_until_secs < new_locked_until_secs, error::invalid_argument(EINVALID_LOCKUP)); + let new_locked_until_secs = + timestamp::now_seconds() + + staking_config::get_recurring_lockup_duration(&config); + assert!( + old_locked_until_secs < new_locked_until_secs, + error::invalid_argument(EINVALID_LOCKUP) + ); stake_pool.locked_until_secs = new_locked_until_secs; if (std::features::module_event_migration_enabled()) { @@ -3445,8 +4171,8 @@ directly inactive if it's not from an active validator. IncreaseLockup { pool_address, old_locked_until_secs, - new_locked_until_secs, - }, + new_locked_until_secs + } ); } else { event::emit_event( @@ -3454,8 +4180,8 @@ directly inactive if it's not from an active validator. IncreaseLockupEvent { pool_address, old_locked_until_secs, - new_locked_until_secs, - }, + new_locked_until_secs + } ); } } @@ -3482,13 +4208,12 @@ This can only called by the operator of the validator/staking pool.
public entry fun join_validator_set(
-    operator: &signer,
-    pool_address: address
+    operator: &signer, pool_address: address
 ) acquires StakePool, ValidatorConfig, ValidatorSet {
     check_stake_permission(operator);
     assert!(
         staking_config::get_allow_validator_set_change(&staking_config::get()),
-        error::invalid_argument(ENO_POST_GENESIS_VALIDATOR_SET_CHANGE_ALLOWED),
+        error::invalid_argument(ENO_POST_GENESIS_VALIDATOR_SET_CHANGE_ALLOWED)
     );
 
     join_validator_set_internal(operator, pool_address);
@@ -3521,16 +4246,18 @@ This internal version can only be called by the Genesis module during Genesis.
 
 
 
public(friend) fun join_validator_set_internal(
-    operator: &signer,
-    pool_address: address
+    operator: &signer, pool_address: address
 ) acquires StakePool, ValidatorConfig, ValidatorSet {
     assert_reconfig_not_in_progress();
     assert_stake_pool_exists(pool_address);
     let stake_pool = borrow_global_mut<StakePool>(pool_address);
-    assert!(signer::address_of(operator) == stake_pool.operator_address, error::unauthenticated(ENOT_OPERATOR));
+    assert!(
+        signer::address_of(operator) == stake_pool.operator_address,
+        error::unauthenticated(ENOT_OPERATOR)
+    );
     assert!(
         get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE,
-        error::invalid_state(EALREADY_ACTIVE_VALIDATOR),
+        error::invalid_state(EALREADY_ACTIVE_VALIDATOR)
     );
 
     let config = staking_config::get();
@@ -3544,7 +4271,10 @@ This internal version can only be called by the Genesis module during Genesis.
 
     // Add validator to pending_active, to be activated in the next epoch.
     let validator_config = borrow_global<ValidatorConfig>(pool_address);
-    assert!(!vector::is_empty(&validator_config.consensus_pubkey), error::invalid_argument(EINVALID_PUBLIC_KEY));
+    assert!(
+        !vector::is_empty(&validator_config.consensus_pubkey),
+        error::invalid_argument(EINVALID_PUBLIC_KEY)
+    );
 
     // Validate the current validator set size has not exceeded the limit.
     let validator_set = borrow_global_mut<ValidatorSet>(@supra_framework);
@@ -3552,17 +4282,19 @@ This internal version can only be called by the Genesis module during Genesis.
         &mut validator_set.pending_active,
         generate_validator_info(pool_address, stake_pool, *validator_config)
     );
-    let validator_set_size = vector::length(&validator_set.active_validators) + vector::length(
-        &validator_set.pending_active
+    let validator_set_size = vector::length(&validator_set.active_validators)
+        + vector::length(&validator_set.pending_active);
+    assert!(
+        validator_set_size <= MAX_VALIDATOR_SET_SIZE,
+        error::invalid_argument(EVALIDATOR_SET_TOO_LARGE)
     );
-    assert!(validator_set_size <= MAX_VALIDATOR_SET_SIZE, error::invalid_argument(EVALIDATOR_SET_TOO_LARGE));
 
     if (std::features::module_event_migration_enabled()) {
         event::emit(JoinValidatorSet { pool_address });
     } else {
         event::emit_event(
             &mut stake_pool.join_validator_set_events,
-            JoinValidatorSetEvent { pool_address },
+            JoinValidatorSetEvent { pool_address }
         );
     }
 }
@@ -3621,9 +4353,7 @@ Unlock amount from the active stake. Only possible if the lockup ha
 
public fun unlock_with_cap(amount: u64, owner_cap: &OwnerCapability) acquires StakePool {
     assert_reconfig_not_in_progress();
     // Short-circuit if amount to unlock is 0 so we don't emit events.
-    if (amount == 0) {
-        return
-    };
+    if (amount == 0) { return };
 
     // Unlocked coins are moved to pending_inactive. When the current lockup cycle expires, they will be moved into
     // inactive in the earliest possible epoch transition.
@@ -3675,8 +4405,7 @@ Withdraw from account's inacti
 
 
 
public entry fun withdraw(
-    owner: &signer,
-    withdraw_amount: u64
+    owner: &signer, withdraw_amount: u64
 ) acquires OwnerCapability, StakePool, ValidatorSet {
     check_stake_permission(owner);
     let owner_address = signer::address_of(owner);
@@ -3708,8 +4437,7 @@ Withdraw from pool_address's inactive stake with the corresponding
 
 
 
public fun withdraw_with_cap(
-    owner_cap: &OwnerCapability,
-    withdraw_amount: u64
+    owner_cap: &OwnerCapability, withdraw_amount: u64
 ): Coin<SupraCoin> acquires StakePool, ValidatorSet {
     assert_reconfig_not_in_progress();
     let pool_address = owner_cap.pool_address;
@@ -3718,9 +4446,10 @@ Withdraw from pool_address's inactive stake with the corresponding
     // There's an edge case where a validator unlocks their stake and leaves the validator set before
     // the stake is fully unlocked (the current lockup cycle has not expired yet).
     // This can leave their stake stuck in pending_inactive even after the current lockup cycle expires.
-    if (get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE &&
-        timestamp::now_seconds() >= stake_pool.locked_until_secs) {
-        let pending_inactive_stake = coin::extract_all(&mut stake_pool.pending_inactive);
+    if (get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE
+        && timestamp::now_seconds() >= stake_pool.locked_until_secs) {
+        let pending_inactive_stake =
+            coin::extract_all(&mut stake_pool.pending_inactive);
         coin::merge(&mut stake_pool.inactive, pending_inactive_stake);
     };
 
@@ -3775,28 +4504,33 @@ Can only be called by the operator of the validator/staking pool.
 
 
 
public entry fun leave_validator_set(
-    operator: &signer,
-    pool_address: address
+    operator: &signer, pool_address: address
 ) acquires StakePool, ValidatorSet {
     check_stake_permission(operator);
     assert_reconfig_not_in_progress();
     let config = staking_config::get();
     assert!(
         staking_config::get_allow_validator_set_change(&config),
-        error::invalid_argument(ENO_POST_GENESIS_VALIDATOR_SET_CHANGE_ALLOWED),
+        error::invalid_argument(ENO_POST_GENESIS_VALIDATOR_SET_CHANGE_ALLOWED)
     );
 
     assert_stake_pool_exists(pool_address);
     let stake_pool = borrow_global_mut<StakePool>(pool_address);
     // Account has to be the operator.
-    assert!(signer::address_of(operator) == stake_pool.operator_address, error::unauthenticated(ENOT_OPERATOR));
+    assert!(
+        signer::address_of(operator) == stake_pool.operator_address,
+        error::unauthenticated(ENOT_OPERATOR)
+    );
 
     let validator_set = borrow_global_mut<ValidatorSet>(@supra_framework);
     // If the validator is still pending_active, directly kick the validator out.
-    let maybe_pending_active_index = find_validator(&validator_set.pending_active, pool_address);
+    let maybe_pending_active_index =
+        find_validator(&validator_set.pending_active, pool_address);
     if (option::is_some(&maybe_pending_active_index)) {
         vector::swap_remove(
-            &mut validator_set.pending_active, option::extract(&mut maybe_pending_active_index));
+            &mut validator_set.pending_active,
+            option::extract(&mut maybe_pending_active_index)
+        );
 
         // Decrease the voting power increase as the pending validator's voting power was added when they requested
         // to join. Now that they changed their mind, their voting power should not affect the joining limit of this
@@ -3806,17 +4540,27 @@ Can only be called by the operator of the validator/staking pool.
         // rounding error somewhere that can lead to an underflow, we still want to allow this transaction to
         // succeed.
         if (validator_set.total_joining_power > validator_stake) {
-            validator_set.total_joining_power = validator_set.total_joining_power - validator_stake;
+            validator_set.total_joining_power =
+                validator_set.total_joining_power - validator_stake;
         } else {
             validator_set.total_joining_power = 0;
         };
     } else {
         // Validate that the validator is already part of the validator set.
-        let maybe_active_index = find_validator(&validator_set.active_validators, pool_address);
-        assert!(option::is_some(&maybe_active_index), error::invalid_state(ENOT_VALIDATOR));
+        let maybe_active_index =
+            find_validator(&validator_set.active_validators, pool_address);
+        assert!(
+            option::is_some(&maybe_active_index),
+            error::invalid_state(ENOT_VALIDATOR)
+        );
         let validator_info = vector::swap_remove(
-            &mut validator_set.active_validators, option::extract(&mut maybe_active_index));
-        assert!(vector::length(&validator_set.active_validators) != 0, error::invalid_state(ELAST_VALIDATOR));
+            &mut validator_set.active_validators,
+            option::extract(&mut maybe_active_index)
+        );
+        assert!(
+            vector::length(&validator_set.active_validators) != 0,
+            error::invalid_state(ELAST_VALIDATOR)
+        );
         vector::push_back(&mut validator_set.pending_inactive, validator_info);
 
         if (std::features::module_event_migration_enabled()) {
@@ -3858,7 +4602,8 @@ when the epoch starts.
 
public fun is_current_epoch_validator(pool_address: address): bool acquires ValidatorSet {
     assert_stake_pool_exists(pool_address);
     let validator_state = get_validator_state(pool_address);
-    validator_state == VALIDATOR_STATUS_ACTIVE || validator_state == VALIDATOR_STATUS_PENDING_INACTIVE
+    validator_state == VALIDATOR_STATUS_ACTIVE
+        || validator_state == VALIDATOR_STATUS_PENDING_INACTIVE
 }
 
@@ -3884,8 +4629,7 @@ This function cannot abort.
public(friend) fun update_performance_statistics(
-    proposer_index: Option<u64>,
-    failed_proposer_indices: vector<u64>
+    proposer_index: Option<u64>, failed_proposer_indices: vector<u64>
 ) acquires ValidatorPerformance {
     // Validator set cannot change until the end of the epoch, so the validator index in arguments should
     // match with those of the validators in ValidatorPerformance resource.
@@ -3902,7 +4646,9 @@ This function cannot abort.
         // Here, and in all other vector::borrow, skip any validator indices that are out of bounds,
         // this ensures that this function doesn't abort if there are out of bounds errors.
         if (cur_proposer_index < validator_len) {
-            let validator = vector::borrow_mut(&mut validator_perf.validators, cur_proposer_index);
+            let validator = vector::borrow_mut(
+                &mut validator_perf.validators, cur_proposer_index
+            );
             spec {
                 assume validator.successful_proposals + 1 <= MAX_U64;
             };
@@ -3915,17 +4661,25 @@ This function cannot abort.
     while ({
         spec {
             invariant len(validator_perf.validators) == validator_len;
-            invariant (option::spec_is_some(ghost_proposer_idx) && option::spec_borrow(
-                ghost_proposer_idx
-            ) < validator_len) ==>
-                (validator_perf.validators[option::spec_borrow(ghost_proposer_idx)].successful_proposals ==
-                    ghost_valid_perf.validators[option::spec_borrow(ghost_proposer_idx)].successful_proposals + 1);
+            invariant (
+                option::spec_is_some(ghost_proposer_idx)
+                    && option::spec_borrow(ghost_proposer_idx) < validator_len
+            ) ==>
+                (
+                    validator_perf.validators[option::spec_borrow(ghost_proposer_idx)]
+                    .successful_proposals
+                        == ghost_valid_perf.validators[option::spec_borrow(
+                            ghost_proposer_idx
+                        )].successful_proposals + 1
+                );
         };
         f < f_len
     }) {
         let validator_index = *vector::borrow(&failed_proposer_indices, f);
         if (validator_index < validator_len) {
-            let validator = vector::borrow_mut(&mut validator_perf.validators, validator_index);
+            let validator = vector::borrow_mut(
+                &mut validator_perf.validators, validator_index
+            );
             spec {
                 assume validator.failed_proposals + 1 <= MAX_U64;
             };
@@ -3965,24 +4719,29 @@ power.
 Implementation
 
 
-
public(friend) fun on_new_epoch(
-) acquires SupraCoinCapabilities, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet {
+
public(friend) fun on_new_epoch() acquires SupraCoinCapabilities, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet {
     let validator_set = borrow_global_mut<ValidatorSet>(@supra_framework);
     let config = staking_config::get();
     let validator_perf = borrow_global_mut<ValidatorPerformance>(@supra_framework);
 
     // Process pending stake and distribute transaction fees and rewards for each currently active validator.
-    vector::for_each_ref(&validator_set.active_validators, |validator| {
-        let validator: &ValidatorInfo = validator;
-        update_stake_pool(validator_perf, validator.addr, &config);
-    });
+    vector::for_each_ref(
+        &validator_set.active_validators,
+        |validator| {
+            let validator: &ValidatorInfo = validator;
+            update_stake_pool(validator_perf, validator.addr, &config);
+        }
+    );
 
     // Process pending stake and distribute transaction fees and rewards for each currently pending_inactive validator
     // (requested to leave but not removed yet).
-    vector::for_each_ref(&validator_set.pending_inactive, |validator| {
-        let validator: &ValidatorInfo = validator;
-        update_stake_pool(validator_perf, validator.addr, &config);
-    });
+    vector::for_each_ref(
+        &validator_set.pending_inactive,
+        |validator| {
+            let validator: &ValidatorInfo = validator;
+            update_stake_pool(validator_perf, validator.addr, &config);
+        }
+    );
 
     // Activate currently pending_active validators.
     append(&mut validator_set.active_validators, &mut validator_set.pending_active);
@@ -4005,18 +4764,23 @@ power.
         };
         i < vlen
     }) {
-        let old_validator_info = vector::borrow_mut(&mut validator_set.active_validators, i);
+        let old_validator_info = vector::borrow_mut(
+            &mut validator_set.active_validators, i
+        );
         let pool_address = old_validator_info.addr;
         let validator_config = borrow_global<ValidatorConfig>(pool_address);
         let stake_pool = borrow_global<StakePool>(pool_address);
-        let new_validator_info = generate_validator_info(pool_address, stake_pool, *validator_config);
+        let new_validator_info =
+            generate_validator_info(pool_address, stake_pool, *validator_config);
 
         // A validator needs at least the min stake required to join the validator set.
         if (new_validator_info.voting_power >= minimum_stake) {
             spec {
-                assume total_voting_power + new_validator_info.voting_power <= MAX_U128;
+                assume total_voting_power + new_validator_info.voting_power
+                    <= MAX_U128;
             };
-            total_voting_power = total_voting_power + (new_validator_info.voting_power as u128);
+            total_voting_power =
+                total_voting_power + (new_validator_info.voting_power as u128);
             vector::push_back(&mut next_epoch_validators, new_validator_info);
         };
         i = i + 1;
@@ -4028,7 +4792,8 @@ power.
 
     // Update validator indices, reset performance scores, and renew lockups.
     validator_perf.validators = vector::empty();
-    let recurring_lockup_duration_secs = staking_config::get_recurring_lockup_duration(&config);
+    let recurring_lockup_duration_secs =
+        staking_config::get_recurring_lockup_duration(&config);
     let vlen = vector::length(&validator_set.active_validators);
     let validator_index = 0;
     while ({
@@ -4039,37 +4804,47 @@ power.
             invariant 0 <= validator_index && validator_index <= vlen;
             invariant vlen == len(validator_set.active_validators);
             invariant forall i in 0..validator_index:
-                global<ValidatorConfig>(validator_set.active_validators[i].addr).validator_index < validator_index;
+                global<ValidatorConfig>(validator_set.active_validators[i].addr).validator_index
+                    < validator_index;
             invariant forall i in 0..validator_index:
-                validator_set.active_validators[i].config.validator_index < validator_index;
+                validator_set.active_validators[i].config.validator_index
+                    < validator_index;
             invariant len(validator_perf.validators) == validator_index;
         };
         validator_index < vlen
     }) {
-        let validator_info = vector::borrow_mut(&mut validator_set.active_validators, validator_index);
+        let validator_info = vector::borrow_mut(
+            &mut validator_set.active_validators, validator_index
+        );
         validator_info.config.validator_index = validator_index;
-        let validator_config = borrow_global_mut<ValidatorConfig>(validator_info.addr);
+        let validator_config =
+            borrow_global_mut<ValidatorConfig>(validator_info.addr);
         validator_config.validator_index = validator_index;
 
-        vector::push_back(&mut validator_perf.validators, IndividualValidatorPerformance {
-            successful_proposals: 0,
-            failed_proposals: 0,
-        });
+        vector::push_back(
+            &mut validator_perf.validators,
+            IndividualValidatorPerformance {
+                successful_proposals: 0,
+                failed_proposals: 0
+            }
+        );
 
         // Automatically renew a validator's lockup for validators that will still be in the validator set in the
         // next epoch.
         let stake_pool = borrow_global_mut<StakePool>(validator_info.addr);
         let now_secs = timestamp::now_seconds();
-        let reconfig_start_secs = if (chain_status::is_operating()) {
-            get_reconfig_start_time_secs()
-        } else {
-            now_secs
-        };
+        let reconfig_start_secs =
+            if (chain_status::is_operating()) {
+                get_reconfig_start_time_secs()
+            } else {
+                now_secs
+            };
         if (stake_pool.locked_until_secs <= reconfig_start_secs) {
             spec {
                 assume now_secs + recurring_lockup_duration_secs <= MAX_U64;
             };
-            stake_pool.locked_until_secs = now_secs + recurring_lockup_duration_secs;
+            stake_pool.locked_until_secs = now_secs
+                + recurring_lockup_duration_secs;
         };
 
         validator_index = validator_index + 1;
@@ -4134,12 +4909,80 @@ Return the ValidatorConsensusInfo of each current validator, sorted
 
 
 
public fun next_validator_consensus_infos(): vector<ValidatorConsensusInfo> acquires ValidatorSet, ValidatorPerformance, StakePool, ValidatorConfig {
+    let new_validator_set = compute_next_validator_set_internal(false);
+    validator_consensus_infos_from_validator_set(&new_validator_set)
+}
+
+ + + +
+ + + +## Function `next_epoch_validator_consensus_infos_for_dkg` + +Same as next_validator_consensus_infos but uses the current-epoch config data for +validators that are already active. This is used when starting DKG: the committee +membership (active + pending_active) must reflect the next epoch, but node config +should reflect current-epoch for the active validators to ensure that validators that update +their configuration do not need to run two copies of themselves to participate in DKG. + + +
public fun next_epoch_validator_consensus_infos_for_dkg(): vector<validator_consensus_info::ValidatorConsensusInfo>
+
+ + + +
+Implementation + + +
public fun next_epoch_validator_consensus_infos_for_dkg(): vector<ValidatorConsensusInfo> acquires ValidatorSet, ValidatorPerformance, StakePool, ValidatorConfig {
+    // Use the current-epoch config snapshot for active validators so mid-epoch config changes
+    // do not take effect during DKG (use_current_config_for_actives=true).
+    let new_validator_set = compute_next_validator_set_internal(true);
+    validator_consensus_infos_from_validator_set(&new_validator_set)
+}
+
+ + + +
+ + + +## Function `compute_next_validator_set_internal` + +Computes the validator set for the next epoch. + +use_current_config_for_actives: when true, currently-active validators retain their +current-epoch ValidatorConfig snapshot instead of reading the latest on-chain value. +New joiners (pending_active) always read from ValidatorConfig regardless of this flag. + +pending_active is iterated in reverse to match the order produced by on_new_epoch +(which appends via pop_back). + + +
fun compute_next_validator_set_internal(use_current_config_for_actives: bool): stake::ValidatorSet
+
+ + + +
+Implementation + + +
fun compute_next_validator_set_internal(
+    use_current_config_for_actives: bool
+): ValidatorSet acquires ValidatorSet, ValidatorPerformance, StakePool, ValidatorConfig {
     // Init.
     let cur_validator_set = borrow_global<ValidatorSet>(@supra_framework);
     let staking_config = staking_config::get();
     let validator_perf = borrow_global<ValidatorPerformance>(@supra_framework);
     let (minimum_stake, _) = staking_config::get_required_stake(&staking_config);
-    let (rewards_rate, rewards_rate_denominator) = staking_config::get_reward_rate(&staking_config);
+    let (rewards_rate, rewards_rate_denominator) =
+        staking_config::get_reward_rate(&staking_config);
 
     // Compute new validator set.
     let new_active_validators = vector[];
@@ -4165,11 +5008,14 @@ Return the ValidatorConsensusInfo of each current validator, sorted
         candidate_idx < num_candidates
     }) {
         let candidate_in_current_validator_set = candidate_idx < num_cur_actives;
-        let candidate = if (candidate_idx < num_cur_actives) {
-            vector::borrow(&cur_validator_set.active_validators, candidate_idx)
-        } else {
-            vector::borrow(&cur_validator_set.pending_active, candidate_idx - num_cur_actives)
-        };
+        let candidate =
+            if (candidate_idx < num_cur_actives) {
+                vector::borrow(&cur_validator_set.active_validators, candidate_idx)
+            } else {
+                let pending_idx =
+                    num_cur_pending_actives - 1 - (candidate_idx - num_cur_actives);
+                vector::borrow(&cur_validator_set.pending_active, pending_idx)
+            };
         let stake_pool = borrow_global<StakePool>(candidate.addr);
         let cur_active = coin::value(&stake_pool.active);
         let cur_pending_active = coin::value(&stake_pool.pending_active);
@@ -4200,12 +5046,21 @@ Return the ValidatorConsensusInfo of each current validator, sorted
             + cur_reward;
 
         if (new_voting_power >= minimum_stake) {
-            let config = *borrow_global<ValidatorConfig>(candidate.addr);
+            let config =
+                if (use_current_config_for_actives
+                    && candidate_in_current_validator_set) {
+                    // Use the current-epoch config snapshot so that any mid-epoch changes
+                    // (consensus key, network addresses, etc.) only take effect after the
+                    // epoch transition, not during DKG.
+                    candidate.config
+                } else {
+                    *borrow_global<ValidatorConfig>(candidate.addr)
+                };
             config.validator_index = num_new_actives;
             let new_validator_info = ValidatorInfo {
                 addr: candidate.addr,
                 voting_power: new_voting_power,
-                config,
+                config
             };
 
             // Update ValidatorSet.
@@ -4215,21 +5070,71 @@ Return the ValidatorConsensusInfo of each current validator, sorted
             new_total_power = new_total_power + (new_voting_power as u128);
             vector::push_back(&mut new_active_validators, new_validator_info);
             num_new_actives = num_new_actives + 1;
-
         };
         candidate_idx = candidate_idx + 1;
     };
 
-    let new_validator_set = ValidatorSet {
+    ValidatorSet {
         consensus_scheme: cur_validator_set.consensus_scheme,
         active_validators: new_active_validators,
         pending_inactive: vector[],
         pending_active: vector[],
         total_voting_power: new_total_power,
-        total_joining_power: 0,
-    };
+        total_joining_power: 0
+    }
+}
+
+ + + +
+ + + +## Function `calculate_candidate_reward` + +Computes the reward earned by a candidate validator for the current epoch. +Returns 0 for pending-active validators (not yet in the active set) or validators +with no active stake. + + +
fun calculate_candidate_reward(candidate: &stake::ValidatorInfo, candidate_in_current_validator_set: bool, cur_active: u64, validator_perf: &stake::ValidatorPerformance, rewards_rate: u64, rewards_rate_denominator: u64): u64
+
+ + + +
+Implementation - validator_consensus_infos_from_validator_set(&new_validator_set) + +
fun calculate_candidate_reward(
+    candidate: &ValidatorInfo,
+    candidate_in_current_validator_set: bool,
+    cur_active: u64,
+    validator_perf: &ValidatorPerformance,
+    rewards_rate: u64,
+    rewards_rate_denominator: u64
+): u64 {
+    if (candidate_in_current_validator_set && cur_active != 0) {
+        spec {
+            assert candidate.config.validator_index
+                < len(validator_perf.validators);
+        };
+        let cur_perf = vector::borrow(
+            &validator_perf.validators, candidate.config.validator_index
+        );
+        spec {
+            assume cur_perf.successful_proposals + cur_perf.failed_proposals
+                <= MAX_U64;
+        };
+        calculate_rewards_amount(
+            cur_active,
+            cur_perf.successful_proposals,
+            cur_perf.successful_proposals + cur_perf.failed_proposals,
+            rewards_rate,
+            rewards_rate_denominator
+        )
+    } else { 0 }
 }
 
@@ -4252,7 +5157,9 @@ Return the ValidatorConsensusInfo of each current validator, sorted Implementation -
fun validator_consensus_infos_from_validator_set(validator_set: &ValidatorSet): vector<ValidatorConsensusInfo> {
+
fun validator_consensus_infos_from_validator_set(
+    validator_set: &ValidatorSet
+): vector<ValidatorConsensusInfo> {
     let validator_consensus_infos = vector[];
 
     let num_active = vector::length(&validator_set.active_validators);
@@ -4266,54 +5173,83 @@ Return the ValidatorConsensusInfo of each current validator, sorted
     let idx = 0;
     while ({
         spec {
-            invariant idx <= len(validator_set.active_validators) + len(validator_set.pending_inactive);
+            invariant idx
+                <= len(validator_set.active_validators)
+                    + len(validator_set.pending_inactive);
             invariant len(validator_consensus_infos) == idx;
-            invariant len(validator_consensus_infos) <= len(validator_set.active_validators) + len(validator_set.pending_inactive);
+            invariant len(validator_consensus_infos)
+                <= len(validator_set.active_validators)
+                    + len(validator_set.pending_inactive);
         };
         idx < total
     }) {
-        vector::push_back(&mut validator_consensus_infos, validator_consensus_info::default());
+        vector::push_back(
+            &mut validator_consensus_infos, validator_consensus_info::default()
+        );
         idx = idx + 1;
     };
     spec {
-        assert len(validator_consensus_infos) == len(validator_set.active_validators) + len(validator_set.pending_inactive);
-        assert spec_validator_indices_are_valid_config(validator_set.active_validators,
-            len(validator_set.active_validators) + len(validator_set.pending_inactive));
+        assert len(validator_consensus_infos)
+            == len(validator_set.active_validators)
+                + len(validator_set.pending_inactive);
+        assert spec_validator_indices_are_valid_config(
+            validator_set.active_validators,
+            len(validator_set.active_validators)
+                + len(validator_set.pending_inactive)
+        );
     };
 
-    vector::for_each_ref(&validator_set.active_validators, |obj| {
-        let vi: &ValidatorInfo = obj;
-        spec {
-            assume len(validator_consensus_infos) == len(validator_set.active_validators) + len(validator_set.pending_inactive);
-            assert vi.config.validator_index < len(validator_consensus_infos);
-        };
-        let vci = vector::borrow_mut(&mut validator_consensus_infos, vi.config.validator_index);
-        *vci = validator_consensus_info::new(
-            vi.addr,
-            vi.config.consensus_pubkey,
-            vi.voting_power
-        );
-        spec {
-            assert len(validator_consensus_infos) == len(validator_set.active_validators) + len(validator_set.pending_inactive);
-        };
-    });
+    vector::for_each_ref(
+        &validator_set.active_validators,
+        |obj| {
+            let vi: &ValidatorInfo = obj;
+            spec {
+                assume len(validator_consensus_infos)
+                    == len(validator_set.active_validators)
+                        + len(validator_set.pending_inactive);
+                assert vi.config.validator_index < len(validator_consensus_infos);
+            };
+            let vci = vector::borrow_mut(
+                &mut validator_consensus_infos, vi.config.validator_index
+            );
+            *vci = validator_consensus_info::new(
+                vi.addr,
+                vi.config.consensus_pubkey,
+                vi.voting_power
+            );
+            spec {
+                assert len(validator_consensus_infos)
+                    == len(validator_set.active_validators)
+                        + len(validator_set.pending_inactive);
+            };
+        }
+    );
 
-    vector::for_each_ref(&validator_set.pending_inactive, |obj| {
-        let vi: &ValidatorInfo = obj;
-        spec {
-            assume len(validator_consensus_infos) == len(validator_set.active_validators) + len(validator_set.pending_inactive);
-            assert vi.config.validator_index < len(validator_consensus_infos);
-        };
-        let vci = vector::borrow_mut(&mut validator_consensus_infos, vi.config.validator_index);
-        *vci = validator_consensus_info::new(
-            vi.addr,
-            vi.config.consensus_pubkey,
-            vi.voting_power
-        );
-        spec {
-            assert len(validator_consensus_infos) == len(validator_set.active_validators) + len(validator_set.pending_inactive);
-        };
-    });
+    vector::for_each_ref(
+        &validator_set.pending_inactive,
+        |obj| {
+            let vi: &ValidatorInfo = obj;
+            spec {
+                assume len(validator_consensus_infos)
+                    == len(validator_set.active_validators)
+                        + len(validator_set.pending_inactive);
+                assert vi.config.validator_index < len(validator_consensus_infos);
+            };
+            let vci = vector::borrow_mut(
+                &mut validator_consensus_infos, vi.config.validator_index
+            );
+            *vci = validator_consensus_info::new(
+                vi.addr,
+                vi.config.consensus_pubkey,
+                vi.voting_power
+            );
+            spec {
+                assert len(validator_consensus_infos)
+                    == len(validator_set.active_validators)
+                        + len(validator_set.pending_inactive);
+            };
+        }
+    );
 
     validator_consensus_infos
 }
@@ -4339,10 +5275,13 @@ Return the ValidatorConsensusInfo of each current validator, sorted
 
 
 
fun addresses_from_validator_infos(infos: &vector<ValidatorInfo>): vector<address> {
-    vector::map_ref(infos, |obj| {
-        let info: &ValidatorInfo = obj;
-        info.addr
-    })
+    vector::map_ref(
+        infos,
+        |obj| {
+            let info: &ValidatorInfo = obj;
+            info.addr
+        }
+    )
 }
 
@@ -4375,12 +5314,14 @@ This function shouldn't abort.
fun update_stake_pool(
     validator_perf: &ValidatorPerformance,
     pool_address: address,
-    staking_config: &StakingConfig,
+    staking_config: &StakingConfig
 ) acquires SupraCoinCapabilities, PendingTransactionFee, StakePool, ValidatorConfig {
     let stake_pool = borrow_global_mut<StakePool>(pool_address);
     let validator_config = borrow_global<ValidatorConfig>(pool_address);
     let validator_index = validator_config.validator_index;
-    let cur_validator_perf = vector::borrow(&validator_perf.validators, validator_index);
+    let cur_validator_perf = vector::borrow(
+        &validator_perf.validators, validator_index
+    );
     let num_successful_proposals = cur_validator_perf.successful_proposals;
 
     let fee_pending_inactive = 0;
@@ -4404,24 +5345,30 @@ This function shouldn't abort.
     spec {
         // The following addition should not overflow because `num_total_proposals` cannot be larger than 86400,
         // the maximum number of proposals in a day (1 proposal per second).
-        assume cur_validator_perf.successful_proposals + cur_validator_perf.failed_proposals <= MAX_U64;
+        assume cur_validator_perf.successful_proposals
+            + cur_validator_perf.failed_proposals <= MAX_U64;
     };
-    let num_total_proposals = cur_validator_perf.successful_proposals + cur_validator_perf.failed_proposals;
-    let (rewards_rate, rewards_rate_denominator) = staking_config::get_reward_rate(staking_config);
-    let rewards_active = distribute_rewards(
-        &mut stake_pool.active,
-        num_successful_proposals,
-        num_total_proposals,
-        rewards_rate,
-        rewards_rate_denominator
-    );
-    let rewards_pending_inactive = distribute_rewards(
-        &mut stake_pool.pending_inactive,
-        num_successful_proposals,
-        num_total_proposals,
-        rewards_rate,
-        rewards_rate_denominator
-    );
+    let num_total_proposals =
+        cur_validator_perf.successful_proposals
+            + cur_validator_perf.failed_proposals;
+    let (rewards_rate, rewards_rate_denominator) =
+        staking_config::get_reward_rate(staking_config);
+    let rewards_active =
+        distribute_rewards(
+            &mut stake_pool.active,
+            num_successful_proposals,
+            num_total_proposals,
+            rewards_rate,
+            rewards_rate_denominator
+        );
+    let rewards_pending_inactive =
+        distribute_rewards(
+            &mut stake_pool.pending_inactive,
+            num_successful_proposals,
+            num_total_proposals,
+            rewards_rate,
+            rewards_rate_denominator
+        );
     spec {
         assume rewards_active + rewards_pending_inactive <= MAX_U64;
     };
@@ -4449,7 +5396,7 @@ This function shouldn't abort.
     if (get_reconfig_start_time_secs() >= current_lockup_expiration) {
         coin::merge(
             &mut stake_pool.inactive,
-            coin::extract_all(&mut stake_pool.pending_inactive),
+            coin::extract_all(&mut stake_pool.pending_inactive)
         );
     };
 
@@ -4521,7 +5468,7 @@ Calculate the rewards amount.
     num_successful_proposals: u64,
     num_total_proposals: u64,
     rewards_rate: u64,
-    rewards_rate_denominator: u64,
+    rewards_rate_denominator: u64
 ): u64 {
     spec {
         // The following condition must hold because
@@ -4532,13 +5479,14 @@ Calculate the rewards amount.
     };
     // The rewards amount is equal to (stake amount * rewards rate * performance multiplier).
     // We do multiplication in u128 before division to avoid the overflow and minimize the rounding error.
-    let rewards_numerator = (stake_amount as u128) * (rewards_rate as u128) * (num_successful_proposals as u128);
-    let rewards_denominator = (rewards_rate_denominator as u128) * (num_total_proposals as u128);
+    let rewards_numerator =
+        (stake_amount as u128) * (rewards_rate as u128)
+            * (num_successful_proposals as u128);
+    let rewards_denominator =
+        (rewards_rate_denominator as u128) * (num_total_proposals as u128);
     if (rewards_denominator != 0) {
         ((rewards_numerator / rewards_denominator) as u64)
-    } else {
-        0
-    }
+    } else { 0 }
 }
 
@@ -4567,22 +5515,22 @@ Mint rewards corresponding to current epoch's acquires SupraCoinCapabilities { let stake_amount = coin::value(stake); - let rewards_amount = if (stake_amount != 0) { - calculate_rewards_amount( - stake_amount, - num_successful_proposals, - num_total_proposals, - rewards_rate, - rewards_rate_denominator - ) - } else { - 0 - }; + let rewards_amount = + if (stake_amount != 0) { + calculate_rewards_amount( + stake_amount, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ) + } else { 0 }; if (rewards_amount != 0) { - let mint_cap = &borrow_global<SupraCoinCapabilities>(@supra_framework).mint_cap; + let mint_cap = + &borrow_global<SupraCoinCapabilities>(@supra_framework).mint_cap; let rewards = coin::mint(rewards_amount, mint_cap); coin::merge(stake, rewards); }; @@ -4672,13 +5620,11 @@ Mint rewards corresponding to current epoch's Implementation -
fun generate_validator_info(addr: address, stake_pool: &StakePool, config: ValidatorConfig): ValidatorInfo {
+
fun generate_validator_info(
+    addr: address, stake_pool: &StakePool, config: ValidatorConfig
+): ValidatorInfo {
     let voting_power = get_next_epoch_voting_power(stake_pool);
-    ValidatorInfo {
-        addr,
-        voting_power,
-        config,
-    }
+    ValidatorInfo { addr, voting_power, config }
 }
 
@@ -4707,7 +5653,8 @@ Returns validator's next epoch voting power, including pending_active, active, a let value_active = coin::value(&stake_pool.active); let value_pending_inactive = coin::value(&stake_pool.pending_inactive); spec { - assume value_pending_active + value_active + value_pending_inactive <= MAX_U64; + assume value_pending_active + value_active + value_pending_inactive + <= MAX_U64; }; value_pending_active + value_active + value_pending_inactive } @@ -4735,14 +5682,19 @@ Returns validator's next epoch voting power, including pending_active, active, a
fun update_voting_power_increase(increase_amount: u64) acquires ValidatorSet {
     let validator_set = borrow_global_mut<ValidatorSet>(@supra_framework);
     let voting_power_increase_limit =
-        (staking_config::get_voting_power_increase_limit(&staking_config::get()) as u128);
-    validator_set.total_joining_power = validator_set.total_joining_power + (increase_amount as u128);
+        (
+            staking_config::get_voting_power_increase_limit(&staking_config::get()) as u128
+        );
+    validator_set.total_joining_power =
+        validator_set.total_joining_power + (increase_amount as u128);
 
     // Only validator voting power increase if the current validator set's voting power > 0.
     if (validator_set.total_voting_power != 0) {
         assert!(
-            validator_set.total_joining_power <= validator_set.total_voting_power * voting_power_increase_limit / 100,
-            error::invalid_argument(EVOTING_POWER_INCREASE_EXCEEDS_LIMIT),
+            validator_set.total_joining_power
+                <= validator_set.total_voting_power * voting_power_increase_limit
+                    / 100,
+            error::invalid_argument(EVOTING_POWER_INCREASE_EXCEEDS_LIMIT)
         );
     }
 }
@@ -4768,7 +5720,10 @@ Returns validator's next epoch voting power, including pending_active, active, a
 
 
 
fun assert_stake_pool_exists(pool_address: address) {
-    assert!(stake_pool_exists(pool_address), error::invalid_argument(ESTAKE_POOL_DOES_NOT_EXIST));
+    assert!(
+        stake_pool_exists(pool_address),
+        error::invalid_argument(ESTAKE_POOL_DOES_NOT_EXIST)
+    );
 }
 
@@ -4792,8 +5747,7 @@ Returns validator's next epoch voting power, including pending_active, active, a
public fun configure_allowed_validators(
-    supra_framework: &signer,
-    accounts: vector<address>
+    supra_framework: &signer, accounts: vector<address>
 ) acquires AllowedValidators {
     let supra_framework_address = signer::address_of(supra_framework);
     system_addresses::assert_supra_framework(supra_framework);
@@ -4826,9 +5780,8 @@ Returns validator's next epoch voting power, including pending_active, active, a
 
 
 
fun is_allowed(account: address): bool acquires AllowedValidators {
-    if (!exists<AllowedValidators>(@supra_framework)) {
-        true
-    } else {
+    if (!exists<AllowedValidators>(@supra_framework)) { true }
+    else {
         let allowed = borrow_global<AllowedValidators>(@supra_framework);
         vector::contains(&allowed.accounts, &account)
     }
@@ -4855,7 +5808,10 @@ Returns validator's next epoch voting power, including pending_active, active, a
 
 
 
fun assert_owner_cap_exists(owner: address) {
-    assert!(exists<OwnerCapability>(owner), error::not_found(EOWNER_CAP_NOT_FOUND));
+    assert!(
+        exists<OwnerCapability>(owner),
+        error::not_found(EOWNER_CAP_NOT_FOUND)
+    );
 }
 
@@ -4879,7 +5835,10 @@ Returns validator's next epoch voting power, including pending_active, active, a
fun assert_reconfig_not_in_progress() {
-    assert!(!reconfiguration_state::is_in_progress(), error::invalid_state(ERECONFIGURATION_IN_PROGRESS));
+    assert!(
+        !reconfiguration_state::is_in_progress(),
+        error::invalid_state(ERECONFIGURATION_IN_PROGRESS)
+    );
 }
 
@@ -5247,6 +6206,7 @@ Returns validator's next epoch voting power, including pending_active, active, a
pragma verify = false;
+pragma aborts_if_is_partial = true;
 include AbortsIfSignerPermissionStake {
     s: account
 };
@@ -5457,7 +6417,8 @@ Returns validator's next epoch voting power, including pending_active, active, a
 
 
 
-
include AbortsIfSignerPermissionStake {
+
pragma aborts_if_is_partial = true;
+include AbortsIfSignerPermissionStake {
     s: operator
 };
 let pre_stake_pool = global<StakePool>(pool_address);
@@ -5466,10 +6427,6 @@ Returns validator's next epoch voting power, including pending_active, active, a
 aborts_if !exists<StakePool>(pool_address);
 aborts_if signer::address_of(operator) != pre_stake_pool.operator_address;
 aborts_if !exists<ValidatorConfig>(pool_address);
-let is_public_key_validated = ed25519::spec_public_key_validate_internal(
-    new_consensus_pubkey,
-);
-aborts_if !is_public_key_validated;
 modifies global<ValidatorConfig>(pool_address);
 include StakedValueNochange;
 ensures validator_info.consensus_pubkey == new_consensus_pubkey;
@@ -5488,7 +6445,8 @@ Returns validator's next epoch voting power, including pending_active, active, a
 
 
 
-
include AbortsIfSignerPermissionStake {
+
pragma aborts_if_is_partial = true;
+include AbortsIfSignerPermissionStake {
     s: operator
 };
 let pre_stake_pool = global<StakePool>(pool_address);
@@ -5814,6 +6772,300 @@ Returns validator's next epoch voting power, including pending_active, active, a
 
 
 
+
+
+
+
+
schema AddStakeWithCapAbortsIfAndEnsures {
+    owner_cap: OwnerCapability;
+    amount: u64;
+    let pool_address = owner_cap.pool_address;
+    aborts_if !exists<StakePool>(pool_address);
+    let config = global<staking_config::StakingConfig>(@supra_framework);
+    let validator_set = global<ValidatorSet>(@supra_framework);
+    let voting_power_increase_limit = config.voting_power_increase_limit;
+    let post post_validator_set = global<ValidatorSet>(@supra_framework);
+    let update_voting_power_increase = amount != 0 && (spec_contains(validator_set.active_validators, pool_address)
+                                                       || spec_contains(validator_set.pending_active, pool_address));
+    aborts_if update_voting_power_increase && validator_set.total_joining_power + amount > MAX_U128;
+    ensures update_voting_power_increase ==> post_validator_set.total_joining_power == validator_set.total_joining_power + amount;
+    aborts_if update_voting_power_increase && validator_set.total_voting_power > 0
+            && validator_set.total_voting_power * voting_power_increase_limit > MAX_U128;
+    aborts_if update_voting_power_increase && validator_set.total_voting_power > 0
+            && validator_set.total_joining_power + amount > validator_set.total_voting_power * voting_power_increase_limit / 100;
+    let stake_pool = global<StakePool>(pool_address);
+    let post post_stake_pool = global<StakePool>(pool_address);
+    let value_pending_active = stake_pool.pending_active.value;
+    let value_active = stake_pool.active.value;
+    ensures amount != 0 && spec_is_current_epoch_validator(pool_address) ==> post_stake_pool.pending_active.value == value_pending_active + amount;
+    ensures amount != 0 && !spec_is_current_epoch_validator(pool_address) ==> post_stake_pool.active.value == value_active + amount;
+    let maximum_stake = config.maximum_stake;
+    let value_pending_inactive = stake_pool.pending_inactive.value;
+    let next_epoch_voting_power = value_pending_active + value_active + value_pending_inactive;
+    let voting_power = next_epoch_voting_power + amount;
+    aborts_if amount != 0 && voting_power > MAX_U64;
+    aborts_if amount != 0 && voting_power > maximum_stake;
+}
+
+ + + + + + + +
schema AddStakeAbortsIfAndEnsures {
+    owner: signer;
+    amount: u64;
+    let owner_address = signer::address_of(owner);
+    aborts_if !exists<OwnerCapability>(owner_address);
+    let owner_cap = global<OwnerCapability>(owner_address);
+    include AddStakeWithCapAbortsIfAndEnsures { owner_cap };
+}
+
+ + + + + + + +
fun spec_is_allowed(account: address): bool {
+   if (!exists<AllowedValidators>(@supra_framework)) {
+       true
+   } else {
+       let allowed = global<AllowedValidators>(@supra_framework);
+       contains(allowed.accounts, account)
+   }
+}
+
+ + + + + + + +
fun spec_find_validator(v: vector<ValidatorInfo>, addr: address): Option<u64>;
+
+ + + + + + + +
fun spec_validators_are_initialized(validators: vector<ValidatorInfo>): bool {
+   forall i in 0..len(validators):
+       spec_has_stake_pool(validators[i].addr) &&
+           spec_has_validator_config(validators[i].addr)
+}
+
+ + + + + + + +
fun spec_validators_are_initialized_addrs(addrs: vector<address>): bool {
+   forall i in 0..len(addrs):
+       spec_has_stake_pool(addrs[i]) &&
+           spec_has_validator_config(addrs[i])
+}
+
+ + + + + + + +
fun spec_validator_indices_are_valid(validators: vector<ValidatorInfo>): bool {
+   spec_validator_indices_are_valid_addr(validators, spec_validator_index_upper_bound()) &&
+       spec_validator_indices_are_valid_config(validators, spec_validator_index_upper_bound())
+}
+
+ + + + + + + +
fun spec_validator_indices_are_valid_addr(validators: vector<ValidatorInfo>, upper_bound: u64): bool {
+   forall i in 0..len(validators):
+       global<ValidatorConfig>(validators[i].addr).validator_index < upper_bound
+}
+
+ + + + + + + +
fun spec_validator_indices_are_valid_config(validators: vector<ValidatorInfo>, upper_bound: u64): bool {
+   forall i in 0..len(validators):
+       validators[i].config.validator_index < upper_bound
+}
+
+ + + + + + + +
fun spec_validator_indices_active_pending_inactive(validator_set: ValidatorSet): bool {
+   len(validator_set.pending_inactive) + len(validator_set.active_validators) == spec_validator_index_upper_bound()
+}
+
+ + + + + + + +
fun spec_validator_index_upper_bound(): u64 {
+   len(global<ValidatorPerformance>(@supra_framework).validators)
+}
+
+ + + + + + + +
fun spec_has_stake_pool(a: address): bool {
+   exists<StakePool>(a)
+}
+
+ + + + + + + +
fun spec_has_validator_config(a: address): bool {
+   exists<ValidatorConfig>(a)
+}
+
+ + + + + + + +
fun spec_rewards_amount(
+   stake_amount: u64,
+   num_successful_proposals: u64,
+   num_total_proposals: u64,
+   rewards_rate: u64,
+   rewards_rate_denominator: u64,
+): u64;
+
+ + + + + + + +
fun spec_contains(validators: vector<ValidatorInfo>, addr: address): bool {
+   exists i in 0..len(validators): validators[i].addr == addr
+}
+
+ + + + + + + +
fun spec_is_current_epoch_validator(pool_address: address): bool {
+   let validator_set = global<ValidatorSet>(@supra_framework);
+   !spec_contains(validator_set.pending_active, pool_address)
+       && (spec_contains(validator_set.active_validators, pool_address)
+       || spec_contains(validator_set.pending_inactive, pool_address))
+}
+
+ + + + + + + +
schema ResourceRequirement {
+    requires exists<SupraCoinCapabilities>(@supra_framework);
+    requires exists<ValidatorPerformance>(@supra_framework);
+    requires exists<ValidatorSet>(@supra_framework);
+    requires exists<StakingConfig>(@supra_framework);
+    requires exists<StakingRewardsConfig>(@supra_framework) || !features::spec_periodical_reward_rate_decrease_enabled();
+    requires exists<timestamp::CurrentTimeMicroseconds>(@supra_framework);
+}
+
+ + + + + + + +
fun spec_get_reward_rate_1(config: StakingConfig): num {
+   if (features::spec_periodical_reward_rate_decrease_enabled()) {
+       let epoch_rewards_rate = global<staking_config::StakingRewardsConfig>(@supra_framework).rewards_rate;
+       if (epoch_rewards_rate.value == 0) {
+           0
+       } else {
+           let denominator_0 = aptos_std::fixed_point64::spec_divide_u128(staking_config::MAX_REWARDS_RATE, epoch_rewards_rate);
+           let denominator = if (denominator_0 > MAX_U64) {
+               MAX_U64
+           } else {
+               denominator_0
+           };
+           let nominator = aptos_std::fixed_point64::spec_multiply_u128(denominator, epoch_rewards_rate);
+           nominator
+       }
+   } else {
+           config.rewards_rate
+   }
+}
+
+ + + + + + + +
fun spec_get_reward_rate_2(config: StakingConfig): num {
+   if (features::spec_periodical_reward_rate_decrease_enabled()) {
+       let epoch_rewards_rate = global<staking_config::StakingRewardsConfig>(@supra_framework).rewards_rate;
+       if (epoch_rewards_rate.value == 0) {
+           1
+       } else {
+           let denominator_0 = aptos_std::fixed_point64::spec_divide_u128(staking_config::MAX_REWARDS_RATE, epoch_rewards_rate);
+           let denominator = if (denominator_0 > MAX_U64) {
+               MAX_U64
+           } else {
+               denominator_0
+           };
+           denominator
+       }
+   } else {
+           config.rewards_rate_denominator
+   }
+}
+
+ + + ### Function `update_stake_pool` diff --git a/aptos-move/framework/supra-framework/doc/supra_dkg.md b/aptos-move/framework/supra-framework/doc/supra_dkg.md new file mode 100644 index 00000000000..fe1ec290b58 --- /dev/null +++ b/aptos-move/framework/supra-framework/doc/supra_dkg.md @@ -0,0 +1,843 @@ + + + +# Module `0x1::supra_dkg` + +DKG on-chain states and helper functions. + + +- [Struct `DKGStartEvent`](#0x1_supra_dkg_DKGStartEvent) +- [Struct `DKGMetaSetEvent`](#0x1_supra_dkg_DKGMetaSetEvent) +- [Struct `DKGFinishEvent`](#0x1_supra_dkg_DKGFinishEvent) +- [Struct `DKGSessionMetadata`](#0x1_supra_dkg_DKGSessionMetadata) +- [Struct `DKGSessionState`](#0x1_supra_dkg_DKGSessionState) +- [Resource `DKGState`](#0x1_supra_dkg_DKGState) +- [Struct `OnChainAggregateCommitment`](#0x1_supra_dkg_OnChainAggregateCommitment) +- [Struct `OnChainAggregateCommitmentAllCommittees`](#0x1_supra_dkg_OnChainAggregateCommitmentAllCommittees) +- [Constants](#@Constants_0) +- [Function `initialize`](#0x1_supra_dkg_initialize) +- [Function `start`](#0x1_supra_dkg_start) +- [Function `set_dkg_meta`](#0x1_supra_dkg_set_dkg_meta) +- [Function `finish`](#0x1_supra_dkg_finish) +- [Function `try_clear_incomplete_session`](#0x1_supra_dkg_try_clear_incomplete_session) +- [Function `incomplete_session`](#0x1_supra_dkg_incomplete_session) +- [Function `last_completed_session`](#0x1_supra_dkg_last_completed_session) +- [Function `session_dealer_epoch`](#0x1_supra_dkg_session_dealer_epoch) +- [Specification](#@Specification_1) + - [Function `initialize`](#@Specification_1_initialize) + - [Function `start`](#@Specification_1_start) + - [Function `set_dkg_meta`](#@Specification_1_set_dkg_meta) + - [Function `finish`](#@Specification_1_finish) + - [Function `try_clear_incomplete_session`](#@Specification_1_try_clear_incomplete_session) + - [Function `incomplete_session`](#@Specification_1_incomplete_session) + + +
use 0x1::any;
+use 0x1::dkg_committee;
+use 0x1::error;
+use 0x1::event;
+use 0x1::option;
+use 0x1::stake;
+use 0x1::string;
+use 0x1::system_addresses;
+use 0x1::timestamp;
+use 0x1::type_info;
+use 0x1::vector;
+
+ + + + + +## Struct `DKGStartEvent` + + + +
#[event]
+struct DKGStartEvent has drop, store
+
+ + + +
+Fields + + +
+
+session_metadata: supra_dkg::DKGSessionMetadata +
+
+ +
+
+start_time_us: u64 +
+
+ +
+
+ + +
+ + + +## Struct `DKGMetaSetEvent` + + + +
#[event]
+struct DKGMetaSetEvent has drop, store
+
+ + + +
+Fields + + +
+
+dkg_meta_transcript: vector<u8> +
+
+ +
+
+ + +
+ + + +## Struct `DKGFinishEvent` + + + +
#[event]
+struct DKGFinishEvent has drop, store
+
+ + + +
+Fields + + +
+
+target_committees_public_key_shares: vector<u8> +
+
+ +
+
+ + +
+ + + +## Struct `DKGSessionMetadata` + +This can be considered as the public input of DKG. + + +
struct DKGSessionMetadata has copy, drop, store
+
+ + + +
+Fields + + +
+
+dealer_epoch: u64 +
+
+ +
+
+randomness_seed: vector<u8> +
+
+ +
+
+dealer_committee: dkg_committee::DkgCommittee +
+
+ +
+
+target_committees: vector<dkg_committee::ReceiverCommittee> +
+
+ +
+
+ + +
+ + + +## Struct `DKGSessionState` + +The input and output of a DKG session. +The validator set of epoch x works together for an DKG output for the target validator set of epoch x+1. + + +
struct DKGSessionState has copy, drop, store
+
+ + + +
+Fields + + +
+
+metadata: supra_dkg::DKGSessionMetadata +
+
+ +
+
+start_time_us: u64 +
+
+ +
+
+dkg_meta_transcript: vector<u8> +
+
+ +
+
+target_committees_public_key_shares: vector<u8> +
+
+ +
+
+ + +
+ + + +## Resource `DKGState` + +The completed and in-progress DKG sessions. + + +
struct DKGState has key
+
+ + + +
+Fields + + +
+
+last_completed: option::Option<supra_dkg::DKGSessionState> +
+
+ +
+
+in_progress: option::Option<supra_dkg::DKGSessionState> +
+
+ +
+
+ + +
+ + + +## Struct `OnChainAggregateCommitment` + + + +
struct OnChainAggregateCommitment has copy, drop
+
+ + + +
+Fields + + +
+
+bls12381_commitment_g: vector<u8> +
+
+ +
+
+bls12381_commitment_evals: vector<vector<u8>> +
+
+ +
+
+dealer_ids: vector<u32> +
+
+ +
+
+committee_index: u32 +
+
+ +
+
+epoch: u64 +
+
+ +
+
+chain_id: u8 +
+
+ +
+
+threshold_type: u8 +
+
+ +
+
+ + +
+ + + +## Struct `OnChainAggregateCommitmentAllCommittees` + + + +
struct OnChainAggregateCommitmentAllCommittees has copy, drop
+
+ + + +
+Fields + + +
+
+commitments: vector<supra_dkg::OnChainAggregateCommitment> +
+
+ +
+
+ + +
+ + + +## Constants + + + + + + +
const EDKG_INVALID_PK_SHARES: u64 = 4;
+
+ + + + + + + +
const EDKG_META_ALREADY_SET: u64 = 2;
+
+ + + + + + + +
const EDKG_META_NOT_SET: u64 = 3;
+
+ + + + + + + +
const EDKG_NOT_IN_PROGRESS: u64 = 1;
+
+ + + + + +## Function `initialize` + +Called in genesis to initialize on-chain states when DKG is active from genesis, +otherwise, must be called from a governance script before the DKG feature flag +is activated. + + +
public fun initialize(supra_framework: &signer)
+
+ + + +
+Implementation + + +
public fun initialize(supra_framework: &signer) {
+    system_addresses::assert_supra_framework(supra_framework);
+    if (!exists<DKGState>(@supra_framework)) {
+        move_to<DKGState>(
+            supra_framework,
+            DKGState {
+                last_completed: std::option::none(),
+                in_progress: std::option::none()
+            }
+        );
+    };
+}
+
+ + + +
+ + + +## Function `start` + +Mark on-chain DKG state as in-progress. Notify validators to start DKG. +Abort if a DKG is already in progress. + + +
public(friend) fun start(dealer_epoch: u64, randomness_seed: vector<u8>, dealer_committee: dkg_committee::DkgCommittee, target_committees: vector<dkg_committee::ReceiverCommittee>)
+
+ + + +
+Implementation + + +
public(friend) fun start(
+    dealer_epoch: u64,
+    randomness_seed: vector<u8>,
+    dealer_committee: DkgCommittee,
+    target_committees: vector<ReceiverCommittee>
+) acquires DKGState {
+    let dkg_state = borrow_global_mut<DKGState>(@supra_framework);
+    let new_session_metadata = DKGSessionMetadata {
+        dealer_epoch,
+        randomness_seed,
+        dealer_committee,
+        target_committees
+    };
+    let start_time_us = timestamp::now_microseconds();
+    dkg_state.in_progress = std::option::some(
+        DKGSessionState {
+            metadata: new_session_metadata,
+            start_time_us,
+            dkg_meta_transcript: vector[],
+            target_committees_public_key_shares: vector[]
+        }
+    );
+
+    emit(DKGStartEvent { start_time_us, session_metadata: new_session_metadata });
+}
+
+ + + +
+ + + +## Function `set_dkg_meta` + +Family Node sets the DKGMeta for the in-progress DKG session +The dkg transcript is assumed to have been already verified by the aptos VM in process_dkg_result method + + +
public(friend) fun set_dkg_meta(dkg_meta_all_committees: vector<u8>)
+
+ + + +
+Implementation + + +
public(friend) fun set_dkg_meta(dkg_meta_all_committees: vector<u8>) acquires DKGState {
+    // ensure dkg is in progress
+    let dkg_state = borrow_global_mut<DKGState>(@supra_framework);
+    assert!(
+        option::is_some(&dkg_state.in_progress),
+        error::invalid_state(EDKG_NOT_IN_PROGRESS)
+    );
+
+    // we only add the first DKG Meta proposed and ignore the rest
+    let session = option::extract(&mut dkg_state.in_progress);
+    assert!(
+        vector::length(&session.dkg_meta_transcript) == 0,
+        error::already_exists(EDKG_META_ALREADY_SET)
+    );
+    session.dkg_meta_transcript = dkg_meta_all_committees;
+    dkg_state.in_progress = option::some(session);
+
+    emit(DKGMetaSetEvent { dkg_meta_transcript: dkg_meta_all_committees });
+}
+
+ + + +
+ + + +## Function `finish` + +Family Node sets the target_committees_public_key_shares for the in-progress DKG session and +marks the incomplete DKG session completed. +The target_committees_public_key_shares is assumed to be verified by the aptos VM before calling this function + + +
public(friend) fun finish(target_committees_public_key_shares: vector<u8>)
+
+ + + +
+Implementation + + +
public(friend) fun finish(
+    target_committees_public_key_shares: vector<u8>
+) acquires DKGState {
+    // ensure dkg is in progress
+    let dkg_state = borrow_global_mut<DKGState>(@supra_framework);
+    assert!(
+        option::is_some(&dkg_state.in_progress),
+        error::invalid_state(EDKG_NOT_IN_PROGRESS)
+    );
+
+    // DKG meta should be already set before `finish` is called
+    let session = option::extract(&mut dkg_state.in_progress);
+    assert!(
+        vector::length(&session.dkg_meta_transcript) > 0,
+        error::already_exists(EDKG_META_NOT_SET)
+    );
+
+    session.target_committees_public_key_shares = target_committees_public_key_shares;
+    dkg_state.last_completed = option::some(session);
+    dkg_state.in_progress = option::none();
+
+    // propagate updated keys to stake.move for all threshold types
+    let public_key_shares_all_comms_serialized =
+        any::new(
+            type_info::type_name<OnChainAggregateCommitmentAllCommittees>(),
+            target_committees_public_key_shares
+        );
+    let public_key_shares_all_comms =
+        any::unpack<OnChainAggregateCommitmentAllCommittees>(
+            public_key_shares_all_comms_serialized
+        );
+
+    // Build a vector of DkgCommitteeOutput for all committees
+    let committee_outputs = vector[];
+    let i = 0;
+    let len = vector::length(&public_key_shares_all_comms.commitments);
+    while (i < len) {
+        let commitment = vector::borrow(&public_key_shares_all_comms.commitments, i);
+        // As the first index contains the committee's threshold public key, we can skip that
+        let evals = vector::slice(
+            &commitment.bls12381_commitment_evals,
+            1,
+            vector::length(&commitment.bls12381_commitment_evals)
+        );
+
+        vector::push_back(
+            &mut committee_outputs,
+            new_dkg_committee_output(commitment.threshold_type, evals)
+        );
+        i = i + 1;
+    };
+
+    // Set all keys for all threshold types
+    stake::set_dkg_output_keys(committee_outputs);
+    emit(DKGFinishEvent { target_committees_public_key_shares });
+}
+
+ + + +
+ + + +## Function `try_clear_incomplete_session` + +Delete the currently incomplete session, if it exists. + + +
public fun try_clear_incomplete_session(fx: &signer)
+
+ + + +
+Implementation + + +
public fun try_clear_incomplete_session(fx: &signer) acquires DKGState {
+    system_addresses::assert_supra_framework(fx);
+    if (exists<DKGState>(@supra_framework)) {
+        let dkg_state = borrow_global_mut<DKGState>(@supra_framework);
+        dkg_state.in_progress = option::none();
+    }
+}
+
+ + + +
+ + + +## Function `incomplete_session` + +Return the incomplete DKG session state, if it exists. + + +
public fun incomplete_session(): option::Option<supra_dkg::DKGSessionState>
+
+ + + +
+Implementation + + +
public fun incomplete_session(): Option<DKGSessionState> acquires DKGState {
+    if (exists<DKGState>(@supra_framework)) {
+        borrow_global<DKGState>(@supra_framework).in_progress
+    } else {
+        option::none()
+    }
+}
+
+ + + +
+ + + +## Function `last_completed_session` + +Return the last completed DKG session state, if it exists. + + +
public fun last_completed_session(): option::Option<supra_dkg::DKGSessionState>
+
+ + + +
+Implementation + + +
public fun last_completed_session(): Option<DKGSessionState> acquires DKGState {
+    if (exists<DKGState>(@supra_framework)) {
+        borrow_global<DKGState>(@supra_framework).last_completed
+    } else {
+        option::none()
+    }
+}
+
+ + + +
+ + + +## Function `session_dealer_epoch` + +Return the dealer epoch of a DKGSessionState. + + +
public fun session_dealer_epoch(session: &supra_dkg::DKGSessionState): u64
+
+ + + +
+Implementation + + +
public fun session_dealer_epoch(session: &DKGSessionState): u64 {
+    session.metadata.dealer_epoch
+}
+
+ + + +
+ + + +## Specification + + + +
invariant [suspendable] chain_status::is_operating() ==>
+    exists<DKGState>(@supra_framework);
+
+ + + + + +### Function `initialize` + + +
public fun initialize(supra_framework: &signer)
+
+ + + + +
let supra_framework_addr = signer::address_of(supra_framework);
+aborts_if supra_framework_addr != @supra_framework;
+
+ + + + + +### Function `start` + + +
public(friend) fun start(dealer_epoch: u64, randomness_seed: vector<u8>, dealer_committee: dkg_committee::DkgCommittee, target_committees: vector<dkg_committee::ReceiverCommittee>)
+
+ + + + +
aborts_if !exists<DKGState>(@supra_framework);
+aborts_if !exists<timestamp::CurrentTimeMicroseconds>(@supra_framework);
+
+ + + + + +### Function `set_dkg_meta` + + +
public(friend) fun set_dkg_meta(dkg_meta_all_committees: vector<u8>)
+
+ + + + +
requires exists<DKGState>(@supra_framework);
+requires option::is_some(global<DKGState>(@supra_framework).in_progress);
+aborts_if false;
+
+ + + + + +### Function `finish` + + +
public(friend) fun finish(target_committees_public_key_shares: vector<u8>)
+
+ + + + +
requires exists<DKGState>(@supra_framework);
+requires option::is_some(global<DKGState>(@supra_framework).in_progress);
+aborts_if false;
+
+ + + + + + + +
fun has_incomplete_session(): bool {
+   if (exists<DKGState>(@supra_framework)) {
+       option::spec_is_some(global<DKGState>(@supra_framework).in_progress)
+   } else { false }
+}
+
+ + + + + +### Function `try_clear_incomplete_session` + + +
public fun try_clear_incomplete_session(fx: &signer)
+
+ + + + +
let addr = signer::address_of(fx);
+aborts_if addr != @supra_framework;
+
+ + + + + +### Function `incomplete_session` + + +
public fun incomplete_session(): option::Option<supra_dkg::DKGSessionState>
+
+ + + + +
aborts_if false;
+
+ + +[move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/supra-framework/doc/supra_governance.md b/aptos-move/framework/supra-framework/doc/supra_governance.md index 64324f0d9d0..77fd580446d 100644 --- a/aptos-move/framework/supra-framework/doc/supra_governance.md +++ b/aptos-move/framework/supra-framework/doc/supra_governance.md @@ -79,7 +79,6 @@ on a proposal multiple times as long as the total voting power of these votes do
use 0x1::account;
-use 0x1::consensus_config;
 use 0x1::error;
 use 0x1::event;
 use 0x1::features;
@@ -633,9 +632,7 @@ Stores the signer capability for a given address.
 
 
 
public fun store_signer_cap(
-    supra_framework: &signer,
-    signer_address: address,
-    signer_cap: SignerCapability,
+    supra_framework: &signer, signer_address: address, signer_cap: SignerCapability
 ) acquires GovernanceResponsbility {
     system_addresses::assert_supra_framework(supra_framework);
     system_addresses::assert_framework_reserved(signer_address);
@@ -643,11 +640,14 @@ Stores the signer capability for a given address.
     if (!exists<GovernanceResponsbility>(@supra_framework)) {
         move_to(
             supra_framework,
-            GovernanceResponsbility { signer_caps: simple_map::create<address, SignerCapability>() }
+            GovernanceResponsbility {
+                signer_caps: simple_map::create<address, SignerCapability>()
+            }
         );
     };
 
-    let signer_caps = &mut borrow_global_mut<GovernanceResponsbility>(@supra_framework).signer_caps;
+    let signer_caps =
+        &mut borrow_global_mut<GovernanceResponsbility>(@supra_framework).signer_caps;
     simple_map::add(signer_caps, signer_address, signer_cap);
 }
 
@@ -678,26 +678,42 @@ This function is private because it's called directly from the vm. supra_framework: &signer, voting_duration_secs: u64, min_voting_threshold: u64, - voters: vector<address>, + voters: vector<address> ) { multisig_voting::register<GovernanceProposal>(supra_framework); - assert!(vector::length(&voters) >= min_voting_threshold && min_voting_threshold > vector::length(&voters) / 2, error::invalid_argument(ETHRESHOLD_EXCEEDS_VOTERS)); - assert!(min_voting_threshold > 1, error::invalid_argument(ETHRESHOLD_MUST_BE_GREATER_THAN_ONE)); - - move_to(supra_framework, SupraGovernanceConfig { - voting_duration_secs, - min_voting_threshold, - voters, - }); - move_to(supra_framework, SupraGovernanceEvents { - create_proposal_events: account::new_event_handle<SupraCreateProposalEvent>(supra_framework), - update_config_events: account::new_event_handle<SupraUpdateConfigEvent>(supra_framework), - vote_events: account::new_event_handle<SupraVoteEvent>(supra_framework), - }); - move_to(supra_framework, ApprovedExecutionHashes { - hashes: simple_map::create<u64, vector<u8>>(), - }) + assert!( + vector::length(&voters) >= min_voting_threshold + && min_voting_threshold > vector::length(&voters) / 2, + error::invalid_argument(ETHRESHOLD_EXCEEDS_VOTERS) + ); + assert!( + min_voting_threshold > 1, + error::invalid_argument(ETHRESHOLD_MUST_BE_GREATER_THAN_ONE) + ); + + move_to( + supra_framework, + SupraGovernanceConfig { voting_duration_secs, min_voting_threshold, voters } + ); + move_to( + supra_framework, + SupraGovernanceEvents { + create_proposal_events: account::new_event_handle<SupraCreateProposalEvent>( + supra_framework + ), + update_config_events: account::new_event_handle<SupraUpdateConfigEvent>( + supra_framework + ), + vote_events: account::new_event_handle<SupraVoteEvent>(supra_framework) + } + ); + move_to( + supra_framework, + ApprovedExecutionHashes { + hashes: simple_map::create<u64, vector<u8>>() + } + ) }
@@ -726,35 +742,35 @@ SupraGovernance. supra_framework: &signer, voting_duration_secs: u64, min_voting_threshold: u64, - voters: vector<address>, + voters: vector<address> ) acquires SupraGovernanceConfig, SupraGovernanceEvents { system_addresses::assert_supra_framework(supra_framework); - assert!(vector::length(&voters) >= min_voting_threshold && min_voting_threshold > vector::length(&voters) / 2, error::invalid_argument(ETHRESHOLD_EXCEEDS_VOTERS)); - assert!(min_voting_threshold > 1, error::invalid_argument(ETHRESHOLD_MUST_BE_GREATER_THAN_ONE)); + assert!( + vector::length(&voters) >= min_voting_threshold + && min_voting_threshold > vector::length(&voters) / 2, + error::invalid_argument(ETHRESHOLD_EXCEEDS_VOTERS) + ); + assert!( + min_voting_threshold > 1, + error::invalid_argument(ETHRESHOLD_MUST_BE_GREATER_THAN_ONE) + ); - let supra_governance_config = borrow_global_mut<SupraGovernanceConfig>(@supra_framework); + let supra_governance_config = + borrow_global_mut<SupraGovernanceConfig>(@supra_framework); supra_governance_config.voting_duration_secs = voting_duration_secs; supra_governance_config.min_voting_threshold = min_voting_threshold; supra_governance_config.voters = voters; if (std::features::module_event_migration_enabled()) { event::emit( - SupraUpdateConfig { - min_voting_threshold, - voting_duration_secs, - voters, - }, + SupraUpdateConfig { min_voting_threshold, voting_duration_secs, voters } ) }; let events = borrow_global_mut<SupraGovernanceEvents>(@supra_framework); event::emit_event<SupraUpdateConfigEvent>( &mut events.update_config_events, - SupraUpdateConfigEvent { - min_voting_threshold, - voting_duration_secs, - voters, - }, + SupraUpdateConfigEvent { min_voting_threshold, voting_duration_secs, voters } ); }
@@ -860,9 +876,15 @@ only the exact script with matching hash can be successfully executed. proposer: &signer, execution_hash: vector<u8>, metadata_location: vector<u8>, - metadata_hash: vector<u8>, + metadata_hash: vector<u8> ) acquires SupraGovernanceConfig, SupraGovernanceEvents { - supra_create_proposal_v2(proposer, execution_hash, metadata_location, metadata_hash, false); + supra_create_proposal_v2( + proposer, + execution_hash, + metadata_location, + metadata_hash, + false + ); }
@@ -893,7 +915,7 @@ only the exact script with matching hash can be successfully executed. execution_hash: vector<u8>, metadata_location: vector<u8>, metadata_hash: vector<u8>, - is_multi_step_proposal: bool, + is_multi_step_proposal: bool ) acquires SupraGovernanceConfig, SupraGovernanceEvents { supra_create_proposal_v2_impl( proposer, @@ -933,38 +955,46 @@ Return proposal_id when a proposal is successfully created. execution_hash: vector<u8>, metadata_location: vector<u8>, metadata_hash: vector<u8>, - is_multi_step_proposal: bool, + is_multi_step_proposal: bool ): u64 acquires SupraGovernanceConfig, SupraGovernanceEvents { let proposer_address = signer::address_of(proposer); - let supra_governance_config = borrow_global<SupraGovernanceConfig>(@supra_framework); + let supra_governance_config = + borrow_global<SupraGovernanceConfig>(@supra_framework); - assert!(vector::contains(&supra_governance_config.voters, &proposer_address), error::permission_denied(EACCOUNT_NOT_AUTHORIZED)); + assert!( + vector::contains(&supra_governance_config.voters, &proposer_address), + error::permission_denied(EACCOUNT_NOT_AUTHORIZED) + ); - let proposal_expiration = timestamp::now_seconds() + supra_governance_config.voting_duration_secs; + let proposal_expiration = + timestamp::now_seconds() + supra_governance_config.voting_duration_secs; // Create and validate proposal metadata. - let proposal_metadata = create_proposal_metadata(metadata_location, metadata_hash); - - let proposal_id = multisig_voting::create_proposal_v2( - proposer_address, - @supra_framework, - governance_proposal::create_proposal(), - execution_hash, - supra_governance_config.min_voting_threshold, - supra_governance_config.voters, - proposal_expiration, - proposal_metadata, - is_multi_step_proposal, + let proposal_metadata = create_proposal_metadata( + metadata_location, metadata_hash ); + let proposal_id = + multisig_voting::create_proposal_v2( + proposer_address, + @supra_framework, + governance_proposal::create_proposal(), + execution_hash, + supra_governance_config.min_voting_threshold, + supra_governance_config.voters, + proposal_expiration, + proposal_metadata, + is_multi_step_proposal + ); + if (std::features::module_event_migration_enabled()) { event::emit( SupraCreateProposal { proposal_id, proposer: proposer_address, execution_hash, - proposal_metadata, - }, + proposal_metadata + } ); }; let events = borrow_global_mut<SupraGovernanceEvents>(@supra_framework); @@ -974,8 +1004,8 @@ Return proposal_id when a proposal is successfully created. proposal_id, proposer: proposer_address, execution_hash, - proposal_metadata, - }, + proposal_metadata + } ); proposal_id } @@ -1002,9 +1032,7 @@ Vote on proposal with proposal_id and all voting power from s
public entry fun supra_vote(
-    voter: &signer,
-    proposal_id: u64,
-    should_pass: bool,
+    voter: &signer, proposal_id: u64, should_pass: bool
 ) acquires ApprovedExecutionHashes, SupraGovernanceEvents, SupraGovernanceConfig {
     supra_vote_internal(voter, proposal_id, should_pass);
 }
@@ -1034,50 +1062,50 @@ cannot vote on the proposal even after partial governance voting is enabled.
 
 
 
fun supra_vote_internal(
-    voter: &signer,
-    proposal_id: u64,
-    should_pass: bool,
+    voter: &signer, proposal_id: u64, should_pass: bool
 ) acquires ApprovedExecutionHashes, SupraGovernanceEvents, SupraGovernanceConfig {
     let voter_address = signer::address_of(voter);
 
-    let supra_governance_config = borrow_global<SupraGovernanceConfig>(@supra_framework);
-    assert!(vector::contains(&supra_governance_config.voters, &signer::address_of(voter)), error::permission_denied(EACCOUNT_NOT_AUTHORIZED));
+    let supra_governance_config =
+        borrow_global<SupraGovernanceConfig>(@supra_framework);
+    assert!(
+        vector::contains(
+            &supra_governance_config.voters, &signer::address_of(voter)
+        ),
+        error::permission_denied(EACCOUNT_NOT_AUTHORIZED)
+    );
 
     // The voter's stake needs to be locked up at least as long as the proposal's expiration.
-    let proposal_expiration = multisig_voting::get_proposal_expiration_secs<GovernanceProposal>(
-        @supra_framework,
-        proposal_id
+    let proposal_expiration =
+        multisig_voting::get_proposal_expiration_secs<GovernanceProposal>(
+            @supra_framework, proposal_id
+        );
+    assert!(
+        timestamp::now_seconds() <= proposal_expiration,
+        error::invalid_argument(EPROPOSAL_IS_EXPIRE)
     );
-    assert!(timestamp::now_seconds() <= proposal_expiration, error::invalid_argument(EPROPOSAL_IS_EXPIRE));
 
     multisig_voting::vote<GovernanceProposal>(
         voter,
         &governance_proposal::create_empty_proposal(),
         @supra_framework,
         proposal_id,
-        should_pass,
+        should_pass
     );
 
     if (std::features::module_event_migration_enabled()) {
-        event::emit(
-            SupraVote {
-                proposal_id,
-                voter: voter_address,
-                should_pass,
-            },
-        );
+        event::emit(SupraVote { proposal_id, voter: voter_address, should_pass });
     };
     let events = borrow_global_mut<SupraGovernanceEvents>(@supra_framework);
     event::emit_event<SupraVoteEvent>(
         &mut events.vote_events,
-        SupraVoteEvent {
-            proposal_id,
-            voter: voter_address,
-            should_pass,
-        },
+        SupraVoteEvent { proposal_id, voter: voter_address, should_pass }
     );
 
-    let proposal_state = multisig_voting::get_proposal_state<GovernanceProposal>(@supra_framework, proposal_id);
+    let proposal_state =
+        multisig_voting::get_proposal_state<GovernanceProposal>(
+            @supra_framework, proposal_id
+        );
     if (proposal_state == PROPOSAL_STATE_SUCCEEDED) {
         add_supra_approved_script_hash(proposal_id);
     }
@@ -1103,7 +1131,9 @@ cannot vote on the proposal even after partial governance voting is enabled.
 Implementation
 
 
-
public entry fun add_supra_approved_script_hash_script(proposal_id: u64) acquires ApprovedExecutionHashes {
+
public entry fun add_supra_approved_script_hash_script(
+    proposal_id: u64
+) acquires ApprovedExecutionHashes {
     add_supra_approved_script_hash(proposal_id)
 }
 
@@ -1131,18 +1161,29 @@ are too large (e.g. module upgrades).
public fun add_supra_approved_script_hash(proposal_id: u64) acquires ApprovedExecutionHashes {
-    let approved_hashes = borrow_global_mut<ApprovedExecutionHashes>(@supra_framework);
+    let approved_hashes =
+        borrow_global_mut<ApprovedExecutionHashes>(@supra_framework);
 
     // Ensure the proposal can be resolved.
-    let proposal_state = multisig_voting::get_proposal_state<GovernanceProposal>(@supra_framework, proposal_id);
-    assert!(proposal_state == PROPOSAL_STATE_SUCCEEDED, error::invalid_argument(EPROPOSAL_NOT_RESOLVABLE_YET));
+    let proposal_state =
+        multisig_voting::get_proposal_state<GovernanceProposal>(
+            @supra_framework, proposal_id
+        );
+    assert!(
+        proposal_state == PROPOSAL_STATE_SUCCEEDED,
+        error::invalid_argument(EPROPOSAL_NOT_RESOLVABLE_YET)
+    );
 
-    let execution_hash = multisig_voting::get_execution_hash<GovernanceProposal>(@supra_framework, proposal_id);
+    let execution_hash =
+        multisig_voting::get_execution_hash<GovernanceProposal>(
+            @supra_framework, proposal_id
+        );
 
     // If this is a multi-step proposal, the proposal id will already exist in the ApprovedExecutionHashes map.
     // We will update execution hash in ApprovedExecutionHashes to be the next_execution_hash.
     if (simple_map::contains_key(&approved_hashes.hashes, &proposal_id)) {
-        let current_execution_hash = simple_map::borrow_mut(&mut approved_hashes.hashes, &proposal_id);
+        let current_execution_hash =
+            simple_map::borrow_mut(&mut approved_hashes.hashes, &proposal_id);
         *current_execution_hash = execution_hash;
     } else {
         simple_map::add(&mut approved_hashes.hashes, proposal_id, execution_hash);
@@ -1172,8 +1213,7 @@ than yes).
 
 
 
public fun supra_resolve(
-    proposal_id: u64,
-    signer_address: address
+    proposal_id: u64, signer_address: address
 ): signer acquires ApprovedExecutionHashes, GovernanceResponsbility {
     multisig_voting::resolve<GovernanceProposal>(@supra_framework, proposal_id);
     remove_supra_approved_hash(proposal_id);
@@ -1202,11 +1242,11 @@ Resolve a successful multi-step proposal. This would fail if the proposal is not
 
 
 
public fun resolve_supra_multi_step_proposal(
-    proposal_id: u64,
-    signer_address: address,
-    next_execution_hash: vector<u8>
+    proposal_id: u64, signer_address: address, next_execution_hash: vector<u8>
 ): signer acquires GovernanceResponsbility, ApprovedExecutionHashes {
-    multisig_voting::resolve_proposal_v2<GovernanceProposal>(@supra_framework, proposal_id, next_execution_hash);
+    multisig_voting::resolve_proposal_v2<GovernanceProposal>(
+        @supra_framework, proposal_id, next_execution_hash
+    );
     // If the current step is the last step of this multi-step proposal,
     // we will remove the execution hash from the ApprovedExecutionHashes map.
     if (vector::length(&next_execution_hash) == 0) {
@@ -1243,11 +1283,14 @@ Remove an approved proposal's execution script hash.
 
 
public fun remove_supra_approved_hash(proposal_id: u64) acquires ApprovedExecutionHashes {
     assert!(
-        multisig_voting::is_resolved<GovernanceProposal>(@supra_framework, proposal_id),
-        error::invalid_argument(EPROPOSAL_NOT_RESOLVED_YET),
+        multisig_voting::is_resolved<GovernanceProposal>(
+            @supra_framework, proposal_id
+        ),
+        error::invalid_argument(EPROPOSAL_NOT_RESOLVED_YET)
     );
 
-    let approved_hashes = &mut borrow_global_mut<ApprovedExecutionHashes>(@supra_framework).hashes;
+    let approved_hashes =
+        &mut borrow_global_mut<ApprovedExecutionHashes>(@supra_framework).hashes;
     if (simple_map::contains_key(approved_hashes, &proposal_id)) {
         simple_map::remove(approved_hashes, &proposal_id);
     };
@@ -1265,12 +1308,12 @@ Remove an approved proposal's execution script hash.
 Manually reconfigure. Called at the end of a governance txn that alters on-chain configs.
 
 WARNING: this function always ensures a reconfiguration starts, but when the reconfiguration finishes depends.
-- If feature RECONFIGURE_WITH_DKG is disabled, it finishes immediately.
+- If feature SUPRA_DKG is disabled, it finishes immediately.
 - At the end of the calling transaction, we will be in a new epoch.
-- If feature RECONFIGURE_WITH_DKG is enabled, it starts DKG, and the new epoch will start in a block prologue after DKG finishes.
+- If feature SUPRA_DKG is enabled, it starts DKG, and the new epoch will start in a block prologue after DKG finishes.
 
 This behavior affects when an update of an on-chain config (e.g. ConsensusConfig, Features) takes effect,
-since such updates are applied whenever we enter an new epoch.
+since such updates are applied whenever we enter a new epoch.
 
 
 
public entry fun reconfigure(supra_framework: &signer)
@@ -1284,7 +1327,11 @@ since such updates are applied whenever we enter an new epoch.
 
 
public entry fun reconfigure(supra_framework: &signer) {
     system_addresses::assert_supra_framework(supra_framework);
-    if (consensus_config::validator_txn_enabled() && randomness_config::enabled()) {
+
+    // The block executor should seed the randomness config with the digest of the last
+    // block of the first epoch in which the DKG is enabled, so the second conjunct should
+    // always be true once the first is true. We keep it for safety in case of regression.
+    if (features::supra_dkg_enabled() && randomness_config::enabled()) {
         reconfiguration_with_dkg::try_start();
     } else {
         reconfiguration_with_dkg::finish(supra_framework);
@@ -1301,7 +1348,7 @@ since such updates are applied whenever we enter an new epoch.
 ## Function `force_end_epoch`
 
 Change epoch immediately.
-If RECONFIGURE_WITH_DKG is enabled and we are in the middle of a DKG,
+If SUPRA_DKG is enabled and we are in the middle of a DKG,
 stop waiting for DKG and enter the new epoch without randomness.
 
 WARNING: currently only used by tests. In most cases you should use reconfigure() instead.
@@ -1344,7 +1391,9 @@ where the core resources account exists and has been granted power to mint Supra
 Implementation
 
 
-
public entry fun force_end_epoch_test_only(supra_framework: &signer) acquires GovernanceResponsbility {
+
public entry fun force_end_epoch_test_only(
+    supra_framework: &signer
+) acquires GovernanceResponsbility {
     let core_signer = get_signer_testnet_only(supra_framework, @0x1);
     system_addresses::assert_supra_framework(&core_signer);
     reconfiguration_with_dkg::finish(&core_signer);
@@ -1371,7 +1420,9 @@ Update feature flags and also trigger reconfiguration.
 Implementation
 
 
-
public fun toggle_features(supra_framework: &signer, enable: vector<u64>, disable: vector<u64>) {
+
public fun toggle_features(
+    supra_framework: &signer, enable: vector<u64>, disable: vector<u64>
+) {
     system_addresses::assert_supra_framework(supra_framework);
     features::change_feature_flags_for_next_epoch(supra_framework, enable, disable);
     reconfigure(supra_framework);
@@ -1399,10 +1450,14 @@ Only called in testnet where the core resources account exists and has been gran
 
 
 
public fun get_signer_testnet_only(
-    core_resources: &signer, signer_address: address): signer acquires GovernanceResponsbility {
+    core_resources: &signer, signer_address: address
+): signer acquires GovernanceResponsbility {
     system_addresses::assert_core_resource(core_resources);
     // Core resources account only has mint capability in tests/testnets.
-    assert!(supra_coin::has_mint_capability(core_resources), error::unauthenticated(EUNAUTHORIZED));
+    assert!(
+        supra_coin::has_mint_capability(core_resources),
+        error::unauthenticated(EUNAUTHORIZED)
+    );
     get_signer(signer_address)
 }
 
@@ -1428,8 +1483,10 @@ Return a signer for making changes to 0x1 as part of on-chain governance proposa
fun get_signer(signer_address: address): signer acquires GovernanceResponsbility {
-    let governance_responsibility = borrow_global<GovernanceResponsbility>(@supra_framework);
-    let signer_cap = simple_map::borrow(&governance_responsibility.signer_caps, &signer_address);
+    let governance_responsibility =
+        borrow_global<GovernanceResponsbility>(@supra_framework);
+    let signer_cap =
+        simple_map::borrow(&governance_responsibility.signer_caps, &signer_address);
     create_signer_with_capability(signer_cap)
 }
 
@@ -1454,11 +1511,16 @@ Return a signer for making changes to 0x1 as part of on-chain governance proposa
fun create_proposal_metadata(
-    metadata_location: vector<u8>,
-    metadata_hash: vector<u8>
+    metadata_location: vector<u8>, metadata_hash: vector<u8>
 ): SimpleMap<String, vector<u8>> {
-    assert!(string::length(&utf8(metadata_location)) <= 256, error::invalid_argument(EMETADATA_LOCATION_TOO_LONG));
-    assert!(string::length(&utf8(metadata_hash)) <= 256, error::invalid_argument(EMETADATA_HASH_TOO_LONG));
+    assert!(
+        string::length(&utf8(metadata_location)) <= 256,
+        error::invalid_argument(EMETADATA_LOCATION_TOO_LONG)
+    );
+    assert!(
+        string::length(&utf8(metadata_hash)) <= 256,
+        error::invalid_argument(EMETADATA_HASH_TOO_LONG)
+    );
 
     let metadata = simple_map::create<String, vector<u8>>();
     simple_map::add(&mut metadata, utf8(METADATA_LOCATION_KEY), metadata_location);
diff --git a/aptos-move/framework/supra-framework/doc/transaction_context.md b/aptos-move/framework/supra-framework/doc/transaction_context.md
index 6e3c7fd2154..05d2ab8f16e 100644
--- a/aptos-move/framework/supra-framework/doc/transaction_context.md
+++ b/aptos-move/framework/supra-framework/doc/transaction_context.md
@@ -37,6 +37,8 @@
 -  [Function `args`](#0x1_transaction_context_args)
 -  [Function `multisig_payload`](#0x1_transaction_context_multisig_payload)
 -  [Function `multisig_payload_internal`](#0x1_transaction_context_multisig_payload_internal)
+-  [Function `get_transaction_consensus_hash`](#0x1_transaction_context_get_transaction_consensus_hash)
+-  [Function `get_transaction_consensus_hash_internal`](#0x1_transaction_context_get_transaction_consensus_hash_internal)
 -  [Function `multisig_address`](#0x1_transaction_context_multisig_address)
 -  [Function `inner_entry_function_payload`](#0x1_transaction_context_inner_entry_function_payload)
 -  [Specification](#@Specification_1)
@@ -911,6 +913,56 @@ This function aborts if called outside of the transaction prologue, execution, o
 
 
 
+
+ + + +## Function `get_transaction_consensus_hash` + +Returns the Keccak-256 hash of the current signed transaction (the transaction consensus hash). +This is distinct from get_transaction_hash(), which returns the session UUID hash. +Aborts if called outside a user transaction context. + + +
public fun get_transaction_consensus_hash(): vector<u8>
+
+ + + +
+Implementation + + +
public fun get_transaction_consensus_hash(): vector<u8> {
+    assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED));
+    get_transaction_consensus_hash_internal()
+}
+
+ + + +
+ + + +## Function `get_transaction_consensus_hash_internal` + + + +
fun get_transaction_consensus_hash_internal(): vector<u8>
+
+ + + +
+Implementation + + +
native fun get_transaction_consensus_hash_internal(): vector<u8>;
+
+ + +
diff --git a/aptos-move/framework/supra-framework/doc/validator_public_keys.md b/aptos-move/framework/supra-framework/doc/validator_public_keys.md new file mode 100644 index 00000000000..af5be0c5e11 --- /dev/null +++ b/aptos-move/framework/supra-framework/doc/validator_public_keys.md @@ -0,0 +1,1293 @@ + + + +# Module `0x1::validator_public_keys` + + + +- [Struct `CertificateThresholdType`](#0x1_validator_public_keys_CertificateThresholdType) +- [Struct `InternalPublicKeys`](#0x1_validator_public_keys_InternalPublicKeys) +- [Struct `ValidatorPublicKeys`](#0x1_validator_public_keys_ValidatorPublicKeys) +- [Constants](#@Constants_0) +- [Function `validity_certificate_type`](#0x1_validator_public_keys_validity_certificate_type) +- [Function `quorum_certificate_type`](#0x1_validator_public_keys_quorum_certificate_type) +- [Function `unanimous_certificate_type`](#0x1_validator_public_keys_unanimous_certificate_type) +- [Function `bcft_validity_certificate_type`](#0x1_validator_public_keys_bcft_validity_certificate_type) +- [Function `bcft_quorum_certificate_type`](#0x1_validator_public_keys_bcft_quorum_certificate_type) +- [Function `bcft_fallback_view_change_certificate_type`](#0x1_validator_public_keys_bcft_fallback_view_change_certificate_type) +- [Function `clan_majority_certificate_type`](#0x1_validator_public_keys_clan_majority_certificate_type) +- [Function `is_validity_certificate_type`](#0x1_validator_public_keys_is_validity_certificate_type) +- [Function `is_quorum_certificate_type`](#0x1_validator_public_keys_is_quorum_certificate_type) +- [Function `is_unanimous_certificate_type`](#0x1_validator_public_keys_is_unanimous_certificate_type) +- [Function `is_bcft_validity_certificate_type`](#0x1_validator_public_keys_is_bcft_validity_certificate_type) +- [Function `is_bcft_quorum_certificate_type`](#0x1_validator_public_keys_is_bcft_quorum_certificate_type) +- [Function `is_bcft_fallback_view_change_certificate_type`](#0x1_validator_public_keys_is_bcft_fallback_view_change_certificate_type) +- [Function `is_clan_majority_certificate_type`](#0x1_validator_public_keys_is_clan_majority_certificate_type) +- [Function `validator_public_keys_from_bytes`](#0x1_validator_public_keys_validator_public_keys_from_bytes) +- [Function `public_key_to_bytes`](#0x1_validator_public_keys_public_key_to_bytes) +- [Function `get_network_key`](#0x1_validator_public_keys_get_network_key) +- [Function `get_supra_bls_multi_sig_pub_key`](#0x1_validator_public_keys_get_supra_bls_multi_sig_pub_key) +- [Function `get_supra_cg_key`](#0x1_validator_public_keys_get_supra_cg_key) +- [Function `get_supra_ed_key`](#0x1_validator_public_keys_get_supra_ed_key) +- [Function `replace_static_keys`](#0x1_validator_public_keys_replace_static_keys) +- [Function `validate_static_keys`](#0x1_validator_public_keys_validate_static_keys) +- [Function `is_valid_ed25519_key`](#0x1_validator_public_keys_is_valid_ed25519_key) +- [Function `is_valid_bls12381_key`](#0x1_validator_public_keys_is_valid_bls12381_key) +- [Function `is_valid_cg_key`](#0x1_validator_public_keys_is_valid_cg_key) +- [Function `split_consensus_key_and_pop`](#0x1_validator_public_keys_split_consensus_key_and_pop) +- [Function `verify_bls_multisig_pop`](#0x1_validator_public_keys_verify_bls_multisig_pop) +- [Function `rotate_supra_bls_threshold_validity_key`](#0x1_validator_public_keys_rotate_supra_bls_threshold_validity_key) +- [Function `rotate_supra_bls_threshold_quorum_key`](#0x1_validator_public_keys_rotate_supra_bls_threshold_quorum_key) +- [Function `rotate_supra_bls_threshold_unanimous_key`](#0x1_validator_public_keys_rotate_supra_bls_threshold_unanimous_key) +- [Function `rotate_supra_bls_threshold_bcft_validity_key`](#0x1_validator_public_keys_rotate_supra_bls_threshold_bcft_validity_key) +- [Function `rotate_supra_bls_threshold_bcft_quorum_key`](#0x1_validator_public_keys_rotate_supra_bls_threshold_bcft_quorum_key) +- [Function `rotate_supra_bls_threshold_bcft_fallback_view_change_key`](#0x1_validator_public_keys_rotate_supra_bls_threshold_bcft_fallback_view_change_key) +- [Function `rotate_supra_bls_threshold_clan_majority_key`](#0x1_validator_public_keys_rotate_supra_bls_threshold_clan_majority_key) +- [Function `rotate_supra_bls_threshold_key_by_type`](#0x1_validator_public_keys_rotate_supra_bls_threshold_key_by_type) + + +
use 0x1::any;
+use 0x1::bcs;
+use 0x1::bls12381;
+use 0x1::class_groups;
+use 0x1::ed25519;
+use 0x1::error;
+use 0x1::option;
+use 0x1::string;
+use 0x1::type_info;
+use 0x1::vector;
+
+ + + + + +## Struct `CertificateThresholdType` + +Internal tag wrapper + + +
struct CertificateThresholdType has copy, drop, store
+
+ + + +
+Fields + + +
+
+tag: u8 +
+
+ +
+
+ + +
+ + + +## Struct `InternalPublicKeys` + +InternalPublicKeys consists of: +1. bls multisig key +2. bls threshold key shares for various certificate types +3. classgroup key +4. ed25519 key + + +
struct InternalPublicKeys has copy, drop, store
+
+ + + +
+Fields + + +
+
+bls_multisig_key: bls12381::PublicKey +
+
+ +
+
+bls_threshold_validity_certificate_key: option::Option<bls12381::PublicKey> +
+
+ +
+
+bls_threshold_quorum_certificate_key: option::Option<bls12381::PublicKey> +
+
+ +
+
+bls_threshold_unanimous_certificate_key: option::Option<bls12381::PublicKey> +
+
+ +
+
+bls_threshold_bcft_validity_certificate_key: option::Option<bls12381::PublicKey> +
+
+ +
+
+bls_threshold_bcft_quorum_certificate_key: option::Option<bls12381::PublicKey> +
+
+ +
+
+bls_threshold_bcft_fallback_view_change_certificate_key: option::Option<bls12381::PublicKey> +
+
+ +
+
+bls_threshold_clan_majority_certificate_key: option::Option<bls12381::PublicKey> +
+
+ +
+
+class_group_key: class_groups::CGPublicKey +
+
+ +
+
+ed25519_key: ed25519::ValidatedPublicKey +
+
+ +
+
+ + +
+ + + +## Struct `ValidatorPublicKeys` + +ValidatorPublicKeys consists of: +1. network key +2. supra's internal keys + + +
struct ValidatorPublicKeys has copy, drop, store
+
+ + + +
+Fields + + +
+
+network_key: ed25519::ValidatedPublicKey +
+
+ +
+
+supra_keys: validator_public_keys::InternalPublicKeys +
+
+ +
+
+ + +
+ + + +## Constants + + + + +The size of a serialized bls12381 G1 public key, in bytes. + + +
const BLS12381_G1_PUBLIC_KEY_NUM_BYTES: u64 = 48;
+
+ + + + + +The size of a serialized bls12381 proof-of-possession (a G2 signature), in bytes. + + +
const BLS12381_POP_NUM_BYTES: u64 = 96;
+
+ + + + + +The integer should match the Rust enum value representation in CertificateThresholdType. +n - f - c, given there are f Byzantine nodes and c crash-only nodes in the [Committee] with n >= 3f + 2c + 1 nodes. + + +
const CERTIFICATE_THRESHOLD_TYPE_BCFT_FALLBACK_VIEW_CHANGE: u8 = 5;
+
+ + + + + +The integer should match the Rust enum value representation in CertificateThresholdType +2f + c + 1, given there are f Byzantine nodes and c crash-only nodes in the [Committee] with n >= 3f + 2c + 1 nodes. + + +
const CERTIFICATE_THRESHOLD_TYPE_BCFT_QUORUM: u8 = 4;
+
+ + + + + +The integer should match the Rust enum value representation in CertificateThresholdType. +f+1, given there are f Byzantine nodes and c crash-only nodes in the [Committee] with n >= 3f + 2c + 1 nodes. + + +
const CERTIFICATE_THRESHOLD_TYPE_BCFT_VALIDITY: u8 = 3;
+
+ + + + + +The integer should match the Rust enum value representation in CertificateThresholdType. +f+1, given there are f Byzantine nodes in the [Committee] with n >= 2f + 1 nodes. + + +
const CERTIFICATE_THRESHOLD_TYPE_CLAN_MAJORITY: u8 = 6;
+
+ + + + + +The integer should match the Rust enum value representation in CertificateThresholdType. +2f+1, given there are f Byzantine nodes in the [Committee] and n >= 3f + 1 nodes in total. + + +
const CERTIFICATE_THRESHOLD_TYPE_QUORUM: u8 = 1;
+
+ + + + + +The integer should match the Rust enum value representation in CertificateThresholdType. +n, where n is the total number of nodes in the [Committee]. + + +
const CERTIFICATE_THRESHOLD_TYPE_UNANIMOUS: u8 = 2;
+
+ + + + + +The integer should match the Rust enum value representation in CertificateThresholdType. +f+1, given there are f Byzantine nodes in the [Committee]. + + +
const CERTIFICATE_THRESHOLD_TYPE_VALIDITY: u8 = 0;
+
+ + + + + +The size of a serialized ed25519 public key, in bytes. + + +
const ED25519_PUBLIC_KEY_NUM_BYTES: u64 = 32;
+
+ + + + + +Error: A consensus key blob is too short to contain an appended BLS proof-of-possession. + + +
const EINVALID_POP_LENGTH: u64 = 2;
+
+ + + + + +Error: Unknown certificate threshold type. + + +
const EUNKNOWN_THRESHOLD_TYPE: u64 = 1;
+
+ + + + + +## Function `validity_certificate_type` + + + +
public fun validity_certificate_type(): validator_public_keys::CertificateThresholdType
+
+ + + +
+Implementation + + +
public fun validity_certificate_type(): CertificateThresholdType {
+    CertificateThresholdType { tag: CERTIFICATE_THRESHOLD_TYPE_VALIDITY }
+}
+
+ + + +
+ + + +## Function `quorum_certificate_type` + + + +
public fun quorum_certificate_type(): validator_public_keys::CertificateThresholdType
+
+ + + +
+Implementation + + +
public fun quorum_certificate_type(): CertificateThresholdType {
+    CertificateThresholdType { tag: CERTIFICATE_THRESHOLD_TYPE_QUORUM }
+}
+
+ + + +
+ + + +## Function `unanimous_certificate_type` + + + +
public fun unanimous_certificate_type(): validator_public_keys::CertificateThresholdType
+
+ + + +
+Implementation + + +
public fun unanimous_certificate_type(): CertificateThresholdType {
+    CertificateThresholdType { tag: CERTIFICATE_THRESHOLD_TYPE_UNANIMOUS }
+}
+
+ + + +
+ + + +## Function `bcft_validity_certificate_type` + + + +
public fun bcft_validity_certificate_type(): validator_public_keys::CertificateThresholdType
+
+ + + +
+Implementation + + +
public fun bcft_validity_certificate_type(): CertificateThresholdType {
+    CertificateThresholdType { tag: CERTIFICATE_THRESHOLD_TYPE_BCFT_VALIDITY }
+}
+
+ + + +
+ + + +## Function `bcft_quorum_certificate_type` + + + +
public fun bcft_quorum_certificate_type(): validator_public_keys::CertificateThresholdType
+
+ + + +
+Implementation + + +
public fun bcft_quorum_certificate_type(): CertificateThresholdType {
+    CertificateThresholdType { tag: CERTIFICATE_THRESHOLD_TYPE_BCFT_QUORUM }
+}
+
+ + + +
+ + + +## Function `bcft_fallback_view_change_certificate_type` + + + +
public fun bcft_fallback_view_change_certificate_type(): validator_public_keys::CertificateThresholdType
+
+ + + +
+Implementation + + +
public fun bcft_fallback_view_change_certificate_type(): CertificateThresholdType {
+    CertificateThresholdType {
+        tag: CERTIFICATE_THRESHOLD_TYPE_BCFT_FALLBACK_VIEW_CHANGE
+    }
+}
+
+ + + +
+ + + +## Function `clan_majority_certificate_type` + + + +
public fun clan_majority_certificate_type(): validator_public_keys::CertificateThresholdType
+
+ + + +
+Implementation + + +
public fun clan_majority_certificate_type(): CertificateThresholdType {
+    CertificateThresholdType { tag: CERTIFICATE_THRESHOLD_TYPE_CLAN_MAJORITY }
+}
+
+ + + +
+ + + +## Function `is_validity_certificate_type` + + + +
public fun is_validity_certificate_type(t: &validator_public_keys::CertificateThresholdType): bool
+
+ + + +
+Implementation + + +
public fun is_validity_certificate_type(t: &CertificateThresholdType): bool {
+    t.tag == CERTIFICATE_THRESHOLD_TYPE_VALIDITY
+}
+
+ + + +
+ + + +## Function `is_quorum_certificate_type` + + + +
public fun is_quorum_certificate_type(t: &validator_public_keys::CertificateThresholdType): bool
+
+ + + +
+Implementation + + +
public fun is_quorum_certificate_type(t: &CertificateThresholdType): bool {
+    t.tag == CERTIFICATE_THRESHOLD_TYPE_QUORUM
+}
+
+ + + +
+ + + +## Function `is_unanimous_certificate_type` + + + +
public fun is_unanimous_certificate_type(t: &validator_public_keys::CertificateThresholdType): bool
+
+ + + +
+Implementation + + +
public fun is_unanimous_certificate_type(
+    t: &CertificateThresholdType
+): bool {
+    t.tag == CERTIFICATE_THRESHOLD_TYPE_UNANIMOUS
+}
+
+ + + +
+ + + +## Function `is_bcft_validity_certificate_type` + + + +
public fun is_bcft_validity_certificate_type(t: &validator_public_keys::CertificateThresholdType): bool
+
+ + + +
+Implementation + + +
public fun is_bcft_validity_certificate_type(
+    t: &CertificateThresholdType
+): bool {
+    t.tag == CERTIFICATE_THRESHOLD_TYPE_BCFT_VALIDITY
+}
+
+ + + +
+ + + +## Function `is_bcft_quorum_certificate_type` + + + +
public fun is_bcft_quorum_certificate_type(t: &validator_public_keys::CertificateThresholdType): bool
+
+ + + +
+Implementation + + +
public fun is_bcft_quorum_certificate_type(
+    t: &CertificateThresholdType
+): bool {
+    t.tag == CERTIFICATE_THRESHOLD_TYPE_BCFT_QUORUM
+}
+
+ + + +
+ + + +## Function `is_bcft_fallback_view_change_certificate_type` + + + +
public fun is_bcft_fallback_view_change_certificate_type(t: &validator_public_keys::CertificateThresholdType): bool
+
+ + + +
+Implementation + + +
public fun is_bcft_fallback_view_change_certificate_type(
+    t: &CertificateThresholdType
+): bool {
+    t.tag == CERTIFICATE_THRESHOLD_TYPE_BCFT_FALLBACK_VIEW_CHANGE
+}
+
+ + + +
+ + + +## Function `is_clan_majority_certificate_type` + + + +
public fun is_clan_majority_certificate_type(t: &validator_public_keys::CertificateThresholdType): bool
+
+ + + +
+Implementation + + +
public fun is_clan_majority_certificate_type(
+    t: &CertificateThresholdType
+): bool {
+    t.tag == CERTIFICATE_THRESHOLD_TYPE_CLAN_MAJORITY
+}
+
+ + + +
+ + + +## Function `validator_public_keys_from_bytes` + + + +
public fun validator_public_keys_from_bytes(bytes: vector<u8>): validator_public_keys::ValidatorPublicKeys
+
+ + + +
+Implementation + + +
public fun validator_public_keys_from_bytes(bytes: vector<u8>): ValidatorPublicKeys {
+    // bcs deserialization
+    let bytes_serialized =
+        any::new(type_info::type_name<ValidatorPublicKeys>(), bytes);
+    let validator_public_keys = any::unpack<ValidatorPublicKeys>(bytes_serialized);
+    validator_public_keys
+}
+
+ + + +
+ + + +## Function `public_key_to_bytes` + + + +
public fun public_key_to_bytes(pk: validator_public_keys::ValidatorPublicKeys): vector<u8>
+
+ + + +
+Implementation + + +
public fun public_key_to_bytes(pk: ValidatorPublicKeys): vector<u8> {
+    // bcs deserialization
+    bcs::to_bytes<ValidatorPublicKeys>(&pk)
+}
+
+ + + +
+ + + +## Function `get_network_key` + + + +
public fun get_network_key(pk: &validator_public_keys::ValidatorPublicKeys): ed25519::ValidatedPublicKey
+
+ + + +
+Implementation + + +
public fun get_network_key(pk: &ValidatorPublicKeys): ed25519::ValidatedPublicKey {
+    pk.network_key
+}
+
+ + + +
+ + + +## Function `get_supra_bls_multi_sig_pub_key` + + + +
public fun get_supra_bls_multi_sig_pub_key(pk: &validator_public_keys::ValidatorPublicKeys): bls12381::PublicKey
+
+ + + +
+Implementation + + +
public fun get_supra_bls_multi_sig_pub_key(pk: &ValidatorPublicKeys): bls12381::PublicKey {
+    pk.supra_keys.bls_multisig_key
+}
+
+ + + +
+ + + +## Function `get_supra_cg_key` + + + +
public fun get_supra_cg_key(pk: &validator_public_keys::ValidatorPublicKeys): class_groups::CGPublicKey
+
+ + + +
+Implementation + + +
public fun get_supra_cg_key(pk: &ValidatorPublicKeys): class_groups::CGPublicKey {
+    pk.supra_keys.class_group_key
+}
+
+ + + +
+ + + +## Function `get_supra_ed_key` + + + +
public fun get_supra_ed_key(pk: &validator_public_keys::ValidatorPublicKeys): ed25519::ValidatedPublicKey
+
+ + + +
+Implementation + + +
public fun get_supra_ed_key(pk: &ValidatorPublicKeys): ed25519::ValidatedPublicKey {
+    pk.supra_keys.ed25519_key
+}
+
+ + + +
+ + + +## Function `replace_static_keys` + +Overwrites the four static keys of target (network_key, bls_multisig_key, class_group_key, +ed25519_key) with those from source, leaving the DKG-managed BLS threshold key fields of +target untouched. Used by stake::rotate_consensus_key so that an operator key rotation +only changes the static keys and cannot clobber the threshold keys written by the DKG via +stake::set_dkg_output_keys. + + +
public fun replace_static_keys(target: &mut validator_public_keys::ValidatorPublicKeys, source: &validator_public_keys::ValidatorPublicKeys)
+
+ + + +
+Implementation + + +
public fun replace_static_keys(
+    target: &mut ValidatorPublicKeys, source: &ValidatorPublicKeys
+) {
+    target.network_key = source.network_key;
+    target.supra_keys.bls_multisig_key = source.supra_keys.bls_multisig_key;
+    target.supra_keys.class_group_key = source.supra_keys.class_group_key;
+    target.supra_keys.ed25519_key = source.supra_keys.ed25519_key;
+}
+
+ + + +
+ + + +## Function `validate_static_keys` + +Returns true iff the four static (non-DKG) public keys decode to cryptographically valid +keys: the network key, the BLS multisig key, the class-group key and the ed25519 key. + +validator_public_keys_from_bytes reconstructs each key's raw bytes via BCS without +running the per-key validation natives, so a registration blob can carry malformed keys +(the Validated*/PublicKey types are a misnomer after deserialization). This re-runs +each key's validating constructor on the recovered bytes to reject them. + +The DKG-managed BLS threshold key shares are intentionally not checked: they are absent at +registration and are produced/overwritten by the protocol via stake::set_dkg_output_keys +(which validates them). Proof-of-possession is not verified here either (no PoP is supplied +at registration); only key well-formedness / subgroup membership is checked. + + +
public fun validate_static_keys(pk: &validator_public_keys::ValidatorPublicKeys): bool
+
+ + + +
+Implementation + + +
public fun validate_static_keys(pk: &ValidatorPublicKeys): bool {
+    is_valid_ed25519_key(&pk.network_key)
+        && is_valid_bls12381_key(&pk.supra_keys.bls_multisig_key)
+        && is_valid_cg_key(&pk.supra_keys.class_group_key)
+        && is_valid_ed25519_key(&pk.supra_keys.ed25519_key)
+}
+
+ + + +
+ + + +## Function `is_valid_ed25519_key` + + + +
fun is_valid_ed25519_key(pk: &ed25519::ValidatedPublicKey): bool
+
+ + + +
+Implementation + + +
fun is_valid_ed25519_key(pk: &ed25519::ValidatedPublicKey): bool {
+    option::is_some(
+        &ed25519::new_validated_public_key_from_bytes(
+            ed25519::validated_public_key_to_bytes(pk)
+        )
+    )
+}
+
+ + + +
+ + + +## Function `is_valid_bls12381_key` + + + +
fun is_valid_bls12381_key(pk: &bls12381::PublicKey): bool
+
+ + + +
+Implementation + + +
fun is_valid_bls12381_key(pk: &bls12381::PublicKey): bool {
+    option::is_some(
+        &bls12381::public_key_from_bytes(bls12381::public_key_to_bytes(pk))
+    )
+}
+
+ + + +
+ + + +## Function `is_valid_cg_key` + + + +
fun is_valid_cg_key(pk: &class_groups::CGPublicKey): bool
+
+ + + +
+Implementation + + +
fun is_valid_cg_key(pk: &class_groups::CGPublicKey): bool {
+    option::is_some(
+        &class_groups::public_key_from_bytes(class_groups::public_key_to_bytes(pk))
+    )
+}
+
+ + + +
+ + + +## Function `split_consensus_key_and_pop` + +Splits a submitted consensus key blob into its ValidatorPublicKeys bytes (the prefix) and +the appended BLS12-381 proof-of-possession (the trailing BLS12381_POP_NUM_BYTES bytes). +Operators submit the PoP appended to the key bytes so that the contract can verify it +without a dedicated entry-function parameter (Move forbids changing public signatures). + + +
public fun split_consensus_key_and_pop(blob: vector<u8>): (vector<u8>, vector<u8>)
+
+ + + +
+Implementation + + +
public fun split_consensus_key_and_pop(blob: vector<u8>): (vector<u8>, vector<u8>) {
+    let len = vector::length(&blob);
+    assert!(len >= BLS12381_POP_NUM_BYTES, error::invalid_argument(EINVALID_POP_LENGTH));
+    let pop = vector::trim(&mut blob, len - BLS12381_POP_NUM_BYTES);
+    (blob, pop)
+}
+
+ + + +
+ + + +## Function `verify_bls_multisig_pop` + +Returns true iff pop_bytes is a valid BLS12-381 proof-of-possession for the BLS multisig +key in pk. The multisig key is the only aggregatable (hence rogue-key-attackable) key an +operator submits, so it is the only one that requires a PoP; the class-group key carries its +own ZK PoP (verified by its validate_pubkey_internal native), the ed25519 keys are +non-aggregated, and the BLS threshold shares are produced by the DKG. + + +
public fun verify_bls_multisig_pop(pk: &validator_public_keys::ValidatorPublicKeys, pop_bytes: vector<u8>): bool
+
+ + + +
+Implementation + + +
public fun verify_bls_multisig_pop(
+    pk: &ValidatorPublicKeys, pop_bytes: vector<u8>
+): bool {
+    let pk_bytes = bls12381::public_key_to_bytes(&pk.supra_keys.bls_multisig_key);
+    let pop = bls12381::proof_of_possession_from_bytes(pop_bytes);
+    option::is_some(&bls12381::public_key_from_bytes_with_pop(pk_bytes, &pop))
+}
+
+ + + +
+ + + +## Function `rotate_supra_bls_threshold_validity_key` + + + +
public fun rotate_supra_bls_threshold_validity_key(pk: &mut validator_public_keys::ValidatorPublicKeys, new_bls_threshold_validity_key: bls12381::PublicKey)
+
+ + + +
+Implementation + + +
public fun rotate_supra_bls_threshold_validity_key(
+    pk: &mut ValidatorPublicKeys, new_bls_threshold_validity_key: bls12381::PublicKey
+) {
+    pk.supra_keys.bls_threshold_validity_certificate_key = option::some(
+        new_bls_threshold_validity_key
+    );
+}
+
+ + + +
+ + + +## Function `rotate_supra_bls_threshold_quorum_key` + + + +
public fun rotate_supra_bls_threshold_quorum_key(pk: &mut validator_public_keys::ValidatorPublicKeys, new_bls_threshold_quorum_key: bls12381::PublicKey)
+
+ + + +
+Implementation + + +
public fun rotate_supra_bls_threshold_quorum_key(
+    pk: &mut ValidatorPublicKeys, new_bls_threshold_quorum_key: bls12381::PublicKey
+) {
+    pk.supra_keys.bls_threshold_quorum_certificate_key = option::some(
+        new_bls_threshold_quorum_key
+    );
+}
+
+ + + +
+ + + +## Function `rotate_supra_bls_threshold_unanimous_key` + + + +
public fun rotate_supra_bls_threshold_unanimous_key(pk: &mut validator_public_keys::ValidatorPublicKeys, new_key: bls12381::PublicKey)
+
+ + + +
+Implementation + + +
public fun rotate_supra_bls_threshold_unanimous_key(
+    pk: &mut ValidatorPublicKeys, new_key: bls12381::PublicKey
+) {
+    pk.supra_keys.bls_threshold_unanimous_certificate_key = option::some(new_key);
+}
+
+ + + +
+ + + +## Function `rotate_supra_bls_threshold_bcft_validity_key` + + + +
public fun rotate_supra_bls_threshold_bcft_validity_key(pk: &mut validator_public_keys::ValidatorPublicKeys, new_key: bls12381::PublicKey)
+
+ + + +
+Implementation + + +
public fun rotate_supra_bls_threshold_bcft_validity_key(
+    pk: &mut ValidatorPublicKeys, new_key: bls12381::PublicKey
+) {
+    pk.supra_keys.bls_threshold_bcft_validity_certificate_key = option::some(new_key);
+}
+
+ + + +
+ + + +## Function `rotate_supra_bls_threshold_bcft_quorum_key` + + + +
public fun rotate_supra_bls_threshold_bcft_quorum_key(pk: &mut validator_public_keys::ValidatorPublicKeys, new_key: bls12381::PublicKey)
+
+ + + +
+Implementation + + +
public fun rotate_supra_bls_threshold_bcft_quorum_key(
+    pk: &mut ValidatorPublicKeys, new_key: bls12381::PublicKey
+) {
+    pk.supra_keys.bls_threshold_bcft_quorum_certificate_key = option::some(new_key);
+}
+
+ + + +
+ + + +## Function `rotate_supra_bls_threshold_bcft_fallback_view_change_key` + + + +
public fun rotate_supra_bls_threshold_bcft_fallback_view_change_key(pk: &mut validator_public_keys::ValidatorPublicKeys, new_key: bls12381::PublicKey)
+
+ + + +
+Implementation + + +
public fun rotate_supra_bls_threshold_bcft_fallback_view_change_key(
+    pk: &mut ValidatorPublicKeys, new_key: bls12381::PublicKey
+) {
+    pk.supra_keys.bls_threshold_bcft_fallback_view_change_certificate_key = option::some(
+        new_key
+    );
+}
+
+ + + +
+ + + +## Function `rotate_supra_bls_threshold_clan_majority_key` + + + +
public fun rotate_supra_bls_threshold_clan_majority_key(pk: &mut validator_public_keys::ValidatorPublicKeys, new_key: bls12381::PublicKey)
+
+ + + +
+Implementation + + +
public fun rotate_supra_bls_threshold_clan_majority_key(
+    pk: &mut ValidatorPublicKeys, new_key: bls12381::PublicKey
+) {
+    pk.supra_keys.bls_threshold_clan_majority_certificate_key = option::some(new_key);
+}
+
+ + + +
+ + + +## Function `rotate_supra_bls_threshold_key_by_type` + +Rotate a threshold key based on the threshold type tag. +threshold_type: 0=validity, 1=quorum, 2=unanimous, 3=bcft_validity, 4=bcft_quorum, 5=bcft_fallback_view_change, 6=clan_majority + + +
public fun rotate_supra_bls_threshold_key_by_type(pk: &mut validator_public_keys::ValidatorPublicKeys, threshold_type: u8, new_key: bls12381::PublicKey)
+
+ + + +
+Implementation + + +
public fun rotate_supra_bls_threshold_key_by_type(
+    pk: &mut ValidatorPublicKeys, threshold_type: u8, new_key: bls12381::PublicKey
+) {
+    if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_VALIDITY) {
+        rotate_supra_bls_threshold_validity_key(pk, new_key);
+    } else if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_QUORUM) {
+        rotate_supra_bls_threshold_quorum_key(pk, new_key);
+    } else if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_UNANIMOUS) {
+        rotate_supra_bls_threshold_unanimous_key(pk, new_key);
+    } else if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_BCFT_VALIDITY) {
+        rotate_supra_bls_threshold_bcft_validity_key(pk, new_key);
+    } else if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_BCFT_QUORUM) {
+        rotate_supra_bls_threshold_bcft_quorum_key(pk, new_key);
+    } else if (threshold_type
+        == CERTIFICATE_THRESHOLD_TYPE_BCFT_FALLBACK_VIEW_CHANGE) {
+        rotate_supra_bls_threshold_bcft_fallback_view_change_key(pk, new_key);
+    } else if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_CLAN_MAJORITY) {
+        rotate_supra_bls_threshold_clan_majority_key(pk, new_key);
+    } else {
+        abort error::invalid_argument(EUNKNOWN_THRESHOLD_TYPE)
+    };
+}
+
+ + + +
+ + +[move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/supra-framework/doc/vesting_without_staking.md b/aptos-move/framework/supra-framework/doc/vesting_without_staking.md index 08dbd417921..0cd53c9ed17 100644 --- a/aptos-move/framework/supra-framework/doc/vesting_without_staking.md +++ b/aptos-move/framework/supra-framework/doc/vesting_without_staking.md @@ -39,6 +39,7 @@ Vesting without staking contract - [Function `vest`](#0x1_vesting_without_staking_vest) - [Function `vest_individual`](#0x1_vesting_without_staking_vest_individual) - [Function `vest_transfer`](#0x1_vesting_without_staking_vest_transfer) +- [Function `admin_delay_vesting`](#0x1_vesting_without_staking_admin_delay_vesting) - [Function `set_vesting_schedule`](#0x1_vesting_without_staking_set_vesting_schedule) - [Function `remove_shareholder`](#0x1_vesting_without_staking_remove_shareholder) - [Function `terminate_vesting_contract`](#0x1_vesting_without_staking_terminate_vesting_contract) @@ -660,6 +661,16 @@ Vesting schedule cannot be empty. + + +Invalid vesting delay parameter + + +
const EINVALID_VESTING_DELAY: u64 = 20;
+
+ + + Invalid vesting schedule parameter @@ -992,11 +1003,10 @@ This errors out if the vesting contract with the provided address doesn't exist. vesting_contract_address: address, shareholder_address: address ): (u64, u64, u64) acquires VestingContract { assert_vesting_contract_exists(vesting_contract_address); - let vesting_record = - simple_map::borrow( - &borrow_global<VestingContract>(vesting_contract_address).shareholders, - &shareholder_address, - ); + let vesting_record = simple_map::borrow( + &borrow_global<VestingContract>(vesting_contract_address).shareholders, + &shareholder_address, + ); ( vesting_record.init_amount, vesting_record.left_amount, @@ -1247,7 +1257,7 @@ Create a vesting schedule with the given schedule of distributions, a vesting st // last vesting fraction must be non zero to ensure that no amount remains unvested forever. assert!( fixed_point32::get_raw_value(*vector::borrow(&schedule, schedule_len - 1)) != - 0, + 0, error::invalid_argument(EEMPTY_VESTING_SCHEDULE), ); assert!( @@ -1424,20 +1434,23 @@ Create a vesting schedule with the given schedule of distributions, a vesting st // Initialize the vesting contract in a new resource account. This allows the same admin to create multiple // pools. - let (contract_signer, contract_signer_cap) = - create_vesting_contract_account(admin, contract_creation_seed); + let (contract_signer, contract_signer_cap) = create_vesting_contract_account( + admin, contract_creation_seed + ); let contract_signer_address = signer::address_of(&contract_signer); let schedule = vector::map_ref( &vesting_numerators, |numerator| { - let event = - fixed_point32::create_from_rational(*numerator, vesting_denominator); + let event = fixed_point32::create_from_rational( + *numerator, vesting_denominator + ); event }, ); - let vesting_schedule = - create_vesting_schedule(schedule, start_timestamp_secs, period_duration); + let vesting_schedule = create_vesting_schedule( + schedule, start_timestamp_secs, period_duration + ); let shareholders_map = simple_map::create<address, VestingRecord>(); let grant_amount = 0; vector::for_each_reverse( @@ -1571,8 +1584,9 @@ Create a vesting contract with a given configurations. // Initialize the vesting contract in a new resource account. This allows the same admin to create multiple // pools. - let (contract_signer, contract_signer_cap) = - create_vesting_contract_account(admin, contract_creation_seed); + let (contract_signer, contract_signer_cap) = create_vesting_contract_account( + admin, contract_creation_seed + ); let contract_signer_address = signer::address_of(&contract_signer); coin::deposit(contract_signer_address, grant); @@ -1688,10 +1702,9 @@ Unlock any vested portion of the grant. return }; - let vesting_record = - simple_map::borrow_mut( - &mut vesting_contract.shareholders, &shareholder_address - ); + let vesting_record = simple_map::borrow_mut( + &mut vesting_contract.shareholders, &shareholder_address + ); let signer_cap = &vesting_contract.signer_cap; // Check if the next vested period has already passed. If not, short-circuit since there's nothing to vest. @@ -1699,9 +1712,9 @@ Unlock any vested portion of the grant. let schedule = &vesting_schedule.schedule; let last_vested_period = vesting_record.last_vested_period; let next_period_to_vest = last_vested_period + 1; - let last_completed_period = - (timestamp::now_seconds() - vesting_schedule.start_timestamp_secs) / vesting_schedule - .period_duration; + let last_completed_period = ( + timestamp::now_seconds() - vesting_schedule.start_timestamp_secs + ) / vesting_schedule.period_duration; // Index is 0-based while period is 1-based so we need to subtract 1. let one = fixed_point32::create_from_rational(1, 1); @@ -1726,9 +1739,10 @@ Unlock any vested portion of the grant. let final_fraction = *vector::borrow(schedule, vector::length(schedule) - 1); // Determine how many periods is needed based on the left_amount periods_fast_forward = last_completed_period - next_period_to_vest + 1; - let added_fraction = fixed_point32::multiply_u64_return_fixpoint32( - periods_fast_forward, final_fraction - ); + let added_fraction = + fixed_point32::multiply_u64_return_fixpoint32( + periods_fast_forward, final_fraction + ); // If the added_fraction is greater than or equal to the left_amount, then we can vest all the left_amount total_vesting_fraction = fixed_point32::add( total_vesting_fraction, added_fraction @@ -1738,12 +1752,13 @@ Unlock any vested portion of the grant. // Make sure the total vesting fraction is not greater than 1. total_vesting_fraction = fixed_point32::min(total_vesting_fraction, one); // We don't need to check vesting_record.left_amount > 0 because vest_transfer will handle that. - let transfer_happened = vest_transfer( - vesting_record, - signer_cap, - beneficiary, - total_vesting_fraction, - ); + let transfer_happened = + vest_transfer( + vesting_record, + signer_cap, + beneficiary, + total_vesting_fraction, + ); //If no amount was transferred DO NOT advance last_vested_period in the vesting record // This check is needed because if the fraction is too low, `vesting_record.init_amount * vesting_fraction` // may be 0. By not advancing, we allow for the possibility for `vesting_fraction` to become large enough @@ -1794,11 +1809,10 @@ Unlock any vested portion of the grant. let vesting_signer = account::create_signer_with_capability(signer_cap); //amount to be transfer is minimum of what is left and vesting fraction due of init_amount - let amount = - min( - vesting_record.left_amount, - fixed_point32::multiply_u64(vesting_record.init_amount, vesting_fraction), - ); + let amount = min( + vesting_record.left_amount, + fixed_point32::multiply_u64(vesting_record.init_amount, vesting_fraction), + ); if (amount > 0) { //update left_amount for the shareholder vesting_record.left_amount = vesting_record.left_amount - amount; @@ -1810,6 +1824,48 @@ Unlock any vested portion of the grant. + + + + +## Function `admin_delay_vesting` + + + +
public entry fun admin_delay_vesting(admin: &signer, contract_address: address, delay_periods: u64)
+
+ + + +
+Implementation + + +
public entry fun admin_delay_vesting(
+    admin: &signer, contract_address: address, delay_periods: u64
+) acquires VestingContract {
+    assert_active_vesting_contract(contract_address);
+    let vesting_contract = borrow_global_mut<VestingContract>(contract_address);
+    verify_admin(admin, vesting_contract);
+
+    assert!(delay_periods > 0, error::invalid_argument(EINVALID_VESTING_DELAY));
+    let (shareholders, vrecords) = simple_map::to_vec_pair(
+        vesting_contract.shareholders
+    );
+    vector::zip_mut<address, VestingRecord>(
+        &mut shareholders,
+        &mut vrecords,
+        |_s, vrecord| {
+            let mrecord: &mut VestingRecord = vrecord;
+            mrecord.last_vested_period = mrecord.last_vested_period + delay_periods;
+        },
+    );
+    vesting_contract.shareholders = simple_map::new_from(shareholders, vrecords);
+}
+
+ + +
@@ -1856,9 +1912,8 @@ Unlock any vested portion of the grant. &mut values, |shareholder, srecord| { let msrecord: &mut VestingRecord = srecord; - let new_last_vested_period = ( - msrecord.last_vested_period * old_period_duration - ) / period_duration; + let new_last_vested_period = + (msrecord.last_vested_period * old_period_duration) / period_duration; msrecord.last_vested_period = new_last_vested_period; }, ); @@ -1907,8 +1962,9 @@ Example usage: If admin find shareholder suspicious, admin can remove it. let vesting_contract = borrow_global_mut<VestingContract>(contract_address); verify_admin(admin, vesting_contract); let vesting_signer = get_vesting_account_signer_internal(vesting_contract); - let shareholder_amount = - simple_map::borrow(&vesting_contract.shareholders, &shareholder_address).left_amount; + let shareholder_amount = simple_map::borrow( + &vesting_contract.shareholders, &shareholder_address + ).left_amount; coin::transfer<SupraCoin>( &vesting_signer, vesting_contract.withdrawal_address, shareholder_amount ); @@ -1923,16 +1979,18 @@ Example usage: If admin find shareholder suspicious, admin can remove it. // remove `shareholder_address`` from `vesting_contract.shareholders` let shareholders = &mut vesting_contract.shareholders; - let (_, shareholders_vesting) = - simple_map::remove(shareholders, &shareholder_address); + let (_, shareholders_vesting) = simple_map::remove( + shareholders, &shareholder_address + ); // remove `shareholder_address` from `vesting_contract.beneficiaries` let beneficiary = option::none(); let shareholder_beneficiaries = &mut vesting_contract.beneficiaries; // Not all shareholders have their beneficiaries, so before removing them, we need to check if the beneficiary exists if (simple_map::contains_key(shareholder_beneficiaries, &shareholder_address)) { - let (_, shareholder_baneficiary) = - simple_map::remove(shareholder_beneficiaries, &shareholder_address); + let (_, shareholder_baneficiary) = simple_map::remove( + shareholder_beneficiaries, &shareholder_address + ); beneficiary = option::some(shareholder_baneficiary); }; @@ -1983,10 +2041,9 @@ Terminate the vesting contract and send all funds back to the withdrawal address vector::for_each_ref( &shareholders_address, |shareholder| { - let shareholder_amount = - simple_map::borrow_mut( - &mut vesting_contract.shareholders, shareholder - ); + let shareholder_amount = simple_map::borrow_mut( + &mut vesting_contract.shareholders, shareholder + ); shareholder_amount.left_amount = 0; }, ); @@ -2119,9 +2176,9 @@ account. let vesting_contract = borrow_global_mut<VestingContract>(contract_address); let addr = signer::address_of(account); assert!( - addr == vesting_contract.admin - || addr - == get_role_holder(contract_address, utf8(ROLE_BENEFICIARY_RESETTER)), + addr == vesting_contract.admin || addr == get_role_holder( + contract_address, utf8(ROLE_BENEFICIARY_RESETTER) + ), error::permission_denied(EPERMISSION_DENIED), ); @@ -2167,8 +2224,7 @@ account. VestingAccountManagement { roles: simple_map::create<String, address>() }, ) }; - let roles = - &mut borrow_global_mut<VestingAccountManagement>(contract_address).roles; + let roles = &mut borrow_global_mut<VestingAccountManagement>(contract_address).roles; simple_map::upsert(roles, role, role_holder); }
diff --git a/aptos-move/framework/supra-framework/sources/aggregator_v2/aggregator_v2.move b/aptos-move/framework/supra-framework/sources/aggregator_v2/aggregator_v2.move index 3374c54c250..0e8bdc3f462 100644 --- a/aptos-move/framework/supra-framework/sources/aggregator_v2/aggregator_v2.move +++ b/aptos-move/framework/supra-framework/sources/aggregator_v2/aggregator_v2.move @@ -194,7 +194,7 @@ module supra_framework::aggregator_v2 { /// Concatenates `before`, `snapshot` and `after` into a single string. /// snapshot passed needs to have integer type - currently supported types are u64 and u128. /// Raises EUNSUPPORTED_AGGREGATOR_SNAPSHOT_TYPE if called with another type. - /// If length of prefix and suffix together exceeds 1024 bytes, ECONCAT_STRING_LENGTH_TOO_LARGE is raised. + /// If length of prefix and suffix together exceed 1024 bytes, ECONCAT_STRING_LENGTH_TOO_LARGE is raised. /// /// Parallelism info: This operation enables parallelism. public native fun derive_string_concat(before: String, snapshot: &AggregatorSnapshot, after: String): DerivedStringSnapshot; diff --git a/aptos-move/framework/supra-framework/sources/automation_registry.move b/aptos-move/framework/supra-framework/sources/automation_registry.move index cf8b970430a..6c34376ddbc 100644 --- a/aptos-move/framework/supra-framework/sources/automation_registry.move +++ b/aptos-move/framework/supra-framework/sources/automation_registry.move @@ -135,6 +135,11 @@ module supra_framework::automation_registry { const EREGISTRY_SYSTEM_MAX_GAS_CAP_NON_ZERO: u64 = 46; /// The input address is not identified as multisig account. const EUNKNOWN_MULTISIG_ADDRESS: u64 = 47; + /// The refund fee for remaining cycle time is greater than total cycle fee for the task. + const EINVALID_CYCLE_REFUND_FEE: u64 = 48; + /// Supra automation v2.1 feature is not enabled. Distinct from EDISABLED_AUTOMATION_FEATURE + /// (which covers the base automation feature) so callers can tell the two conditions apart. + const EDISABLED_AUTOMATION_V2_1_FEATURE: u64 = 49; /// The length of the transaction hash. const TXN_HASH_LENGTH: u64 = 32; @@ -637,6 +642,19 @@ module supra_framework::automation_registry { registration_hash: vector } + #[event] + /// Emitted when the VM/runtime cancels a task that was registered without payload + /// validation and was later found to be invalid. The `diagnostic_message` is a + /// human-readable explanation provided by the runtime (e.g. BCS decode error, unknown + /// entry function). Consumers should use this event -- rather than `TasksStoppedV2` alone -- + /// to distinguish runtime-driven cancellations from voluntary owner-initiated stops. + struct TaskCancelledByRuntime has drop, store { + task_index: u64, + owner: address, + registration_hash: vector, + diagnostic_message: std::string::String, + } + #[event] /// Event emitted on epoch transition containing removed task indexes. struct RemovedTasks has drop, store { @@ -818,6 +836,40 @@ module supra_framework::automation_registry { enumerable_map::get_value(®istry_state.main.tasks, task_index) } + /// Retrieves specific metadata details of an automation task entry by its task index. + /// + /// 1. `u64` - The task index. + /// 2. `address` - The owner of the task. + /// 3. `vector` - The payload transaction (encoded). + /// 4. `u64` - The expiry time of the task (timestamp). + /// 5. `vector` - The hash of the transaction. + /// 6. `u64` - The maximum gas amount allowed for the task. + /// 7. `u64` - The gas price cap for executing the task. + /// 8. `u64` - The automation fee cap for the current epoch. + /// 9. `vector>` - Auxiliary data related to the task (can be multiple items). + /// 10. `u64` - The time at which the task was registered (timestamp). + /// 11. `u8` - The state of the task (e.g., active, cancelled, completed). + /// 12. `u64` - The locked fee reserved for the next epoch execution. + // `deconstruct_task_metadata_v2` introduces task index in it's return list + public fun deconstruct_task_metadata_v2( + task_metadata: &AutomationTaskMetaData + ): (u64, address, vector, u64, vector, u64, u64, u64, vector>, u64, u8, u64) { + ( + task_metadata.task_index, + task_metadata.owner, + task_metadata.payload_tx, + task_metadata.expiry_time, + task_metadata.tx_hash, + task_metadata.max_gas_amount, + task_metadata.gas_price_cap, + task_metadata.automation_fee_cap_for_epoch, + task_metadata.aux_data, + task_metadata.registration_time, + task_metadata.state, + task_metadata.locked_fee_for_next_epoch + ) + } + /// Retrieves specific metadata details of an automation task entry by its task index. /// /// 1. `address` - The owner of the task. @@ -1259,13 +1311,14 @@ module supra_framework::automation_registry { event::emit(TaskCancelledV2 { task_index: automation_task_metadata.task_index, owner, registration_hash: automation_task_metadata.tx_hash }); } - /// Immediately stops automation tasks for the specified `task_indexes`. - /// Only tasks that exist and are owned by the sender can be stopped. - /// If any of the specified tasks are not owned by the sender, the transaction will abort. - /// When a task is stopped, the committed gas for the next epoch is reduced - /// by the max gas amount of the stopped task. Half of the remaining task fee is refunded. - public entry fun stop_tasks( - owner_signer: &signer, + /// Core logic for immediately stopping a set of user automation tasks owned by `owner`. + /// + /// Extracted from the public entry `stop_tasks` so the same refund-and-removal path can be + /// reused by the VM-only `cancel_invalid_task` without requiring a signer from the owner. + /// Callers are responsible for ensuring `owner` is the legitimate task owner before calling; + /// the per-task ownership assert inside this function provides a defence-in-depth check. + fun stop_tasks_internal( + owner: address, task_indexes: vector ) acquires AutomationRegistryV2, ActiveAutomationRegistryConfigV2, AutomationCycleDetails, AutomationRefundBookkeeping { assert!(features::supra_native_automation_enabled(), EDISABLED_AUTOMATION_FEATURE); @@ -1274,7 +1327,6 @@ module supra_framework::automation_registry { // Ensure that task indexes are provided assert!(!vector::is_empty(&task_indexes), EEMPTY_TASK_INDEXES); - let owner = signer::address_of(owner_signer); let automation_registry = &mut borrow_global_mut(@supra_framework).main; let arc = borrow_global(@supra_framework).main_config; let refund_bookkeeping = borrow_global_mut(@supra_framework); @@ -1286,7 +1338,7 @@ module supra_framework::automation_registry { let stopped_task_details = vector[]; let total_refund_fee = 0; - let epoch_locked_fees = automation_registry.epoch_locked_fees; + let total_cycle_locked_fees = automation_registry.epoch_locked_fees; // Calculate refundable fee for this remaining time task in current epoch let current_time = timestamp::now_seconds(); @@ -1323,8 +1375,14 @@ module supra_framework::automation_registry { automation_registry.gas_committed_for_next_epoch = automation_registry.gas_committed_for_next_epoch - task.max_gas_amount; }; - let (epoch_fee_refund, deposit_refund) = if (task.state != PENDING) { - let task_fee = calculate_task_fee( + let (cycle_locked_fee_for_task, cycle_fee_refund, deposit_refund) = if (task.state != PENDING) { + let task_fee_for_full_cycle = + calculate_automation_fee_for_interval( + cycle_info.duration_secs, + task.max_gas_amount, + automation_fee_per_sec, + arc.registry_max_gas_cap); + let task_fee_for_residual_time = calculate_task_fee( &arc, &task, residual_interval, @@ -1332,27 +1390,28 @@ module supra_framework::automation_registry { automation_fee_per_sec ); // Refund full deposit and the half of the remaining run-time fee when task is active or cancelled stage - (task_fee / REFUND_FRACTION, task.locked_fee_for_next_epoch) + (task_fee_for_full_cycle, task_fee_for_residual_time / REFUND_FRACTION, task.locked_fee_for_next_epoch) } else { - (0, (task.locked_fee_for_next_epoch / REFUND_FRACTION)) + (0, 0, (task.locked_fee_for_next_epoch / REFUND_FRACTION)) }; let result = safe_unlock_locked_deposit( refund_bookkeeping, task.locked_fee_for_next_epoch, task.task_index); assert!(result, EDEPOSIT_REFUND); - let (result, remaining_epoch_locked_fees) = safe_unlock_locked_epoch_fee( - epoch_locked_fees, - epoch_fee_refund, + assert!(cycle_locked_fee_for_task >= cycle_fee_refund, EINVALID_CYCLE_REFUND_FEE); + let (result, remaining_cycle_locked_fees) = safe_unlock_locked_epoch_fee( + total_cycle_locked_fees, + cycle_locked_fee_for_task, task.task_index); assert!(result, EEPOCH_FEE_REFUND); - epoch_locked_fees = remaining_epoch_locked_fees; + total_cycle_locked_fees = remaining_cycle_locked_fees; - total_refund_fee = total_refund_fee + (epoch_fee_refund + deposit_refund); + total_refund_fee = total_refund_fee + (cycle_fee_refund + deposit_refund); vector::push_back( &mut stopped_task_details, - TaskStoppedV2 { task_index, deposit_refund, epoch_fee_refund, registration_hash: task.tx_hash } + TaskStoppedV2 { task_index, deposit_refund, epoch_fee_refund: cycle_fee_refund, registration_hash: task.tx_hash } ); } }); @@ -1366,6 +1425,7 @@ module supra_framework::automation_registry { let resource_account_balance = coin::balance(automation_registry.registry_fee_address); assert!(resource_account_balance >= total_refund_fee, EINSUFFICIENT_BALANCE_FOR_REFUND); coin::transfer(&resource_signer, owner, total_refund_fee); + automation_registry.epoch_locked_fees = total_cycle_locked_fees; // Emit task stopped event event::emit(TasksStoppedV2 { @@ -1375,6 +1435,70 @@ module supra_framework::automation_registry { }; } + /// Immediately stops automation tasks for the specified `task_indexes`. + /// Only tasks that exist and are owned by the sender can be stopped. + /// If any of the specified tasks are not owned by the sender, the transaction will abort. + /// When a task is stopped, the committed gas for the next epoch is reduced + /// by the max gas amount of the stopped task. Half of the remaining task fee is refunded. + public entry fun stop_tasks( + owner_signer: &signer, + task_indexes: vector + ) acquires AutomationRegistryV2, ActiveAutomationRegistryConfigV2, AutomationCycleDetails, AutomationRefundBookkeeping { + stop_tasks_internal(signer::address_of(owner_signer), task_indexes) + } + + /// Cancels a single automation task that the runtime has determined to be invalid. + /// May only be called by the VM (enforced via `system_addresses::assert_vm`). + /// + /// This is the runtime-side remedy for tasks registered through + /// `register_without_validation`: because that path skips BCS/entry-function checks, + /// a malformed payload may reach the scheduler and fail repeatedly. The runtime calls + /// this function to remove the task immediately, refund the owner in full (same policy + /// as a voluntary `stop_tasks` call), and emit a diagnostic event so the owner can see + /// why the task was cancelled. + /// + /// Two events are emitted: + /// - `TasksStoppedV2` (fee refund amounts, via `stop_tasks_internal`) + /// - `TaskCancelledByRuntime` (task identity + human-readable diagnostic message) + fun cancel_invalid_task( + vm: signer, + task_index: u64, + diagnostic_message: std::string::String, + ) acquires AutomationRegistryV2, ActiveAutomationRegistryConfigV2, AutomationCycleDetails, AutomationRefundBookkeeping { + // Guard: only the VM may trigger runtime cancellation. + system_addresses::assert_vm(&vm); + + // Read owner address and registration hash before the mutable borrow inside + // stop_tasks_internal. AutomationTaskMetaData has `copy` ability, so + // enumerable_map::get_value returns an owned copy -- no live reference survives + // this block, allowing the subsequent mutable borrow to proceed without conflict. + let owner; + let registration_hash; + { + let automation_registry = borrow_global(@supra_framework); + assert!( + enumerable_map::contains(&automation_registry.main.tasks, task_index), + EAUTOMATION_TASK_NOT_FOUND + ); + let task = enumerable_map::get_value(&automation_registry.main.tasks, task_index); + owner = task.owner; + registration_hash = task.tx_hash; + }; + + // Perform the full refund and removal -- same path as a voluntary stop_tasks call. + // Also emits TasksStoppedV2 with the per-task fee detail. + stop_tasks_internal(owner, vector[task_index]); + + // Emit the runtime-specific event so indexers/explorers can surface the diagnostic + // message to the owner rather than showing only an unexplained stop. + event::emit(TaskCancelledByRuntime { + task_index, + owner, + registration_hash, + diagnostic_message, + }); + } + /// Immediately stops system automation tasks for the specified `task_indexes`. /// Only tasks that exist and are owned by the sender can be stopped. /// If any of the specified tasks are not owned by the sender, the transaction will abort. @@ -1471,6 +1595,7 @@ module supra_framework::automation_registry { assert!(automation_task_metadata.state != CANCELLED, EALREADY_CANCELLED); if (automation_task_metadata.state == PENDING) { enumerable_map::remove_value(&mut automation_registry.main.tasks, task_index); + vector::remove_value(&mut automation_registry.system_tasks_state.task_ids, &task_index); } else { // it is safe not to check the state as above, the cancelled tasks are already rejected. let automation_task_metadata_mut = enumerable_map::get_value_mut( &mut automation_registry.main.tasks, @@ -1841,6 +1966,42 @@ module supra_framework::automation_registry { event::emit(automation_task_metadata); } + /// Registers a new automation task from a smart contract call. + /// + /// Unlike the `AutomationRegistrationPayload` transaction path (which calls the private + /// `register` via the VM and performs full payload validation before execution), this + /// function does NOT validate that `payload_tx` encodes a well-formed entry function with + /// correct parameter types. If the payload is malformed, the task will fail silently at + /// execution time and the caller will have paid registration and deposit fees for nothing. + /// The caller is responsible for providing a valid BCS-encoded `EntryFunction` payload. + /// + /// The required consenus hash of the transaciton registering the task is obtained from native + /// layer. + /// + /// Requires both `supra_native_automation_enabled` and `supra_automation_v2_1_enabled`. + public fun register_without_validation( + owner_signer: &signer, + payload_tx: vector, + expiry_time: u64, + max_gas_amount: u64, + gas_price_cap: u64, + automation_fee_cap_for_epoch: u64, + aux_data: vector> + ) acquires AutomationRegistryV2, AutomationCycleDetails, ActiveAutomationRegistryConfigV2, AutomationRefundBookkeeping { + assert!(features::supra_automation_v2_1_enabled(), EDISABLED_AUTOMATION_V2_1_FEATURE); + let tx_hash = supra_framework::transaction_context::get_transaction_consensus_hash(); + register( + owner_signer, + payload_tx, + expiry_time, + max_gas_amount, + gas_price_cap, + automation_fee_cap_for_epoch, + tx_hash, + aux_data, + ) + } + /// Registers a new system automation task entry. /// Note, system tasks are not charged registration and deposit fee. fun register_system_task( @@ -1922,6 +2083,38 @@ module supra_framework::automation_registry { event::emit(automation_task_metadata); } + /// Registers a new system automation task from a smart contract call. + /// + /// Unlike the `AutomationRegistrationPayload` transaction path (which calls the private + /// `register_system_task` via the VM and performs full payload validation before execution), this + /// function does NOT validate that `payload_tx` encodes a well-formed entry function with + /// correct parameter types. If the payload is malformed, the task will fail silently at + /// execution time and the caller will have paid registration and deposit fees for nothing. + /// The caller is responsible for providing a valid BCS-encoded `EntryFunction` payload. + /// + /// The required consenus hash of the transaciton registering the task is obtained from native + /// layer. + /// + /// Requires both `supra_native_automation_enabled` and `supra_automation_v2_1_enabled`. + public fun register_system_task_without_validation( + owner_signer: &signer, + payload_tx: vector, + expiry_time: u64, + max_gas_amount: u64, + aux_data: vector> + ) acquires AutomationRegistryV2, AutomationCycleDetails, ActiveAutomationRegistryConfigV2 { + assert!(features::supra_automation_v2_1_enabled(), EDISABLED_AUTOMATION_V2_1_FEATURE); + let tx_hash = supra_framework::transaction_context::get_transaction_consensus_hash(); + register_system_task( + owner_signer, + payload_tx, + expiry_time, + max_gas_amount, + tx_hash, + aux_data, + ) + } + /// Called by MoveVm on `AutomationBookkeepingAction::Process` action emitted by native layer ahead of cycle transition fun process_tasks( @@ -2047,6 +2240,7 @@ module supra_framework::automation_registry { vector::for_each(task_indexes, |task_index| { if (enumerable_map::contains(&automation_registry.main.tasks, task_index)) { let task = enumerable_map::remove_value(&mut automation_registry.main.tasks, task_index); + vector::push_back(&mut removed_tasks, task_index); mark_task_processed(transition_state, task_index); // Nothing to refund for GST tasks if (is_of_type(&task, UST)) { @@ -2059,9 +2253,8 @@ module supra_framework::automation_registry { &resource_signer, epoch_locked_fees, current_time, - &mut removed_tasks ) - }; + } } }); @@ -2213,7 +2406,6 @@ module supra_framework::automation_registry { resource_signer: &signer, epoch_locked_fees: u64, current_time: u64, - removed_tasks: &mut vector ) : u64 { assert!(is_of_type(&task, UST), EREGISTERED_TASK_INVALID_TYPE); @@ -2243,7 +2435,6 @@ module supra_framework::automation_registry { task.owner, task.locked_fee_for_next_epoch, task.locked_fee_for_next_epoch); - vector::push_back(removed_tasks, task.task_index); epoch_locked_fees } @@ -3335,6 +3526,14 @@ module supra_framework::automation_registry { automation_registry.main.epoch_locked_fees = locked_fee; } + #[test_only] + public(friend) fun check_locked_fee( + locked_fee: u64, + ) acquires AutomationRegistryV2 { + let automation_registry = borrow_global_mut(@supra_framework); + assert!(automation_registry.main.epoch_locked_fees == locked_fee, locked_fee); + } + #[test_only] public(friend) fun set_total_deposited_automation_fee( fee: u64, diff --git a/aptos-move/framework/supra-framework/sources/block.move b/aptos-move/framework/supra-framework/sources/block.move index 8887739d003..6702ac3d769 100644 --- a/aptos-move/framework/supra-framework/sources/block.move +++ b/aptos-move/framework/supra-framework/sources/block.move @@ -8,6 +8,7 @@ module supra_framework::block { use supra_framework::randomness; use supra_framework::account; + use supra_framework::automation_registry; use supra_framework::event::{Self, EventHandle}; use supra_framework::reconfiguration; use supra_framework::reconfiguration_with_dkg; @@ -15,7 +16,7 @@ module supra_framework::block { use supra_framework::state_storage; use supra_framework::system_addresses; use supra_framework::timestamp; - use supra_framework::automation_registry; + use supra_framework::leader_ban_registry; friend supra_framework::genesis; @@ -29,14 +30,14 @@ module supra_framework::block { epoch_interval: u64, /// Handle where events with the time of new blocks are emitted new_block_events: EventHandle, - update_epoch_interval_events: EventHandle, + update_epoch_interval_events: EventHandle } /// Store new block events as a move resource, internally using a circular buffer. struct CommitHistory has key { max_capacity: u32, next_idx: u32, - table: TableWithLength, + table: TableWithLength } /// Should be in-sync with NewBlockEvent rust struct in new_block.rs @@ -49,13 +50,13 @@ module supra_framework::block { proposer: address, failed_proposer_indices: vector, /// On-chain time during the block at the given height - time_microseconds: u64, + time_microseconds: u64 } /// Event emitted when a proposal is created. struct UpdateEpochIntervalEvent has drop, store { old_epoch_interval: u64, - new_epoch_interval: u64, + new_epoch_interval: u64 } #[event] @@ -69,14 +70,14 @@ module supra_framework::block { proposer: address, failed_proposer_indices: vector, /// On-chain time during the block at the given height - time_microseconds: u64, + time_microseconds: u64 } #[event] /// Event emitted when a proposal is created. struct UpdateEpochInterval has drop, store { old_epoch_interval: u64, - new_epoch_interval: u64, + new_epoch_interval: u64 } /// The number of new block events does not equal the current block height. @@ -89,23 +90,34 @@ module supra_framework::block { const EZERO_MAX_CAPACITY: u64 = 3; /// This can only be called during Genesis. - public(friend) fun initialize(supra_framework: &signer, epoch_interval_microsecs: u64) { + public(friend) fun initialize( + supra_framework: &signer, epoch_interval_microsecs: u64 + ) { system_addresses::assert_supra_framework(supra_framework); - assert!(epoch_interval_microsecs != 0, error::invalid_argument(EZERO_EPOCH_INTERVAL)); + assert!( + epoch_interval_microsecs != 0, + error::invalid_argument(EZERO_EPOCH_INTERVAL) + ); - move_to(supra_framework, CommitHistory { - max_capacity: 2000, - next_idx: 0, - table: table_with_length::new(), - }); + move_to( + supra_framework, + CommitHistory { + max_capacity: 2000, + next_idx: 0, + table: table_with_length::new() + } + ); move_to( supra_framework, BlockResource { height: 0, epoch_interval: epoch_interval_microsecs, - new_block_events: account::new_event_handle(supra_framework), - update_epoch_interval_events: account::new_event_handle(supra_framework), + new_block_events: account::new_event_handle( + supra_framework + ), + update_epoch_interval_events: account::new_event_handle< + UpdateEpochIntervalEvent>(supra_framework) } ); } @@ -113,18 +125,16 @@ module supra_framework::block { /// Initialize the commit history resource if it's not in genesis. public fun initialize_commit_history(fx: &signer, max_capacity: u32) { assert!(max_capacity != 0, error::invalid_argument(EZERO_MAX_CAPACITY)); - move_to(fx, CommitHistory { - max_capacity, - next_idx: 0, - table: table_with_length::new(), - }); + move_to( + fx, + CommitHistory { max_capacity, next_idx: 0, table: table_with_length::new() } + ); } /// Update the epoch interval. /// Can only be called as part of the Supra governance proposal process established by the SupraGovernance module. public fun update_epoch_interval_microsecs( - supra_framework: &signer, - new_epoch_interval: u64, + supra_framework: &signer, new_epoch_interval: u64 ) acquires BlockResource { system_addresses::assert_supra_framework(supra_framework); assert!(new_epoch_interval != 0, error::invalid_argument(EZERO_EPOCH_INTERVAL)); @@ -134,13 +144,11 @@ module supra_framework::block { block_resource.epoch_interval = new_epoch_interval; if (std::features::module_event_migration_enabled()) { - event::emit( - UpdateEpochInterval { old_epoch_interval, new_epoch_interval }, - ); + event::emit(UpdateEpochInterval { old_epoch_interval, new_epoch_interval }); } else { event::emit_event( &mut block_resource.update_epoch_interval_events, - UpdateEpochIntervalEvent { old_epoch_interval, new_epoch_interval }, + UpdateEpochIntervalEvent { old_epoch_interval, new_epoch_interval } ); }; } @@ -151,7 +159,6 @@ module supra_framework::block { borrow_global(@supra_framework).epoch_interval / 1000000 } - fun block_prologue_common( vm: &signer, hash: address, @@ -168,7 +175,7 @@ module supra_framework::block { // Blocks can only be produced by a valid proposer or by the VM itself for Nil blocks (no user txs). assert!( proposer == @vm_reserved || stake::is_current_epoch_validator(proposer), - error::permission_denied(EINVALID_PROPOSER), + error::permission_denied(EINVALID_PROPOSER) ); let proposer_index = option::none(); @@ -187,7 +194,7 @@ module supra_framework::block { previous_block_votes_bitvec, proposer, failed_proposer_indices, - time_microseconds: timestamp, + time_microseconds: timestamp }; emit_new_block_event(vm, &mut block_metadata_ref.new_block_events, new_block_event); @@ -196,6 +203,13 @@ module supra_framework::block { stake::update_performance_statistics(proposer_index, failed_proposer_indices); state_storage::on_new_block(reconfiguration::current_epoch()); + leader_ban_registry::update_ban_registry( + epoch, + round, + proposer_index, + failed_proposer_indices + ); + automation_registry::monitor_cycle_end(); block_metadata_ref.epoch_interval @@ -213,16 +227,17 @@ module supra_framework::block { previous_block_votes_bitvec: vector, timestamp: u64 ) acquires BlockResource, CommitHistory { - let epoch_interval = block_prologue_common( - &vm, - hash, - epoch, - round, - proposer, - failed_proposer_indices, - previous_block_votes_bitvec, - timestamp - ); + let epoch_interval = + block_prologue_common( + &vm, + hash, + epoch, + round, + proposer, + failed_proposer_indices, + previous_block_votes_bitvec, + timestamp + ); randomness::on_new_block(&vm, epoch, round, option::none()); if (timestamp - reconfiguration::last_reconfiguration_time() >= epoch_interval) { reconfiguration::reconfigure(); @@ -239,18 +254,26 @@ module supra_framework::block { failed_proposer_indices: vector, previous_block_votes_bitvec: vector, timestamp: u64, - randomness_seed: Option>, + randomness_seed_vec: vector ) acquires BlockResource, CommitHistory { - let epoch_interval = block_prologue_common( - &vm, - hash, - epoch, - round, - proposer, - failed_proposer_indices, - previous_block_votes_bitvec, - timestamp - ); + let randomness_seed = + if (vector::length(&randomness_seed_vec) == 0) { + option::none() + } else { + option::some(randomness_seed_vec) + }; + + let epoch_interval = + block_prologue_common( + &vm, + hash, + epoch, + round, + proposer, + failed_proposer_indices, + previous_block_votes_bitvec, + timestamp + ); randomness::on_new_block(&vm, epoch, round, randomness_seed); if (timestamp - reconfiguration::last_reconfiguration_time() >= epoch_interval) { @@ -284,16 +307,20 @@ module supra_framework::block { if (table_with_length::contains(&commit_history_ref.table, idx)) { table_with_length::remove(&mut commit_history_ref.table, idx); }; - table_with_length::add(&mut commit_history_ref.table, idx, copy new_block_event); + table_with_length::add( + &mut commit_history_ref.table, idx, copy new_block_event + ); spec { assume idx + 1 <= MAX_U32; }; commit_history_ref.next_idx = (idx + 1) % commit_history_ref.max_capacity; }; - timestamp::update_global_time(vm, new_block_event.proposer, new_block_event.time_microseconds); + timestamp::update_global_time( + vm, new_block_event.proposer, new_block_event.time_microseconds + ); assert!( event::counter(event_handle) == new_block_event.height, - error::invalid_argument(ENUM_NEW_BLOCK_EVENTS_DOES_NOT_MATCH_BLOCK_HEIGHT), + error::invalid_argument(ENUM_NEW_BLOCK_EVENTS_DOES_NOT_MATCH_BLOCK_HEIGHT) ); event::emit_event(event_handle, new_block_event); } @@ -314,7 +341,7 @@ module supra_framework::block { previous_block_votes_bitvec: vector::empty(), proposer: @vm_reserved, failed_proposer_indices: vector::empty(), - time_microseconds: timestamp::now_microseconds(), + time_microseconds: timestamp::now_microseconds() }, ); } @@ -322,8 +349,7 @@ module supra_framework::block { /// Emit a `NewBlockEvent` event. This function will be invoked by write set script directly to generate the /// new block event for WriteSetPayload. public fun emit_writeset_block_event( - vm_signer: &signer, - fake_block_hash: address + vm_signer: &signer, fake_block_hash: address ) acquires BlockResource, CommitHistory { system_addresses::assert_vm(vm_signer); let block_metadata_ref = borrow_global_mut(@supra_framework); @@ -340,13 +366,15 @@ module supra_framework::block { previous_block_votes_bitvec: vector::empty(), proposer: @vm_reserved, failed_proposer_indices: vector::empty(), - time_microseconds: timestamp::now_microseconds(), + time_microseconds: timestamp::now_microseconds() }, ); } #[test_only] - public fun initialize_for_test(account: &signer, epoch_interval_microsecs: u64) { + public fun initialize_for_test( + account: &signer, epoch_interval_microsecs: u64 + ) { initialize(account, epoch_interval_microsecs); } @@ -362,8 +390,7 @@ module supra_framework::block { #[test(supra_framework = @supra_framework, account = @0x123)] #[expected_failure(abort_code = 0x50003, location = supra_framework::system_addresses)] public entry fun test_update_epoch_interval_unauthorized_should_fail( - supra_framework: signer, - account: signer, + supra_framework: signer, account: signer ) acquires BlockResource { account::create_account_for_test(@supra_framework); initialize(&supra_framework, 1); diff --git a/aptos-move/framework/supra-framework/sources/committee_map.move b/aptos-move/framework/supra-framework/sources/committee_map.move index 25c9a3135a3..2a6bf35ea0f 100644 --- a/aptos-move/framework/supra-framework/sources/committee_map.move +++ b/aptos-move/framework/supra-framework/sources/committee_map.move @@ -16,20 +16,35 @@ module supra_framework::committee_map { use aptos_std::simple_map::{Self, SimpleMap}; use supra_framework::account::{Self, new_event_handle}; - /// The number of committee is not equal to the number of committee member - const INVALID_COMMITTEE_NUMBERS: u64 = 4; + /// The number of committees is not equal to the number of committee members + const EINVALID_COMMITTEE_NUMBERS: u64 = 4; /// The node is not found in the committee - const NODE_NOT_FOUND: u64 = 5; + const ENODE_NOT_FOUND: u64 = 5; /// The committee is not found - const INVALID_COMMITTEE_ID: u64 = 6; + const EINVALID_COMMITTEE_ID: u64 = 6; /// The committee type is invalid - const INVALID_COMMITTEE_TYPE: u64 = 7; + const EINVALID_COMMITTEE_TYPE: u64 = 7; /// The number of nodes in the committee is invalid - const INVALID_NODE_NUMBERS: u64 = 8; + const EINVALID_NODE_NUMBERS: u64 = 8; + + /// The number of nodes in the CLAN is invalid + const EINVALID_CLAN_NODE_NUMBERS: u64 = 9; + + /// The number of nodes in the FAMILY is invalid + const EINVALID_FAMILIY_NODE_NUMBERS: u64 = 10; + + /// The number of nodes in the TRIBE is invalid + const EINVALID_TRIBE_NODE_NUMBERS: u64 = 11; + + /// The number of nodes in the committee is ZERO + const EZERO_COMMITTEE_NODE_NUMBER: u64 = 12; + + /// The number of nodes in the CLAN is too small or even + const ECLAN_TOO_SMALL_OR_EVEN_NODES_IN_CLAN: u64 = 13; /// Define the CommitteeType as constants const FAMILY: u8 = 1; @@ -138,7 +153,7 @@ module supra_framework::committee_map { } /// Internal - Assert if the node exists in the committee fun ensure_node_address_exist(committee: &CommitteeInfo, node_address: address) { - assert!(does_node_exist(committee, node_address), error::invalid_argument(NODE_NOT_FOUND)) + assert!(does_node_exist(committee, node_address), error::invalid_argument(ENODE_NOT_FOUND)) } /// Internal - create OwnerCap @@ -183,20 +198,27 @@ module supra_framework::committee_map { // Function to validate the committee type from an integer fun validate_committee_type(committee_type: u8, num_of_nodes: u64): u8 { - assert!(committee_type >= FAMILY && committee_type <= TRIBE, INVALID_COMMITTEE_TYPE); + assert!(committee_type >= FAMILY && committee_type <= TRIBE, EINVALID_COMMITTEE_TYPE); if (committee_type == FAMILY) { // f+1, number of nodes in a family committee should be greater than 1 - assert!(num_of_nodes > 1, INVALID_NODE_NUMBERS); + assert!(num_of_nodes > 1, EINVALID_FAMILIY_NODE_NUMBERS); } else if (committee_type == CLAN) { - // 2f+1, number of nodes in a clan committee should be odd and greater than 3 - assert!(num_of_nodes >= 3 && num_of_nodes % 2 == 1, INVALID_NODE_NUMBERS); + // 2f+1, number of nodes in a clan committee should be odd and greater than or equal to 3 + assert!(num_of_nodes >= 3 && num_of_nodes % 2 == 1, ECLAN_TOO_SMALL_OR_EVEN_NODES_IN_CLAN); } else { - // 3f+1, number of nodes in a tribe committee should be in the format of 3f+1 and greater than 4 - assert!(num_of_nodes >= 4 && (num_of_nodes - 1) % 3 == 0, INVALID_NODE_NUMBERS); + // 3f+1, number of nodes in a tribe committee should be in the format of 3f+1 and greater than or equal to 4 + assert!(num_of_nodes >= 4 && (num_of_nodes - 1) % 3 == 0, EINVALID_TRIBE_NODE_NUMBERS); }; committee_type } + /// Ensures removing exactly one member keeps the committee type invariants valid. + fun assert_removal_allowed(committee: &CommitteeInfo) { + let current_num_of_nodes = simple_map::length(&committee.map); + assert!(current_num_of_nodes > 0, EZERO_COMMITTEE_NODE_NUMBER); + validate_committee_type(committee.committee_type, current_num_of_nodes - 1); + } + #[view] /// Get the committee's node vector and committee type public fun get_committee_info(com_store_addr: address, id: u64): (vector, u8) acquires CommitteeInfoStore { @@ -249,7 +271,7 @@ module supra_framework::committee_map { let committee = simple_map::borrow(&committee_store.committee_map, &id); let (addrs, nodes) = simple_map::to_vec_pair(committee.map); let (flag, index) = vector::index_of(&addrs, &node_address); - assert!(flag, error::invalid_argument(NODE_NOT_FOUND)); + assert!(flag, error::invalid_argument(ENODE_NOT_FOUND)); let node_info = vector::borrow(&nodes, index); NodeData { @@ -332,31 +354,31 @@ module supra_framework::committee_map { rpc_port: vector, committee_type: u8 ) acquires CommitteeInfoStore, SupraCommitteeEventHandler { - // Assert the length of the vector for two are the same + // Assert the length of the vector for two is the same let node_address_len = vector::length(&node_addresses); assert!( node_address_len == vector::length(&ip_public_address), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( node_address_len == vector::length(&node_public_key), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( node_address_len == vector::length(&network_public_key), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( node_address_len == vector::length(&cg_public_key), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( node_address_len == vector::length(&network_port), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( node_address_len == vector::length(&rpc_port), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); // Only the OwnerCap capability can access it let _acquire = &capability::acquire(owner_signer, &OwnerCap {}); @@ -430,31 +452,31 @@ module supra_framework::committee_map { let ids_len = vector::length(&ids); assert!( ids_len == vector::length(&node_addresses_bulk), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( ids_len == vector::length(&ip_public_address_bulk), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( ids_len == vector::length(&node_public_key_bulk), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( ids_len == vector::length(&network_public_key_bulk), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( ids_len == vector::length(&cg_public_key_bulk), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( ids_len == vector::length(&network_port_bulk), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( ids_len == vector::length(&rpc_por_bulkt), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); while (vector::length(&ids) != 0) { let id = vector::pop_back(&mut ids); @@ -494,7 +516,7 @@ module supra_framework::committee_map { let committee_store = borrow_global_mut(com_store_addr); assert!( simple_map::contains_key(&committee_store.committee_map, &id), - error::invalid_argument(INVALID_COMMITTEE_ID) + error::invalid_argument(EINVALID_COMMITTEE_ID) ); let (id, committee_info) = simple_map::remove(&mut committee_store.committee_map, &id); // Also remove the node_to_committee_map @@ -503,7 +525,7 @@ module supra_framework::committee_map { let addr = vector::pop_back(&mut addrs); assert!( simple_map::contains_key(&committee_store.node_to_committee_map, &addr), - error::invalid_argument(NODE_NOT_FOUND) + error::invalid_argument(ENODE_NOT_FOUND) ); simple_map::remove(&mut committee_store.node_to_committee_map, &addr); }; @@ -545,6 +567,27 @@ module supra_framework::committee_map { let _acquire = &capability::acquire(owner_signer, &OwnerCap {}); let committee_store = borrow_global_mut(com_store_addr); + let event_handler = borrow_global_mut(get_committeeInfo_address(owner_signer)); + + // If the node is already associated with another committee, remove the stale entry first. + if (simple_map::contains_key(&committee_store.node_to_committee_map, &node_address)) { + let old_committee_id = *simple_map::borrow(&committee_store.node_to_committee_map, &node_address); + if (old_committee_id != id && simple_map::contains_key(&committee_store.committee_map, &old_committee_id)) { + let old_committee = simple_map::borrow_mut(&mut committee_store.committee_map, &old_committee_id); + if (does_node_exist(old_committee, node_address)) { + assert_removal_allowed(old_committee); + let (_, old_node_info) = simple_map::remove(&mut old_committee.map, &node_address); + emit_event( + &mut event_handler.remove_committee_member, + RemoveCommitteeMemberEvent { + committee_id: old_committee_id, + committee_member: old_node_info + } + ) + } + } + }; + let committee = simple_map::borrow_mut(&mut committee_store.committee_map, &id); let node_info = NodeInfo { ip_public_address: copy ip_public_address, @@ -554,7 +597,6 @@ module supra_framework::committee_map { network_port: network_port, rpc_port: rpc_port, }; - let event_handler = borrow_global_mut(get_committeeInfo_address(owner_signer)); if (!does_node_exist(committee, node_address)) { emit_event( &mut event_handler.add_committee_member, @@ -592,31 +634,31 @@ module supra_framework::committee_map { // Assert the length of the vector for two are the same assert!( vector::length(&ids) == vector::length(&node_addresses), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( vector::length(&ids) == vector::length(&ip_public_address), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( vector::length(&ids) == vector::length(&node_public_key), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( vector::length(&ids) == vector::length(&network_public_key), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( vector::length(&ids) == vector::length(&cg_public_key), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( vector::length(&ids) == vector::length(&network_port), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); assert!( vector::length(&ids) == vector::length(&rpc_port), - error::invalid_argument(INVALID_COMMITTEE_NUMBERS) + error::invalid_argument(EINVALID_COMMITTEE_NUMBERS) ); while (vector::length(&ids) != 0) { let id = vector::pop_back(&mut ids); @@ -655,6 +697,7 @@ module supra_framework::committee_map { let committee_store = borrow_global_mut(com_store_addr); let committee = simple_map::borrow_mut(&mut committee_store.committee_map, &id); ensure_node_address_exist(committee, node_address); + assert_removal_allowed(committee); let (_, node_info) = simple_map::remove(&mut committee.map, &node_address); let event_handler = borrow_global_mut(get_committeeInfo_address(owner_signer)); emit_event( @@ -793,7 +836,7 @@ module supra_framework::committee_map { owner_signer, resource_address, 1, - @0x1, + @0x3, vector[123], vector[123], vector[123], @@ -880,6 +923,131 @@ module supra_framework::committee_map { ); } + #[test(owner_signer = @0xCEFEF)] + #[expected_failure(abort_code = EINVALID_FAMILIY_NODE_NUMBERS, location = Self)] + public entry fun test_remove_committee_member_type_validation( + owner_signer: &signer + ) acquires CommitteeInfoStore, SupraCommitteeEventHandler { + set_up_test(owner_signer); + let resource_address = account::create_resource_address(&@0xCEFEF, SEED_COMMITTEE); + upsert_committee( + owner_signer, + resource_address, + 1, + vector[@0x1, @0x2], + vector[vector[123], vector[124]], + vector[vector[123], vector[124]], + vector[vector[123], vector[124]], + vector[vector[123], vector[124]], + vector[123, 124], + vector[123, 124], + FAMILY + ); + remove_committee_member(owner_signer, resource_address, 1, @0x1); + } + + #[test(owner_signer = @0xCEFEF)] + #[expected_failure(abort_code = EINVALID_FAMILIY_NODE_NUMBERS, location = Self)] + public entry fun test_transfer_member_type_validation( + owner_signer: &signer + ) acquires CommitteeInfoStore, SupraCommitteeEventHandler { + set_up_test(owner_signer); + let resource_address = account::create_resource_address(&@0xCEFEF, SEED_COMMITTEE); + upsert_committee( + owner_signer, + resource_address, + 1, + vector[@0x1, @0x2], + vector[vector[123], vector[124]], + vector[vector[123], vector[124]], + vector[vector[123], vector[124]], + vector[vector[123], vector[124]], + vector[123, 124], + vector[123, 124], + FAMILY + ); + upsert_committee( + owner_signer, + resource_address, + 2, + vector[@0x3, @0x4], + vector[vector[125], vector[126]], + vector[vector[125], vector[126]], + vector[vector[125], vector[126]], + vector[vector[125], vector[126]], + vector[125, 126], + vector[125, 126], + FAMILY + ); + upsert_committee_member( + owner_signer, + resource_address, + 2, + @0x1, + vector[127], + vector[127], + vector[127], + vector[127], + 127, + 127 + ); + } + + #[test(owner_signer = @0xCEFEF)] + public entry fun test_transfer_committee_member_removes_old_committee_entry( + owner_signer: &signer + ) acquires CommitteeInfoStore, SupraCommitteeEventHandler { + set_up_test(owner_signer); + let resource_address = account::create_resource_address(&@0xCEFEF, SEED_COMMITTEE); + upsert_committee( + owner_signer, + resource_address, + 1, + vector[@0x1, @0x2, @0x5], + vector[vector[123], vector[124], vector[125]], + vector[vector[123], vector[124], vector[125]], + vector[vector[123], vector[124], vector[125]], + vector[vector[123], vector[124], vector[125]], + vector[123, 124, 125], + vector[123, 124, 125], + 1 + ); + upsert_committee( + owner_signer, + resource_address, + 2, + vector[@0x3, @0x4], + vector[vector[125], vector[126]], + vector[vector[125], vector[126]], + vector[vector[125], vector[126]], + vector[vector[125], vector[126]], + vector[125, 126], + vector[125, 126], + 1 + ); + upsert_committee_member( + owner_signer, + resource_address, + 2, + @0x1, + vector[127], + vector[127], + vector[127], + vector[127], + 127, + 127 + ); + + let (exists_in_old_committee, _) = find_node_in_committee(resource_address, 1, @0x1); + assert!(!exists_in_old_committee, 1); + assert!(get_committee_id(resource_address, @0x1) == 2, 2); + let (exists_in_new_committee, _) = find_node_in_committee(resource_address, 2, @0x1); + assert!(exists_in_new_committee, 3); + + // Should succeed because node_to_committee_map and committee maps stay in sync. + remove_committee(owner_signer, resource_address, 1); + } + #[test(owner_signer = @0xCEFEF)] public entry fun test_update_dkg_flag( owner_signer: &signer diff --git a/aptos-move/framework/supra-framework/sources/configs/config_buffer.move b/aptos-move/framework/supra-framework/sources/configs/config_buffer.move index fdc0e623236..6147c66c6c7 100644 --- a/aptos-move/framework/supra-framework/sources/configs/config_buffer.move +++ b/aptos-move/framework/supra-framework/sources/configs/config_buffer.move @@ -20,6 +20,7 @@ module supra_framework::config_buffer { use supra_framework::system_addresses; + friend supra_framework::evm_config; friend supra_framework::evm_genesis_config; friend supra_framework::consensus_config; friend supra_framework::execution_config; @@ -33,6 +34,8 @@ module supra_framework::config_buffer { friend supra_framework::randomness_config_seqnum; friend supra_framework::version; friend supra_framework::automation_registry; + friend supra_framework::dkg_config; + friend supra_framework::leader_ban_registry_config; /// Config buffer operations failed with permission denied. const ESTD_SIGNER_NEEDED: u64 = 1; diff --git a/aptos-move/framework/supra-framework/sources/configs/dkg_config.move b/aptos-move/framework/supra-framework/sources/configs/dkg_config.move new file mode 100644 index 00000000000..88865c8c74b --- /dev/null +++ b/aptos-move/framework/supra-framework/sources/configs/dkg_config.move @@ -0,0 +1,411 @@ +// Copyright (c) 2026 Supra. +/// DKG configuration module for configurable DKG parameters. +/// This config can be updated via governance and takes effect at the next epoch. +module supra_framework::dkg_config { + use std::error; + use std::vector; + use supra_framework::config_buffer; + use supra_framework::features; + use supra_framework::system_addresses; + use supra_framework::validator_public_keys::{ + CertificateThresholdType, + bcft_quorum_certificate_type, + bcft_validity_certificate_type, + clan_majority_certificate_type, + quorum_certificate_type, + validity_certificate_type + }; + #[test_only] + use supra_framework::validator_public_keys::unanimous_certificate_type; + + friend supra_framework::genesis; + friend supra_framework::reconfiguration_with_dkg; + + /// Error: Receiver committees vector cannot be empty. + const EEMPTY_RECEIVER_COMMITTEES: u64 = 1; + /// Error: Cannot enable resharing for a threshold type that doesn't exist in current config. + const ERESHARING_FOR_NONEXISTENT_THRESHOLD_TYPE: u64 = 2; + + /// Configuration for a single receiver committee in DKG. + struct ReceiverCommitteeConfig has copy, drop, store { + /// Whether this committee uses resharing from the previous epoch's public key. + is_resharing: bool, + /// The threshold type for this committee (e.g., quorum, clan_majority). + committee_threshold_type: CertificateThresholdType, + /// The threshold type for output keys in DKG for this committee (e.g., validity, quorum). + dkg_threshold_type: CertificateThresholdType + } + + /// Main DKG configuration stored at @supra_framework. + /// Controls DKG parameters that can be updated via governance. + struct DkgConfig has copy, drop, key, store { + /// Threshold type for the dealer committee. (e.g., quorum, clan_majority). + dealer_committee_threshold_type: CertificateThresholdType, + /// Configuration for each receiver committee. + /// Default: [(false, validity), (false, quorum)] + receiver_committees: vector + } + + // ======================== + // Initialization + // ======================== + + // TODO: Add the ability to configure DKG during genesis via the genesis config files. + // This is not necessary for the initial release. + // + /// Initialize DKG config during genesis. + public(friend) fun initialize(framework: &signer) { + system_addresses::assert_supra_framework(framework); + if (!exists(@supra_framework)) { + move_to(framework, default()); + } + } + + // ======================== + // Config Update (Governance) + // ======================== + + /// Set a new DKG config for the next epoch. + /// This can only be called by on-chain governance. + /// Example usage: + /// ``` + /// let new_config = dkg_config::new( + /// quorum_certificate_type(), + /// vector[ + /// dkg_config::new_receiver_committee_config(true, validity_certificate_type()), + /// dkg_config::new_receiver_committee_config(true, quorum_certificate_type()), + /// ] + /// ); + /// dkg_config::set_for_next_epoch(&framework_signer, new_config); + /// supra_governance::reconfigure(&framework_signer); + /// ``` + public fun set_for_next_epoch( + framework: &signer, new_config: DkgConfig + ) acquires DkgConfig { + system_addresses::assert_supra_framework(framework); + + // Validate: receiver_committees cannot be empty + assert!( + vector::length(&new_config.receiver_committees) > 0, + error::invalid_argument(EEMPTY_RECEIVER_COMMITTEES) + ); + + // Validate: if resharing is enabled for a dkg threshold type, it must exist in current config + let current_config = current(); + let i = 0; + let len = vector::length(&new_config.receiver_committees); + while (i < len) { + let new_rc = vector::borrow(&new_config.receiver_committees, i); + if (new_rc.is_resharing) { + // Check if this threshold type exists in current config + assert!( + has_key_threshold_type(¤t_config, new_rc.dkg_threshold_type), + error::invalid_argument(ERESHARING_FOR_NONEXISTENT_THRESHOLD_TYPE) + ); + }; + i = i + 1; + }; + + config_buffer::upsert(new_config); + } + + /// Check if a threshold type exists in the config's receiver committees. + fun has_key_threshold_type( + config: &DkgConfig, threshold_type: CertificateThresholdType + ): bool { + let i = 0; + let len = vector::length(&config.receiver_committees); + while (i < len) { + let rc = vector::borrow(&config.receiver_committees, i); + if (rc.dkg_threshold_type == threshold_type) { + return true + }; + i = i + 1; + }; + false + } + + /// Apply any pending DKG config at epoch boundary. + /// Called from reconfiguration_with_dkg::finish(). + public(friend) fun on_new_epoch(framework: &signer) acquires DkgConfig { + system_addresses::assert_supra_framework(framework); + if (config_buffer::does_exist()) { + let new_config = config_buffer::extract_v2(); + if (exists(@supra_framework)) { + *borrow_global_mut(@supra_framework) = new_config; + } else { + move_to(framework, new_config); + } + } + } + + // ======================== + // Constructors + // ======================== + + /// Create a new DkgConfig. + public fun new( + dealer_committee_threshold_type: CertificateThresholdType, + receiver_committees: vector + ): DkgConfig { + DkgConfig { dealer_committee_threshold_type, receiver_committees } + } + + /// Create a new ReceiverCommitteeConfig. + public fun new_receiver_committee_config( + is_resharing: bool, + committee_threshold_type: CertificateThresholdType, + dkg_threshold_type: CertificateThresholdType + ): ReceiverCommitteeConfig { + ReceiverCommitteeConfig { + is_resharing, + committee_threshold_type, + dkg_threshold_type + } + } + + /// Returns the default DKG configuration. + /// + /// Assumes that the `SUPRA_BCFT_CERTIFICATES` feature flag is enabled. + public fun default(): DkgConfig { + DkgConfig { + dealer_committee_threshold_type: quorum_certificate_type(), + receiver_committees: vector[ + ReceiverCommitteeConfig { + is_resharing: false, + committee_threshold_type: quorum_certificate_type(), + dkg_threshold_type: bcft_quorum_certificate_type() + }, + ReceiverCommitteeConfig { + is_resharing: false, + committee_threshold_type: quorum_certificate_type(), + dkg_threshold_type: bcft_validity_certificate_type() + }, + ReceiverCommitteeConfig { + is_resharing: false, + committee_threshold_type: quorum_certificate_type(), + dkg_threshold_type: clan_majority_certificate_type() + } + ] + } + } + + // ======================== + // Getters + // ======================== + + /// Get the current DKG config. + public fun current(): DkgConfig acquires DkgConfig { + if (exists(@supra_framework)) { + *borrow_global(@supra_framework) + } else { + // This branch should not be executed: + // 1. If the network is started from genesis then the default config should be + // applied during genesis. + // 2. If the DKG feature flag is enabled in an existing network, then governance + // should set a config before enabling the feature flag. + // + // This branch exists as a fallback that ensures that the `BlockMetadata` transaction + // does not fail in case of misconfiguration. + default() + } + } + + /// Get the dealer threshold type from the config. + public fun get_dealer_committee_threshold_type(config: &DkgConfig): + CertificateThresholdType { + config.dealer_committee_threshold_type + } + + /// Get the receiver committee configs from the DkgConfig. + public fun get_receiver_committee_configs(config: &DkgConfig): + vector { + config.receiver_committees + } + + /// Get is_resharing from a ReceiverCommitteeConfig. + public fun get_is_resharing(config: &ReceiverCommitteeConfig): bool { + config.is_resharing + } + + /// Get committee_threshold_type from a ReceiverCommitteeConfig. + public fun get_committee_threshold_type( + config: &ReceiverCommitteeConfig + ): CertificateThresholdType { + config.committee_threshold_type + } + + /// Get dkg_threshold_type from a ReceiverCommitteeConfig. + public fun get_dkg_threshold_type(config: &ReceiverCommitteeConfig): + CertificateThresholdType { + config.dkg_threshold_type + } + + // ======================== + // Tests + // ======================== + + #[test_only] + use supra_framework::account; + + #[test_only] + fun initialize_for_testing(framework: &signer) { + config_buffer::initialize(framework); + initialize(framework); + } + + #[test(framework = @0x1)] + fun test_set_for_next_epoch(framework: signer) acquires DkgConfig { + account::create_account_for_test(@0x1); + initialize_for_testing(&framework); + + // Create new config with resharing enabled + let new_config = + new( + validity_certificate_type(), // Change dealer to validity + vector[ + new_receiver_committee_config( + true, + quorum_certificate_type(), + bcft_quorum_certificate_type() + ), + new_receiver_committee_config( + true, + quorum_certificate_type(), + clan_majority_certificate_type() + ) + ] + ); + + // Stage for next epoch + set_for_next_epoch(&framework, new_config); + + // Config should not change yet + let config = current(); + assert!( + !get_is_resharing( + vector::borrow(&get_receiver_committee_configs(&config), 0) + ), + 1 + ); + + // Apply on new epoch + on_new_epoch(&framework); + + // Now config should be updated + let config = current(); + assert!( + get_dealer_committee_threshold_type(&config) == validity_certificate_type(), + 2 + ); + let receivers = get_receiver_committee_configs(&config); + assert!(get_is_resharing(vector::borrow(&receivers, 0)), 3); + assert!(get_is_resharing(vector::borrow(&receivers, 1)), 4); + } + + #[test(framework = @0x1)] + #[expected_failure(abort_code = 65537, location = Self)] + // EEMPTY_RECEIVER_COMMITTEES + fun test_set_for_next_epoch_empty_receivers_fails(framework: signer) acquires DkgConfig { + account::create_account_for_test(@0x1); + initialize_for_testing(&framework); + + // Try to set config with empty receiver committees - should fail + let bad_config = new( + quorum_certificate_type(), + vector[] // Empty! + ); + set_for_next_epoch(&framework, bad_config); + } + + #[test(framework = @0x1)] + #[expected_failure(abort_code = 65538, location = Self)] + // ERESHARING_FOR_NONEXISTENT_THRESHOLD_TYPE + fun test_set_for_next_epoch_resharing_nonexistent_type_fails( + framework: signer + ) acquires DkgConfig { + account::create_account_for_test(@0x1); + initialize_for_testing(&framework); + + // Default config has validity and quorum threshold types. + // Try to enable resharing for unanimous_certificate_type which doesn't exist. + let bad_config = + new( + quorum_certificate_type(), + vector[ + new_receiver_committee_config( + true, quorum_certificate_type(), unanimous_certificate_type() + ) // This type doesn't exist! + ] + ); + set_for_next_epoch(&framework, bad_config); + } + + #[test(framework = @0x1)] + fun test_set_for_next_epoch_resharing_existing_type_succeeds( + framework: signer + ) acquires DkgConfig { + account::create_account_for_test(@0x1); + initialize_for_testing(&framework); + + // Enable resharing for types that DO exist in current config (validity and quorum) + let good_config = + new( + quorum_certificate_type(), + vector[ + new_receiver_committee_config( + true, + quorum_certificate_type(), + bcft_quorum_certificate_type() + ), + new_receiver_committee_config( + true, + quorum_certificate_type(), + clan_majority_certificate_type() + ) + ] + ); + + // Should succeed + set_for_next_epoch(&framework, good_config); + on_new_epoch(&framework); + + let config = current(); + let receivers = get_receiver_committee_configs(&config); + assert!(get_is_resharing(vector::borrow(&receivers, 0)), 1); + assert!(get_is_resharing(vector::borrow(&receivers, 1)), 2); + } + + #[test(framework = @0x1)] + fun test_add_new_threshold_type_without_resharing_succeeds( + framework: signer + ) acquires DkgConfig { + account::create_account_for_test(@0x1); + initialize_for_testing(&framework); + + // Adding a new threshold type without resharing should succeed + let config_with_new_type = + new( + quorum_certificate_type(), + vector[ + new_receiver_committee_config( + false, quorum_certificate_type(), validity_certificate_type() + ), + new_receiver_committee_config( + false, quorum_certificate_type(), quorum_certificate_type() + ), + new_receiver_committee_config( + false, quorum_certificate_type(), unanimous_certificate_type() + ) // New type, no resharing + ] + ); + + // Should succeed because resharing is false + set_for_next_epoch(&framework, config_with_new_type); + on_new_epoch(&framework); + + let config = current(); + let receivers = get_receiver_committee_configs(&config); + assert!(vector::length(&receivers) == 3, 1); + } +} diff --git a/aptos-move/framework/supra-framework/sources/configs/evm_config.move b/aptos-move/framework/supra-framework/sources/configs/evm_config.move new file mode 100644 index 00000000000..4c8e271eb15 --- /dev/null +++ b/aptos-move/framework/supra-framework/sources/configs/evm_config.move @@ -0,0 +1,482 @@ +module supra_framework::evm_config { + + use std::error; + use std::signer; + use std::string::{Self,String}; + use std::vector; + use aptos_std::simple_map; + use aptos_std::simple_map::SimpleMap; + use aptos_std::bcs; + use supra_framework::config_buffer; + use supra_framework::event; + use supra_framework::system_addresses; + + friend supra_framework::genesis; + friend supra_framework::reconfiguration_with_dkg; + + /// Empty keys/values to update config. + const EEMPTY_DATA: u64 = 1; + + /// Input keys and values should have the same amount of data + const EKEYS_VALUES_MISMATCH: u64 = 2; + + /// Invalid EVM address, valid EVM address must fit in 20 bytes + const EINVALID_EVM_ADDRESS: u64 = 3; + + /// Requested key does not exist in the map + const EKEY_NOT_FOUND: u64 = 4; + + /// Required Key is missing or value type is incorrect for a key + const EMISSING_KEY_OR_INCORRECT_VAL_TYPE: u64 = 5; + + /// Resource already exist at address + const ERESOURCE_ALREADY_EXISTS: u64 = 6; + + /// gas used ratio cannot exceed decimal precision + const EGAS_USED_RATIO_CANNOT_EXCEED_DECIMAL_PRECISION: u64 = 7; + + /// Well-known config key for the EVM gas normalisation denominator. + /// This u64 value is used to scale EVM gas units into Supra gas units. + const CONFIG_KEY_EVM_GAS_NORMALIZATION_DENOM: vector = b"evm_gas_normalization_denom"; + + /// Supra EVM Gas Estimate Margin + const CONFIG_KEY_EVM_GAS_ESTIMATE_MARGIN: vector = b"evm_gas_estimate_margin"; + + /// Supra EVM Gas Used Ratio + const SUPRA_EVM_GAS_USED_RATIO : vector = b"evm_gas_used_ratio"; + + /// DECIMAL_PRECISION + const SUPRA_EVM_GAS_USED_RATIO_DECIMAL_PRECISION: vector = b"evm_gas_used_ratio_decimal_precision"; + + /// Evm and Move address length + const EVM_ADDRESS_BYTE_LENGTH : u64 = 20; + const MOVE_ADDRESS_BYTE_LENGTH: u64 = 32; + + #[event] + struct EvmContractsDetails has key, copy, store, drop { + details: SimpleMap, + } + + /// key-value map of EVM scalar config parameters. + /// Values are plain u128 integers; the Move type system enforces type safety + /// at compile time, eliminating the need for self-describing Any wrappers. + #[event] + struct EvmScalarConfig has key, copy, store, drop { + config: SimpleMap + } + + /// Publishes both the EVM contract address map and the scalar config map. + /// `contract_keys`/`contract_values` must be the same length and every address + /// must be a valid 20-byte EVM address (upper 12 bytes of the 32-byte Move + /// address must be zero). `config_keys`/`config_values` must be the same + /// length and must include all required keys (e.g. evm_gas_normalization_denom). + public(friend) fun initialize( + supra_framework: &signer, + contract_keys: vector, + contract_values: vector
, + config_keys: vector, + config_values: vector + ) { + system_addresses::assert_supra_framework(supra_framework); + assert!(!vector::is_empty(&contract_keys), error::invalid_argument(EEMPTY_DATA)); + assert!(!vector::is_empty(&config_keys), error::invalid_argument(EEMPTY_DATA)); + let supra_framework_addr = signer::address_of(supra_framework); + assert!(!exists(supra_framework_addr),error::invalid_state(ERESOURCE_ALREADY_EXISTS)); + assert!(!exists(supra_framework_addr),error::invalid_state(ERESOURCE_ALREADY_EXISTS)); + assert!( + vector::length(&contract_keys) == vector::length(&contract_values), + error::invalid_argument(EKEYS_VALUES_MISMATCH) + ); + assert!( + vector::length(&config_keys) == vector::length(&config_values), + error::invalid_argument(EKEYS_VALUES_MISMATCH) + ); + + // Check that no contract value is invalid EVM address + let all_valid_evm_address = vector::all(&contract_values, + |v|{ is_valid_evm_address(v) }); + assert!(all_valid_evm_address, error::invalid_argument(EINVALID_EVM_ADDRESS)); + + let contract_details = EvmContractsDetails { + details: simple_map::new_from(contract_keys, contract_values) + }; + move_to(supra_framework, contract_details); + event::emit(contract_details); + + let evm_config = EvmScalarConfig { + config: simple_map::new_from(config_keys, config_values) + }; + validate_scalar_config(&evm_config); + move_to(supra_framework, evm_config); + event::emit(evm_config); + } + + /// This can be called by on-chain governance to update on-chain evm contract + /// details for the next epoch. + /// Example usage: + /// ``` + /// supra_framework::evm_config::upsert_evm_contract_details_for_next_epoch( + /// &framework_signer, vector["contract1_name"], vector[contract1_address]); + /// supra_framework::supra_governance::reconfigure(&framework_signer); + /// ``` + public fun upsert_evm_contract_details_for_next_epoch( + account: &signer, + keys: vector, + values: vector
+ ) acquires EvmContractsDetails { + system_addresses::assert_supra_framework(account); + assert!(!vector::is_empty(&keys), error::invalid_argument(EEMPTY_DATA)); + assert!( + vector::length(&keys) == vector::length(&values), + error::invalid_argument(EKEYS_VALUES_MISMATCH) + ); + let all_valid_evm_address = vector::all(&values, |v| { is_valid_evm_address(v) }); + assert!(all_valid_evm_address, error::invalid_argument(EINVALID_EVM_ADDRESS)); + if (!exists(@supra_framework)) { + std::config_buffer::upsert( + EvmContractsDetails { details: simple_map::new_from(keys, values) } + ); + return + }; + let updated_config = *borrow_global(@supra_framework); + vector::zip(keys, values, |key, value| { + simple_map::upsert(&mut updated_config.details, key, value); + }); + std::config_buffer::upsert(updated_config); + } + + /// This can be called by on-chain governance to update on-chain evm config + /// for the next epoch. Values are plain u128 scalars. + /// Example usage: + /// ``` + /// supra_framework::evm_config::upsert_config_for_next_epoch( + /// &framework_signer, vector["config_key"], vector[new_value]); + /// supra_framework::supra_governance::reconfigure(&framework_signer); + /// ``` + public fun upsert_config_for_next_epoch( + account: &signer, + keys: vector, + values: vector + ) acquires EvmScalarConfig { + system_addresses::assert_supra_framework(account); + assert!(!vector::is_empty(&keys), error::invalid_argument(EEMPTY_DATA)); + assert!( + vector::length(&keys) == vector::length(&values), + error::invalid_argument(EKEYS_VALUES_MISMATCH) + ); + if (!exists(@supra_framework)) { + let evm_config = + EvmScalarConfig { config: simple_map::new_from(keys, values) }; + // Config did not exist earlier, so validate the config for + // presence of required keys and value type match + validate_scalar_config(&evm_config); + std::config_buffer::upsert(evm_config); + return; + }; + // Copy existing config + let updated_config = *borrow_global(@supra_framework); + // We are never removing existing keys so by induction if all required + // keys are present in config during initialization + // they will be there later as well, so no need to validate here + vector::zip(keys, values, |key, value| { + simple_map::upsert(&mut updated_config.config, key, value); + }); + std::config_buffer::upsert(updated_config); + } + + #[view] + /// Returns the contract address stored under `key` in the EvmContractsDetails map. + /// Aborts with EKEY_NOT_FOUND if the resource has not been initialised or the key + /// is not present in the map. + public fun get_contract_value(key: String): address acquires EvmContractsDetails { + assert!(exists(@supra_framework), error::not_found(EKEY_NOT_FOUND)); + let details = borrow_global(@supra_framework); + assert!( + simple_map::contains_key(&details.details, &key), + error::not_found(EKEY_NOT_FOUND) + ); + *simple_map::borrow(&details.details, &key) + } + + #[view] + /// Returns the u128 value stored under `key` in the EvmScalarConfig map. + /// Aborts with EKEY_NOT_FOUND if the resource has not been initialised or the key + /// is not present in the map. + public fun get_scalar_config_value(key: String): u128 acquires EvmScalarConfig { + assert!(exists(@supra_framework), error::not_found(EKEY_NOT_FOUND)); + let config = borrow_global(@supra_framework); + assert!( + simple_map::contains_key(&config.config, &key), + error::not_found(EKEY_NOT_FOUND) + ); + *simple_map::borrow(&config.config, &key) + } + + fun validate_scalar_config(evm_config: &EvmScalarConfig) { + let required_keys = vector[string::utf8(CONFIG_KEY_EVM_GAS_NORMALIZATION_DENOM), + string::utf8(CONFIG_KEY_EVM_GAS_ESTIMATE_MARGIN), + string::utf8(SUPRA_EVM_GAS_USED_RATIO), + string::utf8(SUPRA_EVM_GAS_USED_RATIO_DECIMAL_PRECISION)]; + // With u128 as the value type, the Move type system prevents type mismatches at + // compile time. The only meaningful runtime check is key presence. + vector::for_each_reverse(required_keys, |rk| { + assert!(simple_map::contains_key(&evm_config.config, &rk), + error::invalid_argument(EMISSING_KEY_OR_INCORRECT_VAL_TYPE) + ); + assert!(*simple_map::borrow(&evm_config.config, &rk) > 0u128, error::invalid_argument(EMISSING_KEY_OR_INCORRECT_VAL_TYPE)); + }); + let gas_used_ratio = *simple_map::borrow(&evm_config.config, &string::utf8(SUPRA_EVM_GAS_USED_RATIO)); + let gas_used_ratio_decimal_precision = *simple_map::borrow(&evm_config.config, &string::utf8(SUPRA_EVM_GAS_USED_RATIO_DECIMAL_PRECISION)); + assert!(gas_used_ratio <= gas_used_ratio_decimal_precision, error::invalid_argument(EGAS_USED_RATIO_CANNOT_EXCEED_DECIMAL_PRECISION)); + } + + fun is_valid_evm_address(addr: &address): bool { + // BCS serialises a Move `address` as a raw fixed-size 32-byte array in + // big-endian order (most-significant byte first). An EVM address is only + // 20 bytes wide, so when a 20-byte EVM address is stored in a 32-byte Move + // address the EVM bytes occupy the last 20 positions (indices 12-31) and the + // leading 12 bytes (indices 0-11) must all be zero. + // We iterate only over that prefix and bail immediately on the first non-zero + // byte to avoid unnecessary work. + let evm_addr_bytes = bcs::to_bytes(addr); + + // Sanity check: BCS encoding of an address is always 32 bytes. If somehow + // the length differs, the address cannot be valid. + if (vector::length(&evm_addr_bytes) != MOVE_ADDRESS_BYTE_LENGTH) { + return false + }; + + // Check that all 12 high-order prefix bytes are zero. A non-zero byte here + // means the value cannot fit in 20 bytes and is therefore not a valid EVM address. + let i = 0u64; + let addr_length_diff = MOVE_ADDRESS_BYTE_LENGTH - EVM_ADDRESS_BYTE_LENGTH; + while (i < addr_length_diff) { + if (*vector::borrow(&evm_addr_bytes, i) != 0u8) { + // Non-zero prefix byte found - not a valid 20-byte EVM address. + return false + }; + i = i + 1; + }; + + true + } + + /// Only used in reconfigurations to apply the pending configs in buffer, if any. + /// If supra_framework already holds the resource, overwrite it; otherwise move it in. + public(friend) fun on_new_epoch(framework: &signer) acquires EvmScalarConfig, EvmContractsDetails { + system_addresses::assert_supra_framework(framework); + if (config_buffer::does_exist()) { + let new_config = config_buffer::extract_v2(); + if (!exists(@supra_framework)) { + move_to(framework, new_config); + } else { + let old_config = borrow_global_mut(@supra_framework); + *old_config = new_config; + }; + event::emit(new_config) + }; + if (config_buffer::does_exist()) { + // change to extract_v2 when it is available + let new_config = config_buffer::extract_v2(); + if (!exists(@supra_framework)) { + move_to(framework, new_config); + } else { + let old_config = borrow_global_mut(@supra_framework); + *old_config = new_config; + }; + event::emit(new_config) + }; + } + + // ------------------------------------------------------------------------- + // Tests + // ------------------------------------------------------------------------- + + #[test] + /// Verifies that a small address value (@0x1) is accepted as a valid EVM address. + /// + /// @0x1 is the 256-bit integer 1. BCS serialises a Move address as a raw + /// big-endian 32-byte array, so the most-significant byte is at index 0 and the + /// least-significant byte (0x01) is at index 31. The 12 leading bytes + /// (indices 0-11) are therefore all zero, and the function must return true. + fun test_valid_evm_address_small_value() { + // BCS big-endian layout for @0x1 (32 bytes): + // index 0 : 0x00 + // ... + // index 30 : 0x00 + // index 31 : 0x01 + // Leading bytes 0-11 are all 0x00 -> valid 20-byte EVM address. + assert!(is_valid_evm_address(&@0x1), 0); + } + + #[test] + /// Verifies that a full 32-byte address is rejected as an invalid EVM address. + /// + /// @0x1000...000 (64 hex digits, most-significant nibble = 1) is the 256-bit + /// value 2^252. BCS serialises it as a big-endian byte array, so the + /// most-significant byte (0x10) lands at index 0 - which falls inside the + /// leading window [0, 11] that must be entirely zero for a valid EVM address. + /// The function must therefore return false. + fun test_invalid_evm_address_full_32_bytes() { + // BCS big-endian layout for @0x1000...000 (32 bytes): + // index 0 : 0x10 <- non-zero prefix byte -> invalid EVM address + // index 1 : 0x00 + // ... + // index 31 : 0x00 + assert!( + is_valid_evm_address( + &@0x0000000000000000000000001000000000000000000000000000000000000001 + ), + 0 + ); + + assert!( + !is_valid_evm_address( + &@0x1000000000000000000000000000000000000000000000000000000000000000 + ), + 0 + ); + assert!( + !is_valid_evm_address( + &@0x0000000000000000000000011000000000000000000000000000000000000001 + ), + 0 + ); + + } + + #[test(supra_framework = @supra_framework)] + /// Happy-path test: both get_contract_value and get_scalar_config_value return the + /// values that were seeded into their respective resources. + fun test_get_contract_and_config_value_success(supra_framework: signer) acquires EvmContractsDetails, EvmScalarConfig { + // Seed EvmContractsDetails with a single entry. + let contract_key = std::string::utf8(b"usdc_contract"); + let contract_addr = @0xA550C18; + move_to(&supra_framework, EvmContractsDetails { + details: simple_map::new_from(vector[contract_key], vector[contract_addr]) + }); + + // Seed EvmScalarConfig with a single entry using a plain u128 value. + let config_key = std::string::utf8(b"evm_gas_normalization_denom"); + let config_value = 42u128; + move_to(&supra_framework, EvmScalarConfig { + config: simple_map::new_from(vector[config_key], vector[config_value]) + }); + + // Both lookups must return the exact values that were inserted above. + assert!(get_contract_value(std::string::utf8(b"usdc_contract")) == contract_addr, 0); + assert!( + get_scalar_config_value(std::string::utf8(b"evm_gas_normalization_denom")) == 42u128, + 0 + ); + } + + #[test(supra_framework = @supra_framework)] + /// Failure test: get_contract_value aborts when the requested key is absent. + /// + /// The expected abort code is error::not_found(EKEY_NOT_FOUND) + /// = (NOT_FOUND_CATEGORY=6 << 16) | EKEY_NOT_FOUND=4 = 0x60004. + #[expected_failure(abort_code = 0x60004, location = supra_framework::evm_config)] + fun test_get_contract_value_key_not_found(supra_framework: signer) acquires EvmContractsDetails { + move_to(&supra_framework, EvmContractsDetails { + details: simple_map::new_from( + vector[std::string::utf8(b"existing_key")], + vector[@0x1] + ) + }); + get_contract_value(std::string::utf8(b"nonexistent_key")); + } + + #[test(supra_framework = @supra_framework)] + /// Failure test: get_scalar_config_value aborts when the requested key is absent. + /// + /// The expected abort code is error::not_found(EKEY_NOT_FOUND) + /// = (NOT_FOUND_CATEGORY=6 << 16) | EKEY_NOT_FOUND=4 = 0x60004. + #[expected_failure(abort_code = 0x60004, location = supra_framework::evm_config)] + fun test_get_config_value_key_not_found(supra_framework: signer) acquires EvmScalarConfig { + move_to(&supra_framework, EvmScalarConfig { + config: simple_map::new_from( + vector[std::string::utf8(b"existing_key")], + vector[1u128] + ) + }); + get_scalar_config_value(std::string::utf8(b"nonexistent_key")); + } + + #[test] + /// Success test: validate_scalar_config must not abort when all required keys are present. + /// + /// evm_gas_normalization_denom is the sole required key. A config seeded with that + /// key and a plain u128 value must pass validation. + fun test_validate_config_success() { + let config_key = std::string::utf8(CONFIG_KEY_EVM_GAS_NORMALIZATION_DENOM); + let estimate_margin_key = std::string::utf8(CONFIG_KEY_EVM_GAS_ESTIMATE_MARGIN); + let gas_used_ratio_key = std::string::utf8(SUPRA_EVM_GAS_USED_RATIO); + let decimal_precision_key = std::string::utf8(SUPRA_EVM_GAS_USED_RATIO_DECIMAL_PRECISION); + + + let evm_config = EvmScalarConfig { + config: simple_map::new_from(vector[config_key, estimate_margin_key, gas_used_ratio_key, decimal_precision_key], vector[100u128, 1000u128, 500u128, 1000u128]) + }; + // Must complete without aborting. + validate_scalar_config(&evm_config); + } + + #[test] + /// Failure test: validate_scalar_config aborts when a required key is absent. + /// + /// An empty config is missing evm_gas_normalization_denom, so validation must abort. + /// The expected abort code is error::invalid_argument(EMISSING_KEY_OR_INCORRECT_VAL_TYPE) + /// = (INVALID_ARGUMENT_CATEGORY=1 << 16) | EMISSING_KEY_OR_INCORRECT_VAL_TYPE=5 = 0x10005. + #[expected_failure(abort_code = 0x10005, location = supra_framework::evm_config)] + fun test_validate_config_missing_required_key() { + // An empty config is missing the sole required key -> must abort. + let evm_config = EvmScalarConfig { config: simple_map::new() }; + validate_scalar_config(&evm_config); + } + + #[test(supra_framework = @supra_framework)] + /// Failure test: upsert_evm_contract_details_for_next_epoch aborts when any + /// address in the values vector is not a valid EVM address. + /// + /// The call passes one valid address (@0x1, which fits in 20 bytes with all + /// leading bytes zero) alongside one invalid address whose most-significant + /// byte is non-zero (@0x1000...000). The presence of the invalid address + /// must trigger EINVALID_EVM_ADDRESS regardless of position in the vector. + /// The expected abort code is error::invalid_argument(EINVALID_EVM_ADDRESS) + /// = (INVALID_ARGUMENT_CATEGORY=1 << 16) | EINVALID_EVM_ADDRESS=3 = 0x10003. + #[expected_failure(abort_code = 0x10003, location = supra_framework::evm_config)] + fun test_upsert_evm_contract_details_mixed_invalid_address(supra_framework: signer) acquires EvmContractsDetails { + let keys = vector[ + std::string::utf8(b"valid_contract"), + std::string::utf8(b"invalid_contract") + ]; + let values = vector[ + @0x1, // valid: fits in 20 bytes + @0x1000000000000000000000000000000000000000000000000000000000000000 // invalid: high byte non-zero + ]; + upsert_evm_contract_details_for_next_epoch(&supra_framework, keys, values); + } + + #[test(supra_framework = @supra_framework)] + /// Failure test: validate_scalar_config aborts when gas used ratio exceeds decimal precision. + /// + /// The config includes all required keys, but the value for SUPRA_EVM_GAS_USED_RATIO (500) exceeds the value for SUPRA_EVM_GAS_USED_RATIO_DECIMAL_PRECISION (1000), which is not logically valid. Validation must abort with + /// error::invalid_argument(EGAS_USED_RATIO_CANNOT_EXCEED_DECIMAL_PRECISION) + /// = (INVALID_ARGUMENT_CATEGORY=1 << 16) | EGAS_USED_RATIO_CANNOT_EXCEED_DECIMAL_PRECISION=7 = 0x10007. + #[expected_failure(abort_code = 0x10007, location = supra_framework::evm_config)] + fun test_validate_config_gas_used_ratio_exceeds_decimal_precision() { + let config_key = std::string::utf8(CONFIG_KEY_EVM_GAS_NORMALIZATION_DENOM); + let estimate_margin_key = std::string::utf8(CONFIG_KEY_EVM_GAS_ESTIMATE_MARGIN); + let gas_used_ratio_key = std::string::utf8(SUPRA_EVM_GAS_USED_RATIO); + let decimal_precision_key = std::string::utf8(SUPRA_EVM_GAS_USED_RATIO_DECIMAL_PRECISION); + let evm_config = EvmScalarConfig { + config: simple_map::new_from( + vector[config_key, estimate_margin_key, gas_used_ratio_key, decimal_precision_key], + vector[100u128, 1000u128, 1500u128, 1000u128] // gas used ratio exceeds decimal precision -> must abort + ) + }; + validate_scalar_config(&evm_config); + + } +} diff --git a/aptos-move/framework/supra-framework/sources/configs/leader_ban_registry_config.move b/aptos-move/framework/supra-framework/sources/configs/leader_ban_registry_config.move new file mode 100644 index 00000000000..e5adc17770e --- /dev/null +++ b/aptos-move/framework/supra-framework/sources/configs/leader_ban_registry_config.move @@ -0,0 +1,266 @@ +/// Provides the config related to leader ban registry +module supra_framework::leader_ban_registry_config { + use std::error; + use std::option; + use std::option::Option; + use std::vector; + use supra_std::decode_bcs; + use supra_framework::config_buffer; + use supra_framework::system_addresses; + #[test_only] + use std::signer; + + friend supra_framework::genesis; + friend supra_framework::reconfiguration_with_dkg; + + #[test_only] + friend supra_framework::test_leader_ban_registry_config; + #[test_only] + friend supra_framework::test_leader_ban_registry; + + /// The provided on chain config bytes are empty or invalid + const EINVALID_CONFIG: u64 = 1; + /// The provided on chain config version should be equal or greater than existing + const EINVALID_VERSION: u64 = 2; + /// Decoding from version bytes failed + const EINVALID_VERSION_BYTES: u64 = 3; + /// The BanRegistryParameters already initialised + const EALREADY_INITIALISED: u64 = 4; + + /// Holds ban registry parameters bytes and it's version + struct BanRegistryParameters has drop, key, store { + /// Denotes config bcs bytes + config: vector, + /// Denotes config version + version: u8 + } + + /// Ban registry parameters v0 + struct BanRegistryParametersV0 has drop, key, store { + /// Denotes initial election count denied + initial_elections_denied: u8, + /// Denotes max election count denied + max_elections_denied: u32, + /// Denotes the minimum number of validators that must remain eligible for proposal. This + /// helps to preserve liveness in the presence of extended periods of network asynchrony. + minimum_unbanned_proposers: u8, + /// Denotes the number of elections a validator must serve on probation after ban expires. + /// The ban duration compounds each time a validator is banned whilst on probation, and + /// resets to the base duration if the validator passes probation. + probation_elections: u8 + } + + /// Publishes the BanRegistryParameters config. + public(friend) fun initialize( + supra_framework: &signer, config: vector + ) { + system_addresses::assert_supra_framework(supra_framework); + assert!(vector::length(&config) != 0, error::invalid_argument(EINVALID_CONFIG)); + assert!( + !exists(@supra_framework), + error::already_exists(EALREADY_INITIALISED) + ); + let v0 = deserialise_v0_params(config); + if (option::is_none(&v0)) { + abort error::invalid_argument(EINVALID_VERSION_BYTES) + }; + // we always init with version 0 + move_to(supra_framework, BanRegistryParameters { config, version: 0 }); + let v0_params = option::extract(&mut v0); + move_to(supra_framework, v0_params); + } + + /// This can be called by on-chain governance to update on-chain configs for the next epoch. + /// Example usage: + /// ``` + /// supra_framework::leader_ban_registry_config::set_for_next_epoch(&framework_signer, some_config_bytes, version); + /// supra_framework::supra_governance::reconfigure(&framework_signer); + /// ``` + public fun set_for_next_epoch( + account: &signer, config: vector, version: u8 + ) acquires BanRegistryParameters { + system_addresses::assert_supra_framework(account); + assert!(vector::length(&config) != 0, error::invalid_argument(EINVALID_CONFIG)); + if (exists(@supra_framework)) { + let ban_registry_params = + borrow_global(@supra_framework); + assert!( + version >= ban_registry_params.version, + error::invalid_argument(EINVALID_VERSION) + ); + }; + std::config_buffer::upsert( + BanRegistryParameters { config, version } + ); + } + + /// Only used in reconfigurations to apply the pending `BanRegistryParameters`, if there is any. + public(friend) fun on_new_epoch( + framework: &signer + ) acquires BanRegistryParameters, BanRegistryParametersV0 { + system_addresses::assert_supra_framework(framework); + if (config_buffer::does_exist()) { + let new_config = config_buffer::extract_v2(); + if (exists(@supra_framework)) { + *borrow_global_mut(@supra_framework) = new_config; + } else { + move_to(framework, new_config); + }; + let params = borrow_global(@supra_framework); + if (params.version == 0) { + let v0 = deserialise_v0_params(params.config); + // This is to prevent abort on new epoch if deserialise failed. + if (option::is_some(&v0)) { + let ban_registry_params = option::extract(&mut v0); + if (exists(@supra_framework)) { + *borrow_global_mut(@supra_framework) = ban_registry_params; + } else { + move_to(framework, ban_registry_params); + } + } + } + // later version can be assigned here + } + } + + #[view] + public fun get_ban_registry_params(): (vector, u8) acquires BanRegistryParameters { + if (exists(@supra_framework)) { + let ban_registry_config = + borrow_global(@supra_framework); + return (ban_registry_config.config, ban_registry_config.version) + }; + (vector::empty(), 0) + } + + #[view] + public fun get_ban_registry_params_v0(): (u8, u32, u8, u8) acquires BanRegistryParameters, BanRegistryParametersV0 { + if (exists(@supra_framework)) { + let ban_registry_config = + borrow_global(@supra_framework); + if (ban_registry_config.version == 0) { + let ban_registry_params = + borrow_global(@supra_framework); + return ( + ban_registry_params.initial_elections_denied, + ban_registry_params.max_elections_denied, + ban_registry_params.minimum_unbanned_proposers, + ban_registry_params.probation_elections + ) + } + }; + (0, 0, 0, 0) + } + + /// Provide initial election denied value + public fun get_initial_elections_denied(): u8 acquires BanRegistryParameters, BanRegistryParametersV0 { + if (exists(@supra_framework)) { + let ban_registry_config = + borrow_global(@supra_framework); + if (ban_registry_config.version == 0) { + let ban_registry_params = + borrow_global(@supra_framework); + return ban_registry_params.initial_elections_denied + } + }; + 0 + } + + /// Provide max election denied value + public fun get_max_elections_denied(): u32 acquires BanRegistryParameters, BanRegistryParametersV0 { + if (exists(@supra_framework)) { + let ban_registry_config = + borrow_global(@supra_framework); + if (ban_registry_config.version == 0) { + let ban_registry_params = + borrow_global(@supra_framework); + return ban_registry_params.max_elections_denied + } + }; + 0 + } + + /// Provide minimum unbanned proposers value + public fun get_minimum_unbanned_proposers(): u8 acquires BanRegistryParameters, BanRegistryParametersV0 { + if (exists(@supra_framework)) { + let ban_registry_config = + borrow_global(@supra_framework); + if (ban_registry_config.version == 0) { + let ban_registry_params = + borrow_global(@supra_framework); + return ban_registry_params.minimum_unbanned_proposers + } + }; + 0 + } + + /// Provide probation elections value + public fun get_probation_elections(): u8 acquires BanRegistryParameters, BanRegistryParametersV0 { + if (exists(@supra_framework)) { + let ban_registry_config = + borrow_global(@supra_framework); + if (ban_registry_config.version == 0) { + let ban_registry_params = + borrow_global(@supra_framework); + return ban_registry_params.probation_elections + } + }; + 0 + } + + /// Decoding bytes to `BanRegistryParametersV0` using bcs + fun deserialise_v0_params(bytes: vector): Option { + let bcs_bytes = decode_bcs::new(bytes); + let initial_elections_denied: u8 = decode_bcs::peel_u8(&mut bcs_bytes); + let max_elections_denied: u32 = decode_bcs::peel_u32(&mut bcs_bytes); + let minimum_unbanned_proposers: u8 = decode_bcs::peel_u8(&mut bcs_bytes); + let probation_elections: u8 = decode_bcs::peel_u8(&mut bcs_bytes); + // making sure no bytes left to decode means correct parameter version + if (vector::length(&decode_bcs::into_remainder_bytes(bcs_bytes)) == 0) { + return option::some( + BanRegistryParametersV0 { + initial_elections_denied, + max_elections_denied, + minimum_unbanned_proposers, + probation_elections + } + ) + }; + option::none() + } + + #[test_only] + public fun get_test_ban_registry_params_v0(): BanRegistryParametersV0 { + BanRegistryParametersV0 { + initial_elections_denied: 1, + max_elections_denied: 5, + minimum_unbanned_proposers: 2, + probation_elections: 1 + } + } + + #[test_only] + public fun get_custom_ban_registry_params_v0( + initial_elections_denied: u8, + max_elections_denied: u32, + minimum_unbanned_proposers: u8, + probation_elections: u8 + ): BanRegistryParametersV0 { + BanRegistryParametersV0 { + initial_elections_denied, + max_elections_denied, + minimum_unbanned_proposers, + probation_elections + } + } + + #[test_only] + public fun check_ban_registry_params_exist(sender: &signer): bool { + exists(signer::address_of(sender)) + } + + #[test_only] + public fun check_ban_registry_params_v0_exist(sender: &signer): bool { + exists(signer::address_of(sender)) + } +} diff --git a/aptos-move/framework/supra-framework/sources/configs/randomness_config.move b/aptos-move/framework/supra-framework/sources/configs/randomness_config.move index 1d93515372a..d41e58c00f2 100644 --- a/aptos-move/framework/supra-framework/sources/configs/randomness_config.move +++ b/aptos-move/framework/supra-framework/sources/configs/randomness_config.move @@ -17,7 +17,7 @@ module supra_framework::randomness_config { /// Currently the variant type is one of the following. /// - `ConfigOff` /// - `ConfigV1` - variant: Any, + variant: Any } /// A randomness config variant indicating the feature is disabled. @@ -28,7 +28,7 @@ module supra_framework::randomness_config { /// Any validator subset should not be able to reconstruct randomness if `subset_power / total_power <= secrecy_threshold`, secrecy_threshold: FixedPoint64, /// Any validator subset should be able to reconstruct randomness if `subset_power / total_power > reconstruction_threshold`. - reconstruction_threshold: FixedPoint64, + reconstruction_threshold: FixedPoint64 } /// A randomness config variant indicating the feature is enabled with fast path. @@ -38,7 +38,7 @@ module supra_framework::randomness_config { /// Any validator subset should be able to reconstruct randomness if `subset_power / total_power > reconstruction_threshold`. reconstruction_threshold: FixedPoint64, /// Any validator subset should not be able to reconstruct randomness via the fast path if `subset_power / total_power <= fast_path_secrecy_threshold`, - fast_path_secrecy_threshold: FixedPoint64, + fast_path_secrecy_threshold: FixedPoint64 } /// Initialize the configuration. Used in genesis or governance. @@ -50,7 +50,9 @@ module supra_framework::randomness_config { } /// This can be called by on-chain governance to update on-chain consensus configs for the next epoch. - public fun set_for_next_epoch(framework: &signer, new_config: RandomnessConfig) { + public fun set_for_next_epoch( + framework: &signer, new_config: RandomnessConfig + ) { system_addresses::assert_supra_framework(framework); config_buffer::upsert(new_config); } @@ -71,31 +73,30 @@ module supra_framework::randomness_config { /// Check whether on-chain randomness main logic (e.g., `DKGManager`, `RandManager`, `BlockMetadataExt`) is enabled. /// /// NOTE: this returning true does not mean randomness will run. - /// The feature works if and only if `consensus_config::validator_txn_enabled() && randomness_config::enabled()`. public fun enabled(): bool acquires RandomnessConfig { if (exists(@supra_framework)) { let config = borrow_global(@supra_framework); - let variant_type_name = *string::bytes(copyable_any::type_name(&config.variant)); + let variant_type_name = + *string::bytes(copyable_any::type_name(&config.variant)); variant_type_name != b"0x1::randomness_config::ConfigOff" - } else { - false - } + } else { false } } /// Create a `ConfigOff` variant. public fun new_off(): RandomnessConfig { RandomnessConfig { - variant: copyable_any::pack( ConfigOff {} ) + variant: copyable_any::pack(ConfigOff {}) } } /// Create a `ConfigV1` variant. - public fun new_v1(secrecy_threshold: FixedPoint64, reconstruction_threshold: FixedPoint64): RandomnessConfig { + public fun new_v1( + secrecy_threshold: FixedPoint64, reconstruction_threshold: FixedPoint64 + ): RandomnessConfig { RandomnessConfig { - variant: copyable_any::pack( ConfigV1 { - secrecy_threshold, - reconstruction_threshold - } ) + variant: copyable_any::pack( + ConfigV1 { secrecy_threshold, reconstruction_threshold } + ) } } @@ -103,14 +104,16 @@ module supra_framework::randomness_config { public fun new_v2( secrecy_threshold: FixedPoint64, reconstruction_threshold: FixedPoint64, - fast_path_secrecy_threshold: FixedPoint64, + fast_path_secrecy_threshold: FixedPoint64 ): RandomnessConfig { RandomnessConfig { - variant: copyable_any::pack( ConfigV2 { - secrecy_threshold, - reconstruction_threshold, - fast_path_secrecy_threshold, - } ) + variant: copyable_any::pack( + ConfigV2 { + secrecy_threshold, + reconstruction_threshold, + fast_path_secrecy_threshold + } + ) } } @@ -137,10 +140,11 @@ module supra_framework::randomness_config { initialize_for_testing(&framework); // Enabling. - let config = new_v1( - fixed_point64::create_from_rational(1, 2), - fixed_point64::create_from_rational(2, 3) - ); + let config = + new_v1( + fixed_point64::create_from_rational(1, 2), + fixed_point64::create_from_rational(2, 3) + ); set_for_next_epoch(&framework, config); on_new_epoch(&framework); assert!(enabled(), 1); diff --git a/aptos-move/framework/supra-framework/sources/dkg.move b/aptos-move/framework/supra-framework/sources/dkg.move index 9721c2722bd..6cb058cbccc 100644 --- a/aptos-move/framework/supra-framework/sources/dkg.move +++ b/aptos-move/framework/supra-framework/sources/dkg.move @@ -1,3 +1,6 @@ +/// Deprecated. Replaced by supra_dkg. Retained because the module has already been deployed to +/// production. +/// /// DKG on-chain states and helper functions. module supra_framework::dkg { use std::error; @@ -19,13 +22,13 @@ module supra_framework::dkg { dealer_epoch: u64, randomness_config: RandomnessConfig, dealer_validator_set: vector, - target_validator_set: vector, + target_validator_set: vector } #[event] struct DKGStartEvent has drop, store { session_metadata: DKGSessionMetadata, - start_time_us: u64, + start_time_us: u64 } /// The input and output of a DKG session. @@ -33,13 +36,13 @@ module supra_framework::dkg { struct DKGSessionState has copy, store, drop { metadata: DKGSessionMetadata, start_time_us: u64, - transcript: vector, + transcript: vector } /// The completed and in-progress DKG sessions. struct DKGState has key { last_completed: Option, - in_progress: Option, + in_progress: Option } /// Called in genesis to initialize on-chain states. @@ -50,7 +53,7 @@ module supra_framework::dkg { supra_framework, DKGState { last_completed: std::option::none(), - in_progress: std::option::none(), + in_progress: std::option::none() } ); } @@ -62,26 +65,25 @@ module supra_framework::dkg { dealer_epoch: u64, randomness_config: RandomnessConfig, dealer_validator_set: vector, - target_validator_set: vector, + target_validator_set: vector ) acquires DKGState { let dkg_state = borrow_global_mut(@supra_framework); let new_session_metadata = DKGSessionMetadata { dealer_epoch, randomness_config, dealer_validator_set, - target_validator_set, + target_validator_set }; let start_time_us = timestamp::now_microseconds(); - dkg_state.in_progress = std::option::some(DKGSessionState { - metadata: new_session_metadata, - start_time_us, - transcript: vector[], - }); + dkg_state.in_progress = std::option::some( + DKGSessionState { + metadata: new_session_metadata, + start_time_us, + transcript: vector[] + } + ); - emit(DKGStartEvent { - start_time_us, - session_metadata: new_session_metadata, - }); + emit(DKGStartEvent { start_time_us, session_metadata: new_session_metadata }); } /// Put a transcript into the currently incomplete DKG session, then mark it completed. @@ -89,7 +91,10 @@ module supra_framework::dkg { /// Abort if DKG is not in progress. public(friend) fun finish(transcript: vector) acquires DKGState { let dkg_state = borrow_global_mut(@supra_framework); - assert!(option::is_some(&dkg_state.in_progress), error::invalid_state(EDKG_NOT_IN_PROGRESS)); + assert!( + option::is_some(&dkg_state.in_progress), + error::invalid_state(EDKG_NOT_IN_PROGRESS) + ); let session = option::extract(&mut dkg_state.in_progress); session.transcript = transcript; dkg_state.last_completed = option::some(session); diff --git a/aptos-move/framework/supra-framework/sources/dkg.spec.move b/aptos-move/framework/supra-framework/sources/dkg.spec.move index dcedf6065fd..d5a5ea90589 100644 --- a/aptos-move/framework/supra-framework/sources/dkg.spec.move +++ b/aptos-move/framework/supra-framework/sources/dkg.spec.move @@ -2,7 +2,8 @@ spec supra_framework::dkg { spec module { use supra_framework::chain_status; - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); } spec initialize(supra_framework: &signer) { @@ -15,7 +16,7 @@ spec supra_framework::dkg { dealer_epoch: u64, randomness_config: RandomnessConfig, dealer_validator_set: vector, - target_validator_set: vector, + target_validator_set: vector ) { aborts_if !exists(@supra_framework); aborts_if !exists(@supra_framework); @@ -31,9 +32,7 @@ spec supra_framework::dkg { spec fun has_incomplete_session(): bool { if (exists(@supra_framework)) { option::spec_is_some(global(@supra_framework).in_progress) - } else { - false - } + } else { false } } spec try_clear_incomplete_session(fx: &signer) { diff --git a/aptos-move/framework/supra-framework/sources/dkg_committee.move b/aptos-move/framework/supra-framework/sources/dkg_committee.move new file mode 100644 index 00000000000..6aa47ee2eca --- /dev/null +++ b/aptos-move/framework/supra-framework/sources/dkg_committee.move @@ -0,0 +1,123 @@ +// Copyright (c) 2024 Supra. +module std::dkg_committee { + + use std::bcs; + use std::vector; + use supra_framework::validator_consensus_info; + use supra_framework::validator_consensus_info::ValidatorConsensusInfo; + use supra_framework::validator_public_keys::CertificateThresholdType; + + const EINVALID_DKG_COMMITTEE_SIZE: u64 = 1; + + struct DkgNodeConfig has copy, drop, store { + addr: address, + identity: vector, + dkg_pubkey: vector + } + + struct DkgCommittee has copy, drop, store { + committee: vector, + // The threshold type for the committee's Byzantine fault tolerance. + threshold_type: CertificateThresholdType + } + + struct ReceiverCommittee has copy, drop, store { + is_resharing: bool, + // The threshold type for the output key of the DKG process. + dkg_threshold_type: CertificateThresholdType, + committee: DkgCommittee + } + + public fun new_dkg_node_config( + addr: address, identity: vector, dkg_pubkey: vector + ): DkgNodeConfig { + DkgNodeConfig { addr, identity, dkg_pubkey } + } + + public fun get_addr(dkg_node: &DkgNodeConfig): address { + dkg_node.addr + } + + public fun get_dkg_pubkey(dkg_node: &DkgNodeConfig): vector { + dkg_node.dkg_pubkey + } + + public fun len(committee: &DkgCommittee): u64 { + vector::length(&committee.committee) + } + + public fun get_committee(dkg_committee: &DkgCommittee): vector { + dkg_committee.committee + } + + public fun new_dkg_committee( + committee: vector, threshold_type: CertificateThresholdType + ): DkgCommittee { + assert!(vector::length(&committee) > 0, EINVALID_DKG_COMMITTEE_SIZE); + DkgCommittee { committee, threshold_type } + } + + public fun new_dkg_committee_from_validator_consensus_info( + validator_committee: vector, + threshold_type: CertificateThresholdType + ): DkgCommittee { + assert!(vector::length(&validator_committee) > 0, EINVALID_DKG_COMMITTEE_SIZE); + + // The order of the committee members is important for DKG. + // The order should correspond to the order of the validator committee. + // The output of the DKG has keys in the same order as the committee. + let dkg_committee = vector[]; + vector::for_each( + validator_committee, + |x| { + let validator_keys_bytes = validator_consensus_info::get_pk_bytes(&x); + let addr = validator_consensus_info::get_addr(&x); + vector::push_back( + &mut dkg_committee, + DkgNodeConfig { + addr, + identity: bcs::to_bytes(&addr), + dkg_pubkey: validator_keys_bytes + } + ); + } + ); + + DkgCommittee { committee: dkg_committee, threshold_type } + } + + public fun new_receiver_committee( + is_resharing: bool, + dkg_threshold_type: CertificateThresholdType, + committee: DkgCommittee + ): ReceiverCommittee { + ReceiverCommittee { is_resharing, dkg_threshold_type, committee } + } + + /// Input for DKG key output - contains threshold type and keys for one committee + struct DkgCommitteeOutput has copy, drop { + /// The threshold type (0=validity, 1=quorum, 2=unanimous, etc.) + threshold_type: u8, + /// Public key shares for each validator (indexed by validator position) + keys: vector> + } + + /// Create a new DkgCommitteeOutput + public fun new_dkg_committee_output( + threshold_type: u8, keys: vector> + ): DkgCommitteeOutput { + DkgCommitteeOutput { threshold_type, keys } + } + + /// Get threshold type from DkgCommitteeOutput + public fun get_dkg_committee_output_threshold_type( + output: &DkgCommitteeOutput + ): u8 { + output.threshold_type + } + + /// Get keys from DkgCommitteeOutput + public fun get_dkg_committee_output_keys(output: &DkgCommitteeOutput): vector> { + output.keys + } +} diff --git a/aptos-move/framework/supra-framework/sources/fungible_asset.move b/aptos-move/framework/supra-framework/sources/fungible_asset.move index 470fa89d8c5..9d73d21ab04 100644 --- a/aptos-move/framework/supra-framework/sources/fungible_asset.move +++ b/aptos-move/framework/supra-framework/sources/fungible_asset.move @@ -1119,31 +1119,35 @@ module supra_framework::fungible_asset { ) acquires Metadata { let metadata_address = object::object_address(&metadata_ref.metadata); let mutable_metadata = borrow_global_mut(metadata_address); - - if (option::is_some(&name)){ - let name = option::extract(&mut name); - assert!(string::length(&name) <= MAX_NAME_LENGTH, error::out_of_range(ENAME_TOO_LONG)); - mutable_metadata.name = name; + + if (option::is_some(&name)) { + let new_name = option::destroy_some(name); + assert!(string::length(&new_name) <= MAX_NAME_LENGTH, error::out_of_range(ENAME_TOO_LONG)); + mutable_metadata.name = new_name; }; - if (option::is_some(&symbol)){ - let symbol = option::extract(&mut symbol); - assert!(string::length(&symbol) <= MAX_SYMBOL_LENGTH, error::out_of_range(ESYMBOL_TOO_LONG)); - mutable_metadata.symbol = symbol; + + if (option::is_some(&symbol)) { + let new_symbol = option::destroy_some(symbol); + assert!(string::length(&new_symbol) <= MAX_SYMBOL_LENGTH, error::out_of_range(ESYMBOL_TOO_LONG)); + mutable_metadata.symbol = new_symbol; }; - if (option::is_some(&decimals)){ - let decimals = option::extract(&mut decimals); - assert!(decimals <= MAX_DECIMALS, error::out_of_range(EDECIMALS_TOO_LARGE)); - mutable_metadata.decimals = decimals; + + if (option::is_some(&decimals)) { + let new_decimals = option::destroy_some(decimals); + assert!(new_decimals <= MAX_DECIMALS, error::out_of_range(EDECIMALS_TOO_LARGE)); + mutable_metadata.decimals = new_decimals; }; - if (option::is_some(&icon_uri)){ - let icon_uri = option::extract(&mut icon_uri); - assert!(string::length(&icon_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG)); - mutable_metadata.icon_uri = icon_uri; + + if (option::is_some(&icon_uri)) { + let new_icon_uri = option::destroy_some(icon_uri); + assert!(string::length(&new_icon_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG)); + mutable_metadata.icon_uri = new_icon_uri; }; - if (option::is_some(&project_uri)){ - let project_uri = option::extract(&mut project_uri); - assert!(string::length(&project_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG)); - mutable_metadata.project_uri = project_uri; + + if (option::is_some(&project_uri)) { + let new_project_uri = option::destroy_some(project_uri); + assert!(string::length(&new_project_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG)); + mutable_metadata.project_uri = new_project_uri; }; } diff --git a/aptos-move/framework/supra-framework/sources/genesis.move b/aptos-move/framework/supra-framework/sources/genesis.move index 923b2446025..c7e60581d91 100644 --- a/aptos-move/framework/supra-framework/sources/genesis.move +++ b/aptos-move/framework/supra-framework/sources/genesis.move @@ -5,6 +5,7 @@ module supra_framework::genesis { use std::string::String; use std::vector; use aptos_std::simple_map; + use supra_framework::evm_config; use supra_framework::account; use supra_framework::aggregator_factory; @@ -14,11 +15,14 @@ module supra_framework::genesis { use supra_framework::chain_status; use supra_framework::coin; use supra_framework::consensus_config; + use supra_framework::dkg_config; use supra_framework::execution_config; use supra_framework::supra_config; use supra_framework::evm_genesis_config; use supra_framework::create_signer::create_signer; use supra_framework::gas_schedule; + use supra_framework::leader_ban_registry; + use supra_framework::leader_ban_registry_config; use supra_framework::multisig_account; use supra_framework::pbo_delegation_pool; use supra_framework::reconfiguration; @@ -39,7 +43,7 @@ module supra_framework::genesis { use supra_framework::nonce_validation; #[test_only] - use aptos_std::ed25519; + use supra_std::validator_public_keys; #[verify_only] use std::features; @@ -56,10 +60,9 @@ module supra_framework::genesis { const EDENOMINATOR_IS_ZERO: u64 = 8; const EACCOUNT_NOT_REGISTERED_FOR_COIN: u64 = 9; - struct AccountMap has drop { account_address: address, - balance: u64, + balance: u64 } struct VestingPoolsMap has copy, drop { @@ -76,7 +79,7 @@ module supra_framework::genesis { // Cliff duration in seconds cliff_period_in_seconds: u64, // Each vesting period duration in seconds - period_duration_in_seconds: u64, + period_duration_in_seconds: u64 } struct EmployeeAccountMap has copy, drop { @@ -84,7 +87,7 @@ module supra_framework::genesis { validator: ValidatorConfigurationWithCommission, vesting_schedule_numerator: vector, vesting_schedule_denominator: u64, - beneficiary_resetter: address, + beneficiary_resetter: address } struct ValidatorConfiguration has copy, drop { @@ -94,13 +97,13 @@ module supra_framework::genesis { stake_amount: u64, consensus_pubkey: vector, network_addresses: vector, - full_node_network_addresses: vector, + full_node_network_addresses: vector } struct ValidatorConfigurationWithCommission has copy, drop { validator_config: ValidatorConfiguration, commission_percentage: u64, - join_during_genesis: bool, + join_during_genesis: bool } struct DelegatorConfiguration has copy, drop { @@ -108,7 +111,7 @@ module supra_framework::genesis { delegation_pool_creation_seed: vector, validator: ValidatorConfigurationWithCommission, delegator_addresses: vector
, - delegator_stakes: vector, + delegator_stakes: vector } struct PboDelegatorConfiguration has copy, drop { @@ -122,7 +125,7 @@ module supra_framework::genesis { //Time from `timestamp::now_seconds()` to start unlocking schedule unlock_startup_time_from_now: u64, //Time for each unlock - unlock_period_duration: u64, + unlock_period_duration: u64 } /// Genesis step 1: Initialize supra framework account and core modules on chain. @@ -141,14 +144,13 @@ module supra_framework::genesis { rewards_rate: u64, rewards_rate_denominator: u64, voting_power_increase_limit: u64, - genesis_timestamp_in_microseconds: u64, + genesis_timestamp_in_microseconds: u64 ) { // Initialize the supra framework account. This is the account where system resources and modules will be // deployed to. This will be entirely managed by on-chain governance and no entities have the key or privileges // to use this account. - let (supra_framework_account, supra_framework_signer_cap) = account::create_framework_reserved_account( - @supra_framework - ); + let (supra_framework_account, supra_framework_signer_cap) = + account::create_framework_reserved_account(@supra_framework); // Initialize account configs on supra framework account. account::initialize(&supra_framework_account); @@ -157,21 +159,27 @@ module supra_framework::genesis { b"script_prologue", b"module_prologue", b"multi_agent_script_prologue", - b"epilogue", + b"epilogue" ); // Give the decentralized on-chain governance control over the core framework account. - supra_governance::store_signer_cap(&supra_framework_account, @supra_framework, supra_framework_signer_cap); + supra_governance::store_signer_cap( + &supra_framework_account, @supra_framework, supra_framework_signer_cap + ); // put reserved framework reserved accounts under supra governance let framework_reserved_addresses = vector
[@0x2, @0x3, @0x4, @0x5, @0x6, @0x7, @0x8, @0x9, @0xa]; while (!vector::is_empty(&framework_reserved_addresses)) { let address = vector::pop_back
(&mut framework_reserved_addresses); - let (_, framework_signer_cap) = account::create_framework_reserved_account(address); - supra_governance::store_signer_cap(&supra_framework_account, address, framework_signer_cap); + let (_, framework_signer_cap) = + account::create_framework_reserved_account(address); + supra_governance::store_signer_cap( + &supra_framework_account, address, framework_signer_cap + ); }; consensus_config::initialize(&supra_framework_account, consensus_config); + dkg_config::initialize(&supra_framework_account); execution_config::set(&supra_framework_account, execution_config); supra_config::initialize(&supra_framework_account, supra_config); version::initialize(&supra_framework_account, initial_version); @@ -186,7 +194,7 @@ module supra_framework::genesis { allow_validator_set_change, rewards_rate, rewards_rate_denominator, - voting_power_increase_limit, + voting_power_increase_limit ); storage_gas::initialize(&supra_framework_account); gas_schedule::initialize(&supra_framework_account, gas_schedule); @@ -199,7 +207,6 @@ module supra_framework::genesis { reconfiguration::initialize(&supra_framework_account); block::initialize(&supra_framework_account, epoch_interval_microsecs); state_storage::initialize(&supra_framework_account); - nonce_validation::initialize(&supra_framework_account) } /// Genesis step 2: Initialize Supra coin. @@ -227,9 +234,8 @@ module supra_framework::genesis { _congestion_threshold_percentage: u8, _congestion_base_fee_in_quants_per_sec: u64, _congestion_exponent: u8, - _task_capacity: u16, - ) { - } + _task_capacity: u16 + ) {} /// Genesis step 3: Initialize Supra Native Automation. public fun initialize_supra_native_automation_v2( @@ -245,7 +251,7 @@ module supra_framework::genesis { cycle_duration: u64, sys_task_duration_cap_in_secs: u64, sys_registry_max_gas_cap: u64, - sys_task_capacity: u16, + sys_task_capacity: u16 ) { automation_registry::initialize( supra_framework, @@ -260,15 +266,13 @@ module supra_framework::genesis { task_capacity, sys_task_duration_cap_in_secs, sys_registry_max_gas_cap, - sys_task_capacity, + sys_task_capacity ) } - /// Only called for testnets and e2e tests. fun initialize_core_resources_and_supra_coin( - supra_framework: &signer, - core_resources_auth_key: vector, + supra_framework: &signer, core_resources_auth_key: vector ) { let (burn_cap, mint_cap) = supra_coin::initialize(supra_framework); coin::create_coin_conversion_map(supra_framework); @@ -282,35 +286,63 @@ module supra_framework::genesis { let core_resources = account::create_account(@core_resources); supra_account::register_supra(&core_resources); // register Supra store - account::rotate_authentication_key_internal(&core_resources, core_resources_auth_key); - supra_coin::configure_accounts_for_test(supra_framework, &core_resources, mint_cap); + account::rotate_authentication_key_internal( + &core_resources, core_resources_auth_key + ); + supra_coin::configure_accounts_for_test( + supra_framework, &core_resources, mint_cap + ); } /// Initialize the EVM genesis config. fun initialize_evm_genesis_config( - supra_framework: &signer, - evm_genesis_config: vector, + supra_framework: &signer, evm_genesis_config: vector ) { evm_genesis_config::initialize(supra_framework, evm_genesis_config); } + /// Initialize the EVM config. + fun initialize_evm_config( + supra_framework: &signer, + contract_names: vector, + contract_addresses: vector
, + config_keys: vector, + config_values: vector + ) { + evm_config::initialize(supra_framework, contract_names, contract_addresses, config_keys, config_values); + } + + /// Initialize the leader ban config + fun initialize_leader_ban_registry_config( + supra_framework: &signer, leader_ban_registry_config: vector + ) { + leader_ban_registry_config::initialize( + supra_framework, leader_ban_registry_config + ); + leader_ban_registry::initialize_leader_ban_registry(supra_framework); + } - fun create_accounts(supra_framework: &signer, accounts: vector) { + fun create_accounts( + supra_framework: &signer, accounts: vector + ) { let unique_accounts = vector::empty(); - vector::for_each_ref(&accounts, |account_map| { - let account_map: &AccountMap = account_map; - assert!( - !vector::contains(&unique_accounts, &account_map.account_address), - error::already_exists(EDUPLICATE_ACCOUNT), - ); - vector::push_back(&mut unique_accounts, account_map.account_address); + vector::for_each_ref( + &accounts, + |account_map| { + let account_map: &AccountMap = account_map; + assert!( + !vector::contains(&unique_accounts, &account_map.account_address), + error::already_exists(EDUPLICATE_ACCOUNT) + ); + vector::push_back(&mut unique_accounts, account_map.account_address); - create_account( - supra_framework, - account_map.account_address, - account_map.balance, - ); - }); + create_account( + supra_framework, + account_map.account_address, + account_map.balance + ); + } + ); } /// This creates an funds an account if it doesn't exist. @@ -330,7 +362,6 @@ module supra_framework::genesis { account } - fun create_multiple_multisig_accounts_with_schema( supra_framework: &signer, owner: address, @@ -345,8 +376,17 @@ module supra_framework::genesis { let counter = 0; let result = vector::empty(); while (counter < num_of_accounts) { - let account_addr = create_multisig_account_with_balance(supra_framework, owner, additional_owners, - num_signatures_required, metadata_keys, metadata_values, timeout_duration, balance); + let account_addr = + create_multisig_account_with_balance( + supra_framework, + owner, + additional_owners, + num_signatures_required, + metadata_keys, + metadata_values, + timeout_duration, + balance + ); vector::push_back(&mut result, account_addr); counter = counter + 1; }; @@ -361,11 +401,17 @@ module supra_framework::genesis { metadata_keys: vector, metadata_values: vector>, timeout_duration: u64, - balance: u64, + balance: u64 ): address { - assert!(account::exists_at(owner), error::invalid_argument(EACCOUNT_DOES_NOT_EXIST)); assert!( - vector::all(&additional_owners, |ao_addr|{ account::exists_at(*ao_addr) }), + account::exists_at(owner), + error::invalid_argument(EACCOUNT_DOES_NOT_EXIST) + ); + assert!( + vector::all( + &additional_owners, + |ao_addr| { account::exists_at(*ao_addr) } + ), error::invalid_argument(EACCOUNT_DOES_NOT_EXIST) ); let addr = multisig_account::get_next_multisig_account_address(owner); @@ -386,90 +432,104 @@ module supra_framework::genesis { fun create_employee_validators( employee_vesting_start: u64, employee_vesting_period_duration: u64, - employees: vector, + employees: vector ) { let unique_accounts = vector::empty(); - vector::for_each_ref(&employees, |employee_group| { - let j = 0; - let employee_group: &EmployeeAccountMap = employee_group; - let num_employees_in_group = vector::length(&employee_group.accounts); - - let buy_ins = simple_map::create(); - - while (j < num_employees_in_group) { - let account = vector::borrow(&employee_group.accounts, j); + vector::for_each_ref( + &employees, + |employee_group| { + let j = 0; + let employee_group: &EmployeeAccountMap = employee_group; + let num_employees_in_group = vector::length(&employee_group.accounts); + + let buy_ins = simple_map::create(); + + while (j < num_employees_in_group) { + let account = vector::borrow(&employee_group.accounts, j); + assert!( + !vector::contains(&unique_accounts, account), + error::already_exists(EDUPLICATE_ACCOUNT) + ); + vector::push_back(&mut unique_accounts, *account); + + let employee = create_signer(*account); + let total = coin::balance(*account); + let coins = coin::withdraw(&employee, total); + simple_map::add(&mut buy_ins, *account, coins); + + j = j + 1; + }; + + let j = 0; + let num_vesting_events = vector::length( + &employee_group.vesting_schedule_numerator + ); + let schedule = vector::empty(); + + while (j < num_vesting_events) { + let numerator = vector::borrow( + &employee_group.vesting_schedule_numerator, j + ); + let event = + fixed_point32::create_from_rational( + *numerator, + employee_group.vesting_schedule_denominator + ); + vector::push_back(&mut schedule, event); + + j = j + 1; + }; + + let vesting_schedule = + vesting::create_vesting_schedule( + schedule, + employee_vesting_start, + employee_vesting_period_duration + ); + + let admin = employee_group.validator.validator_config.owner_address; + let admin_signer = &create_signer(admin); + let contract_address = + vesting::create_vesting_contract( + admin_signer, + &employee_group.accounts, + buy_ins, + vesting_schedule, + admin, + employee_group.validator.validator_config.operator_address, + employee_group.validator.validator_config.voter_address, + employee_group.validator.commission_percentage, + x"" + ); + let pool_address = vesting::stake_pool_address(contract_address); + + if (employee_group.beneficiary_resetter != @0x0) { + vesting::set_beneficiary_resetter( + admin_signer, + contract_address, + employee_group.beneficiary_resetter + ); + }; + + let validator = &employee_group.validator.validator_config; assert!( - !vector::contains(&unique_accounts, account), - error::already_exists(EDUPLICATE_ACCOUNT), + account::exists_at(validator.owner_address), + error::not_found(EACCOUNT_DOES_NOT_EXIST) ); - vector::push_back(&mut unique_accounts, *account); - - let employee = create_signer(*account); - let total = coin::balance(*account); - let coins = coin::withdraw(&employee, total); - simple_map::add(&mut buy_ins, *account, coins); - - j = j + 1; - }; - - let j = 0; - let num_vesting_events = vector::length(&employee_group.vesting_schedule_numerator); - let schedule = vector::empty(); - - while (j < num_vesting_events) { - let numerator = vector::borrow(&employee_group.vesting_schedule_numerator, j); - let event = fixed_point32::create_from_rational( - *numerator, - employee_group.vesting_schedule_denominator + assert!( + account::exists_at(validator.operator_address), + error::not_found(EACCOUNT_DOES_NOT_EXIST) ); - vector::push_back(&mut schedule, event); - - j = j + 1; - }; - - let vesting_schedule = vesting::create_vesting_schedule( - schedule, - employee_vesting_start, - employee_vesting_period_duration, - ); - - let admin = employee_group.validator.validator_config.owner_address; - let admin_signer = &create_signer(admin); - let contract_address = vesting::create_vesting_contract( - admin_signer, - &employee_group.accounts, - buy_ins, - vesting_schedule, - admin, - employee_group.validator.validator_config.operator_address, - employee_group.validator.validator_config.voter_address, - employee_group.validator.commission_percentage, - x"", - ); - let pool_address = vesting::stake_pool_address(contract_address); - - if (employee_group.beneficiary_resetter != @0x0) { - vesting::set_beneficiary_resetter(admin_signer, contract_address, employee_group.beneficiary_resetter); - }; - - let validator = &employee_group.validator.validator_config; - assert!( - account::exists_at(validator.owner_address), - error::not_found(EACCOUNT_DOES_NOT_EXIST), - ); - assert!( - account::exists_at(validator.operator_address), - error::not_found(EACCOUNT_DOES_NOT_EXIST), - ); - assert!( - account::exists_at(validator.voter_address), - error::not_found(EACCOUNT_DOES_NOT_EXIST), - ); - if (employee_group.validator.join_during_genesis) { - initialize_validator(pool_address, validator); - }; - }); + assert!( + account::exists_at(validator.voter_address), + error::not_found(EACCOUNT_DOES_NOT_EXIST) + ); + if (employee_group.validator.join_during_genesis) { + initialize_validator(pool_address, validator); + }; + } + ); } /// DEPRECATED @@ -477,12 +537,17 @@ module supra_framework::genesis { fun create_initialize_validators_with_commission( supra_framework: &signer, use_staking_contract: bool, - validators: vector, + validators: vector ) { - vector::for_each_ref(&validators, |validator| { - let validator: &ValidatorConfigurationWithCommission = validator; - create_initialize_validator(supra_framework, validator, use_staking_contract); - }); + vector::for_each_ref( + &validators, + |validator| { + let validator: &ValidatorConfigurationWithCommission = validator; + create_initialize_validator( + supra_framework, validator, use_staking_contract + ); + } + ); } /// DEPRECATED @@ -497,51 +562,66 @@ module supra_framework::genesis { /// /// Network address fields are a vector per account, where each entry is a vector of addresses /// encoded in a single BCS byte array. - fun create_initialize_validators(supra_framework: &signer, validators: vector) { + fun create_initialize_validators( + supra_framework: &signer, validators: vector + ) { let validators_with_commission = vector::empty(); - vector::for_each_reverse(validators, |validator| { - let validator_with_commission = ValidatorConfigurationWithCommission { - validator_config: validator, - commission_percentage: 0, - join_during_genesis: true, - }; - vector::push_back(&mut validators_with_commission, validator_with_commission); - }); + vector::for_each_reverse( + validators, + |validator| { + let validator_with_commission = ValidatorConfigurationWithCommission { + validator_config: validator, + commission_percentage: 0, + join_during_genesis: true + }; + vector::push_back( + &mut validators_with_commission, validator_with_commission + ); + } + ); - create_initialize_validators_with_commission(supra_framework, false, validators_with_commission); + create_initialize_validators_with_commission( + supra_framework, false, validators_with_commission + ); } fun create_initialize_validator( supra_framework: &signer, commission_config: &ValidatorConfigurationWithCommission, - use_staking_contract: bool, + use_staking_contract: bool ) { let validator = &commission_config.validator_config; - let owner = &create_account(supra_framework, validator.owner_address, validator.stake_amount); + let owner = + &create_account( + supra_framework, validator.owner_address, validator.stake_amount + ); create_account(supra_framework, validator.operator_address, 0); create_account(supra_framework, validator.voter_address, 0); // Initialize the stake pool and join the validator set. - let pool_address = if (use_staking_contract) { - staking_contract::create_staking_contract( - owner, - validator.operator_address, - validator.voter_address, - validator.stake_amount, - commission_config.commission_percentage, - x"", - ); - staking_contract::stake_pool_address(validator.owner_address, validator.operator_address) - } else { - stake::initialize_stake_owner( - owner, - validator.stake_amount, - validator.operator_address, - validator.voter_address, - ); - validator.owner_address - }; + let pool_address = + if (use_staking_contract) { + staking_contract::create_staking_contract( + owner, + validator.operator_address, + validator.voter_address, + validator.stake_amount, + commission_config.commission_percentage, + x"" + ); + staking_contract::stake_pool_address( + validator.owner_address, validator.operator_address + ) + } else { + stake::initialize_stake_owner( + owner, + validator.stake_amount, + validator.operator_address, + validator.voter_address + ); + validator.owner_address + }; if (commission_config.join_during_genesis) { initialize_validator(pool_address, validator); @@ -550,50 +630,69 @@ module supra_framework::genesis { fun create_pbo_delegation_pools( pbo_delegator_configs: vector, - delegation_percentage: u64, + delegation_percentage: u64 ) { let unique_accounts: vector
= vector::empty(); assert!( delegation_percentage != 0 && delegation_percentage <= 100, error::invalid_argument(EPERCENTAGE_INVALID) ); - vector::for_each_ref(&pbo_delegator_configs, |pbo_delegator_config| { - let pbo_delegator_config: &PboDelegatorConfiguration = pbo_delegator_config; - assert!(!vector::contains(&unique_accounts, &pbo_delegator_config.delegator_config.owner_address), - error::invalid_argument(EDUPLICATE_ACCOUNT)); - vector::push_back(&mut unique_accounts, pbo_delegator_config.delegator_config.owner_address); - create_pbo_delegation_pool(pbo_delegator_config, delegation_percentage); - }); + vector::for_each_ref( + &pbo_delegator_configs, + |pbo_delegator_config| { + let pbo_delegator_config: &PboDelegatorConfiguration = + pbo_delegator_config; + assert!( + !vector::contains( + &unique_accounts, + &pbo_delegator_config.delegator_config.owner_address + ), + error::invalid_argument(EDUPLICATE_ACCOUNT) + ); + vector::push_back( + &mut unique_accounts, + pbo_delegator_config.delegator_config.owner_address + ); + create_pbo_delegation_pool(pbo_delegator_config, delegation_percentage); + } + ); } fun create_pbo_delegation_pool( - pbo_delegator_config: &PboDelegatorConfiguration, - delegation_percentage: u64, + pbo_delegator_config: &PboDelegatorConfiguration, delegation_percentage: u64 ) { assert!( delegation_percentage != 0 && delegation_percentage <= 100, error::invalid_argument(EPERCENTAGE_INVALID) ); let unique_accounts: vector
= vector::empty(); - vector::for_each_ref(&pbo_delegator_config.delegator_config.delegator_addresses, |delegator_address| { - let delegator_address: &address = delegator_address; - assert!( - !vector::contains(&unique_accounts, delegator_address), - error::already_exists(EDUPLICATE_ACCOUNT), - ); - vector::push_back(&mut unique_accounts, *delegator_address); - }); - let owner_signer = create_signer(pbo_delegator_config.delegator_config.owner_address); + vector::for_each_ref( + &pbo_delegator_config.delegator_config.delegator_addresses, + |delegator_address| { + let delegator_address: &address = delegator_address; + assert!( + !vector::contains(&unique_accounts, delegator_address), + error::already_exists(EDUPLICATE_ACCOUNT) + ); + vector::push_back(&mut unique_accounts, *delegator_address); + } + ); + let owner_signer = + create_signer(pbo_delegator_config.delegator_config.owner_address); // get a list of delegator addresses, withdraw the coin from them and merge them into a single account - let delegator_addresses = pbo_delegator_config.delegator_config.delegator_addresses; + let delegator_addresses = + pbo_delegator_config.delegator_config.delegator_addresses; let coinInitialization = coin::zero(); - vector::for_each(delegator_addresses, |delegator_address| { - let delegator = &create_signer(delegator_address); - let total = coin::balance(delegator_address); - let withdraw_amount = total * delegation_percentage / 100; - let coins = coin::withdraw(delegator, withdraw_amount); - coin::merge(&mut coinInitialization, coins); - }); + vector::for_each( + delegator_addresses, + |delegator_address| { + let delegator = &create_signer(delegator_address); + let total = coin::balance(delegator_address); + let withdraw_amount = total * delegation_percentage / 100; + let coins = coin::withdraw(delegator, withdraw_amount); + coin::merge(&mut coinInitialization, coins); + } + ); pbo_delegation_pool::initialize_delegation_pool( &owner_signer, option::some(pbo_delegator_config.multisig_admin), @@ -604,13 +703,15 @@ module supra_framework::genesis { coinInitialization, pbo_delegator_config.unlock_schedule_numerators, pbo_delegator_config.unlock_schedule_denominator, - pbo_delegator_config.unlock_startup_time_from_now + timestamp::now_seconds(), - pbo_delegator_config.unlock_period_duration, + pbo_delegator_config.unlock_startup_time_from_now + + timestamp::now_seconds(), + pbo_delegator_config.unlock_period_duration ); - let pool_address = pbo_delegation_pool::get_owned_pool_address( - pbo_delegator_config.delegator_config.owner_address - ); + let pool_address = + pbo_delegation_pool::get_owned_pool_address( + pbo_delegator_config.delegator_config.owner_address + ); let validator = pbo_delegator_config.delegator_config.validator.validator_config; pbo_delegation_pool::set_operator(&owner_signer, validator.operator_address); pbo_delegation_pool::set_delegated_voter(&owner_signer, validator.voter_address); @@ -621,101 +722,133 @@ module supra_framework::genesis { }; } - fun assert_validator_addresses_check(validator: &ValidatorConfiguration) { + fun assert_validator_addresses_check( + validator: &ValidatorConfiguration + ) { assert!( account::exists_at(validator.owner_address), - error::not_found(EACCOUNT_DOES_NOT_EXIST), + error::not_found(EACCOUNT_DOES_NOT_EXIST) ); assert!( account::exists_at(validator.operator_address), - error::not_found(EACCOUNT_DOES_NOT_EXIST), + error::not_found(EACCOUNT_DOES_NOT_EXIST) ); assert!( account::exists_at(validator.voter_address), - error::not_found(EACCOUNT_DOES_NOT_EXIST), + error::not_found(EACCOUNT_DOES_NOT_EXIST) ); } - fun create_vesting_without_staking_pools( vesting_pool_map: vector ) { let unique_accounts: vector
= vector::empty(); - vector::for_each_ref(&vesting_pool_map, |pool_config|{ - let pool_config: &VestingPoolsMap = pool_config; - let schedule = vector::empty(); - let schedule_length = vector::length(&pool_config.vesting_numerators); - assert!(schedule_length != 0, error::invalid_argument(EVESTING_SCHEDULE_IS_ZERO)); - assert!(pool_config.vesting_denominator != 0, error::invalid_argument(EDENOMINATOR_IS_ZERO)); - assert!(pool_config.vpool_locking_percentage != 0 && pool_config.vpool_locking_percentage <= 100, - error::invalid_argument(EPERCENTAGE_INVALID)); - //check the sum of numerator are <= denominator. - let sum = vector::fold(pool_config.vesting_numerators, 0, |acc, x| acc + x); - // Check that total of all fraction in `vesting_schedule` is not greater than 1 - assert!(sum <= pool_config.vesting_denominator, - error::invalid_argument(ENUMERATOR_GREATER_THAN_DENOMINATOR)); - //assert that withdrawal_address is registered to receive SupraCoin - assert!( - coin::is_account_registered(pool_config.withdrawal_address), - error::invalid_argument(EACCOUNT_NOT_REGISTERED_FOR_COIN) - ); - //assertion on admin_address? - let admin = create_signer(pool_config.admin_address); - - //Create the vesting schedule - let j = 0; - while (j < schedule_length) { - let numerator = *vector::borrow(&pool_config.vesting_numerators, j); - assert!(numerator != 0, error::invalid_argument(ENUMERATOR_IS_ZERO)); - let event = fixed_point32::create_from_rational(numerator, pool_config.vesting_denominator); - vector::push_back(&mut schedule, event); - j = j + 1; - }; - - let vesting_schedule = vesting_without_staking::create_vesting_schedule( - schedule, - timestamp::now_seconds() + pool_config.cliff_period_in_seconds, - pool_config.period_duration_in_seconds, - ); - - let buy_ins = simple_map::create(); - let num_shareholders = vector::length(&pool_config.shareholders); - assert!(num_shareholders != 0, error::invalid_argument(ENO_SHAREHOLDERS)); - let j = 0; - while (j < num_shareholders) { - let shareholder = *vector::borrow(&pool_config.shareholders, j); - assert!(!vector::contains(&unique_accounts, &shareholder), error::already_exists(EDUPLICATE_ACCOUNT)); - vector::push_back(&mut unique_accounts, shareholder); - let shareholder_signer = create_signer(shareholder); - let amount = coin::balance(shareholder); - let amount_to_extract = (amount * (pool_config.vpool_locking_percentage as u64)) / 100; - let coin_share = coin::withdraw(&shareholder_signer, amount_to_extract); - simple_map::add(&mut buy_ins, shareholder, coin_share); - j = j + 1; - }; - vesting_without_staking::create_vesting_contract( - &admin, - buy_ins, - vesting_schedule, - pool_config.withdrawal_address, - VESTING_CONTRACT_SEED - ); - }); + vector::for_each_ref( + &vesting_pool_map, + |pool_config| { + let pool_config: &VestingPoolsMap = pool_config; + let schedule = vector::empty(); + let schedule_length = vector::length(&pool_config.vesting_numerators); + assert!( + schedule_length != 0, + error::invalid_argument(EVESTING_SCHEDULE_IS_ZERO) + ); + assert!( + pool_config.vesting_denominator != 0, + error::invalid_argument(EDENOMINATOR_IS_ZERO) + ); + assert!( + pool_config.vpool_locking_percentage != 0 + && pool_config.vpool_locking_percentage <= 100, + error::invalid_argument(EPERCENTAGE_INVALID) + ); + //check the sum of numerator are <= denominator. + let sum = vector::fold( + pool_config.vesting_numerators, + 0, + |acc, x| acc + x + ); + // Check that total of all fraction in `vesting_schedule` is not greater than 1 + assert!( + sum <= pool_config.vesting_denominator, + error::invalid_argument(ENUMERATOR_GREATER_THAN_DENOMINATOR) + ); + //assert that withdrawal_address is registered to receive SupraCoin + assert!( + coin::is_account_registered(pool_config.withdrawal_address), + error::invalid_argument(EACCOUNT_NOT_REGISTERED_FOR_COIN) + ); + //assertion on admin_address? + let admin = create_signer(pool_config.admin_address); + + //Create the vesting schedule + let j = 0; + while (j < schedule_length) { + let numerator = *vector::borrow(&pool_config.vesting_numerators, j); + assert!(numerator != 0, error::invalid_argument(ENUMERATOR_IS_ZERO)); + let event = + fixed_point32::create_from_rational( + numerator, pool_config.vesting_denominator + ); + vector::push_back(&mut schedule, event); + j = j + 1; + }; + + let vesting_schedule = + vesting_without_staking::create_vesting_schedule( + schedule, + timestamp::now_seconds() + pool_config.cliff_period_in_seconds, + pool_config.period_duration_in_seconds + ); + + let buy_ins = simple_map::create(); + let num_shareholders = vector::length(&pool_config.shareholders); + assert!(num_shareholders != 0, error::invalid_argument(ENO_SHAREHOLDERS)); + let j = 0; + while (j < num_shareholders) { + let shareholder = *vector::borrow(&pool_config.shareholders, j); + assert!( + !vector::contains(&unique_accounts, &shareholder), + error::already_exists(EDUPLICATE_ACCOUNT) + ); + vector::push_back(&mut unique_accounts, shareholder); + let shareholder_signer = create_signer(shareholder); + let amount = coin::balance(shareholder); + let amount_to_extract = + (amount * (pool_config.vpool_locking_percentage as u64)) / 100; + let coin_share = + coin::withdraw( + &shareholder_signer, amount_to_extract + ); + simple_map::add(&mut buy_ins, shareholder, coin_share); + j = j + 1; + }; + vesting_without_staking::create_vesting_contract( + &admin, + buy_ins, + vesting_schedule, + pool_config.withdrawal_address, + VESTING_CONTRACT_SEED + ); + } + ); } - fun initialize_validator(pool_address: address, validator: &ValidatorConfiguration) { + fun initialize_validator( + pool_address: address, validator: &ValidatorConfiguration + ) { let operator = &create_signer(validator.operator_address); stake::rotate_consensus_key_genesis( operator, pool_address, - validator.consensus_pubkey, + validator.consensus_pubkey ); stake::update_network_and_fullnode_addresses( operator, pool_address, validator.network_addresses, - validator.full_node_network_addresses, + validator.full_node_network_addresses ); stake::join_validator_set_internal(operator, pool_address); } @@ -774,10 +907,12 @@ module supra_framework::genesis { rewards_rate, rewards_rate_denominator, voting_power_increase_limit, - 0, + 0 ); - features::change_feature_flags_for_verification(supra_framework, vector[1, 2, 11], vector[]); + features::change_feature_flags_for_verification( + supra_framework, vector[1, 2, 11], vector[] + ); initialize_supra_coin(supra_framework); supra_governance::initialize_for_verification( supra_framework, @@ -785,10 +920,12 @@ module supra_framework::genesis { // required_proposer_stake, voting_duration_secs, supra_min_voting_threshold, - voters, + voters ); create_accounts(supra_framework, accounts); - create_employee_validators(employee_vesting_start, employee_vesting_period_duration, employees); + create_employee_validators( + employee_vesting_start, employee_vesting_period_duration, employees + ); create_initialize_validators_with_commission(supra_framework, true, validators); set_genesis_end(supra_framework); } @@ -813,7 +950,7 @@ module supra_framework::genesis { 1, 1, 30, - 0, + 0 ) } @@ -854,14 +991,8 @@ module supra_framework::genesis { let addr1 = @0x121345; let accounts = vector[ - AccountMap { - account_address: addr0, - balance: 12345, - }, - AccountMap { - account_address: addr1, - balance: 67890, - }, + AccountMap { account_address: addr0, balance: 12345 }, + AccountMap { account_address: addr1, balance: 67890 } ]; create_accounts(supra_framework, accounts); @@ -873,10 +1004,20 @@ module supra_framework::genesis { } #[test_only] - fun generate_multisig_account(owner: &signer, addition_owner: vector
): address { + fun generate_multisig_account( + owner: &signer, addition_owner: vector
+ ): address { let owner_addr = aptos_std::signer::address_of(owner); - let multisig_addr = multisig_account::get_next_multisig_account_address(owner_addr); - multisig_account::create_with_owners(owner, addition_owner, 2, vector[], vector[], 300); + let multisig_addr = + multisig_account::get_next_multisig_account_address(owner_addr); + multisig_account::create_with_owners( + owner, + addition_owner, + 2, + vector[], + vector[], + 300 + ); multisig_addr } @@ -890,7 +1031,9 @@ module supra_framework::genesis { use std::features; let feature = features::get_new_accounts_default_to_fa_supra_store_feature(); - features::change_feature_flags_for_testing(supra_framework, vector[feature], vector[]); + features::change_feature_flags_for_testing( + supra_framework, vector[feature], vector[] + ); aggregator_factory::initialize_aggregator_factory_for_test(supra_framework); let (burn_cap, mint_cap) = supra_coin::initialize(supra_framework); @@ -900,9 +1043,14 @@ module supra_framework::genesis { supra_account::register_supra(&core_resources); // registers SUPRA store let sup_metadata = object::address_to_object(@supra_fungible_asset); - assert!(primary_fungible_store::primary_store_exists(@core_resources, sup_metadata), 2); + assert!( + primary_fungible_store::primary_store_exists(@core_resources, sup_metadata), + 2 + ); - supra_coin::configure_accounts_for_test(supra_framework, &core_resources, mint_cap); + supra_coin::configure_accounts_for_test( + supra_framework, &core_resources, mint_cap + ); coin::destroy_burn_cap(burn_cap); coin::destroy_mint_cap(mint_cap); } @@ -916,8 +1064,8 @@ module supra_framework::genesis { initialize_supra_coin(supra_framework); let owner = @0x121341; - let (_, pk_1) = stake::generate_identity(); - let _pk_1 = ed25519::unvalidated_public_key_to_bytes(&pk_1); + let (_sk_1, pk_1) = stake::generate_identity(); + let _pk_1 = validator_public_keys::public_key_to_bytes(pk_1); create_account(supra_framework, owner, 0); let validator_config_commission = ValidatorConfigurationWithCommission { validator_config: ValidatorConfiguration { @@ -927,10 +1075,10 @@ module supra_framework::genesis { stake_amount: 0, consensus_pubkey: _pk_1, network_addresses: x"222222", - full_node_network_addresses: x"333333", + full_node_network_addresses: x"333333" }, commission_percentage: 10, - join_during_genesis: true, + join_during_genesis: true }; let delegation_pool_creation_seed = x"121341"; let delegator_addresses = vector[@0x121342, @0x121343]; @@ -951,7 +1099,10 @@ module supra_framework::genesis { i = i + 1; }; let principle_lockup_time = 100; - let multisig = generate_multisig_account(&account::create_signer_for_test(owner), vector[@0x12134]); + let multisig = + generate_multisig_account( + &account::create_signer_for_test(owner), vector[@0x12134] + ); let pbo_delegator_config = PboDelegatorConfiguration { multisig_admin: multisig, unlock_period_duration: 12, @@ -963,8 +1114,8 @@ module supra_framework::genesis { validator: validator_config_commission, delegation_pool_creation_seed, delegator_addresses, - delegator_stakes, - }, + delegator_stakes + } }; create_pbo_delegation_pool(&pbo_delegator_config, delegation_percentage); let pool_address = pbo_delegation_pool::get_owned_pool_address(owner); @@ -979,10 +1130,10 @@ module supra_framework::genesis { initialize_supra_coin(supra_framework); let owner1 = @0x121341; create_account(supra_framework, owner1, 0); - let (_, pk_1) = stake::generate_identity(); - let (_, pk_2) = stake::generate_identity(); - let _pk_1 = ed25519::unvalidated_public_key_to_bytes(&pk_1); - let _pk_2 = ed25519::unvalidated_public_key_to_bytes(&pk_2); + let (_sk_1, pk_1) = stake::generate_identity(); + let (_sk_2, pk_2) = stake::generate_identity(); + let _pk_1 = validator_public_keys::public_key_to_bytes(pk_1); + let _pk_2 = validator_public_keys::public_key_to_bytes(pk_2); let validator_config_commission1 = ValidatorConfigurationWithCommission { validator_config: ValidatorConfiguration { owner_address: owner1, @@ -991,10 +1142,10 @@ module supra_framework::genesis { stake_amount: 100 * ONE_SUPRA, consensus_pubkey: _pk_1, network_addresses: x"222222", - full_node_network_addresses: x"333333", + full_node_network_addresses: x"333333" }, commission_percentage: 10, - join_during_genesis: true, + join_during_genesis: true }; let delegation_pool_creation_seed1 = x"121341"; let delegator_address1 = vector[@0x121342, @0x121343]; @@ -1015,7 +1166,10 @@ module supra_framework::genesis { i = i + 1; }; let principle_lockup_time1 = 100; - let multisig1 = generate_multisig_account(&account::create_signer_for_test(owner1), vector[@0x121342]); + let multisig1 = + generate_multisig_account( + &account::create_signer_for_test(owner1), vector[@0x121342] + ); let pbo_delegator_config1 = PboDelegatorConfiguration { multisig_admin: multisig1, unlock_period_duration: 12, @@ -1027,8 +1181,8 @@ module supra_framework::genesis { validator: validator_config_commission1, delegation_pool_creation_seed: delegation_pool_creation_seed1, delegator_addresses: delegator_address1, - delegator_stakes: delegator_stakes1, - }, + delegator_stakes: delegator_stakes1 + } }; let owner2 = @0x121344; @@ -1040,11 +1194,11 @@ module supra_framework::genesis { voter_address: @0x121346, stake_amount: 100 * ONE_SUPRA, consensus_pubkey: _pk_2, - network_addresses: x"222222", - full_node_network_addresses: x"333333", + network_addresses: x"444444", + full_node_network_addresses: x"555555" }, commission_percentage: 20, - join_during_genesis: true, + join_during_genesis: true }; let delegation_pool_creation_seed2 = x"121344"; let delegator_address2 = vector[@0x121345, @0x121346]; @@ -1053,12 +1207,22 @@ module supra_framework::genesis { let delegator_stakes2: vector = vector::empty(); while (j < vector::length(&delegator_address2)) { let bal = vector::borrow(&initial_balance2, j); - create_account(supra_framework, *vector::borrow(&delegator_address2, j), *bal); - vector::push_back(&mut delegator_stakes2, (*bal) * delegation_percentage / 100); + create_account( + supra_framework, + *vector::borrow(&delegator_address2, j), + *bal + ); + vector::push_back( + &mut delegator_stakes2, + (*bal) * delegation_percentage / 100 + ); j = j + 1; }; let principle_lockup_time2 = 200; - let multisig2 = generate_multisig_account(&account::create_signer_for_test(owner2), vector[@0x121347]); + let multisig2 = + generate_multisig_account( + &account::create_signer_for_test(owner2), vector[@0x121347] + ); let pbo_delegator_config2 = PboDelegatorConfiguration { multisig_admin: multisig2, unlock_period_duration: 12, @@ -1070,8 +1234,8 @@ module supra_framework::genesis { validator: validator_config_commission2, delegation_pool_creation_seed: delegation_pool_creation_seed2, delegator_addresses: delegator_address2, - delegator_stakes: delegator_stakes2, - }, + delegator_stakes: delegator_stakes2 + } }; let pbo_delegator_configs = vector[pbo_delegator_config1, pbo_delegator_config2]; create_pbo_delegation_pools(pbo_delegator_configs, delegation_percentage); @@ -1081,14 +1245,15 @@ module supra_framework::genesis { assert!(pbo_delegation_pool::delegation_pool_exists(pool_address2), 1); } - #[test (supra_framework= @0x1, owner1= @0x1234, owner2= @0x2345, owner3= @0x3456)] + #[test( + supra_framework = @0x1, owner1 = @0x1234, owner2 = @0x2345, owner3 = @0x3456 + )] fun test_create_multisig_account_with_balance( supra_framework: &signer, owner1: address, owner2: address, owner3: address - ) - { + ) { setup(); initialize_supra_coin(supra_framework); let additional_owners = vector[owner2, owner3]; @@ -1100,8 +1265,17 @@ module supra_framework::genesis { create_account(supra_framework, owner1, 0); create_account(supra_framework, owner2, 0); create_account(supra_framework, owner3, 0); - let addr = create_multisig_account_with_balance(supra_framework, owner1, additional_owners, - num_signatures_required, metadata_keys, metadata_values, timeout_duration, balance); + let addr = + create_multisig_account_with_balance( + supra_framework, + owner1, + additional_owners, + num_signatures_required, + metadata_keys, + metadata_values, + timeout_duration, + balance + ); //Ensure it is indeed on-chain multisig account with required threshold assert!(multisig_account::num_signatures_required(addr) == 2, 1); //Ensure the account is seeded with supplied balance @@ -1112,14 +1286,15 @@ module supra_framework::genesis { assert!(coin::balance(owner1) == balance, 3); } - #[test (supra_framework= @0x1, owner1= @0x1234, owner2= @0x2345, owner3= @0x3456)] + #[test( + supra_framework = @0x1, owner1 = @0x1234, owner2 = @0x2345, owner3 = @0x3456 + )] fun test_create_multisig_account_with_schema( supra_framework: &signer, owner1: address, owner2: address, owner3: address - ) - { + ) { setup(); initialize_supra_coin(supra_framework); let additional_owners = vector[owner2, owner3]; @@ -1132,18 +1307,42 @@ module supra_framework::genesis { create_account(supra_framework, owner1, 0); create_account(supra_framework, owner2, 0); create_account(supra_framework, owner3, 0); - let vec_addr = create_multiple_multisig_accounts_with_schema(supra_framework, owner1, - additional_owners, num_signatures_required, metadata_keys, metadata_values, - timeout_duration, balance, num_accounts); + let vec_addr = + create_multiple_multisig_accounts_with_schema( + supra_framework, + owner1, + additional_owners, + num_signatures_required, + metadata_keys, + metadata_values, + timeout_duration, + balance, + num_accounts + ); //Ensure they are indeed on-chain multisig account with required threshold - assert!(vector::all(&vec_addr, |elem| { multisig_account::num_signatures_required(*elem) == 2 }), 1); + assert!( + vector::all( + &vec_addr, + |elem| { multisig_account::num_signatures_required(*elem) == 2 } + ), + 1 + ); //Ensure the accounts are seeded with supplied balance - assert!(vector::all(&vec_addr, |elem| { coin::balance(*elem) == balance }), 2); + assert!( + vector::all( + &vec_addr, + |elem| { + coin::balance(*elem) == balance + } + ), + 2 + ); } - #[test(supra_framework = @0x1)] - fun test_create_vesting_without_staking_pools(supra_framework: &signer) { + fun test_create_vesting_without_staking_pools( + supra_framework: &signer + ) { // use supra_framework::supra_account::create_account; setup(); initialize_supra_coin(supra_framework); @@ -1159,10 +1358,9 @@ module supra_framework::genesis { create_account(supra_framework, withdrawal_address, 0); vector::for_each_ref(&shareholders, |addr| { let addr: address = *addr; - // Note: as exists_at will always give true as default account feature - // if (!account::exists_at(addr)) { + if (!account::exists_at(addr)) { create_account(supra_framework, addr, 100 * ONE_SUPRA); - // }; + }; }); let cliff_period_in_seconds = 100; let period_duration_in_seconds = 200; @@ -1174,7 +1372,7 @@ module supra_framework::genesis { withdrawal_address: withdrawal_address, shareholders: shareholders, cliff_period_in_seconds: cliff_period_in_seconds, - period_duration_in_seconds: period_duration_in_seconds, + period_duration_in_seconds: period_duration_in_seconds }; let vesting_pool_map = vector[pool_config]; create_vesting_without_staking_pools(vesting_pool_map); diff --git a/aptos-move/framework/supra-framework/sources/leader_ban_registry.move b/aptos-move/framework/supra-framework/sources/leader_ban_registry.move new file mode 100644 index 00000000000..0a913126b15 --- /dev/null +++ b/aptos-move/framework/supra-framework/sources/leader_ban_registry.move @@ -0,0 +1,647 @@ +/// Maintains the list of banned validators and updates counters on every epoch. +/// +/// This implementation assumes that each validator is elected once every `n` consensus rounds on expectation, +/// where `n` is the number of validators in the consensus committee (i.e. the `ValidatorSet`). +module supra_framework::leader_ban_registry { + use std::error; + use std::features; + use std::option; + use std::option::Option; + use supra_framework::system_addresses; + use std::vector; + use aptos_std::math64::{pow, min}; + use supra_framework::event; + use supra_framework::stake; + use supra_framework::leader_ban_registry_config; + + friend supra_framework::block; + friend supra_framework::genesis; + friend supra_framework::reconfiguration; + + #[test_only] + friend supra_framework::test_leader_ban_registry; + + /// Leader ban registry already initialized + const EBAN_REGISTRY_ALREADY_EXISTS: u64 = 1; + /// Leader ban registry not initialized + const EBAN_REGISTRY_NOT_INITIALIZED: u64 = 2; + /// Latest view already initialized + const ELATEST_VIEW_ALREADY_EXISTS: u64 = 3; + + /// Information about a ban that is currently in effect for a validator. + struct ActiveBan has store, drop, copy { + /// The consensus epoch in which the current ban was issued (if `on_probation` is `false`) or + /// when its probation period started (if `on_probation` is `true`). + epoch_earned: u64, + /// The consensus round in which the current ban was issued (if `on_probation` is `false`) or + /// when its probation period started (if `on_probation` is `true`). + round_earned: u64, + /// Round count incremented on every epoch change + rounds_served_in_previous_epochs: u64, + /// If `true` then the current ban period has expired and the validator is currently on probation; i.e., it is + /// eligible for election but will be banned for a longer period if it once again fails to propose a canonical + /// block when elected. If `true` then the other fields of this struct denote the consensus view in which + /// the probation period started. + on_probation: bool + } + + /// Holds validator metrics regarding duration pool address etc + struct ValidatorBans has store, drop, copy { + /// Information about the ban that is currently in effect. + active: ActiveBan, + /// The number of consecutive probations that this validator has failed. + consecutive_bans: u32, + /// Validator's pool address + pool_address: address + } + + /// Holds ban registry + struct BanRegistry has drop, store, key { + /// List of validator active bans with pool address + bans: vector + } + + /// Holds latest processed round and epoch + struct LatestView has drop, store, key, copy { + /// Epoch + epoch: u64, + /// Round + round: u64 + } + + #[event] + /// Emits when validator receives a ban or consucutive ban occurred + struct Banned has drop, store { + /// Validator's pool address + pool_address: address, + /// Epoch + epoch: u64, + /// Round + round: u64, + /// The number of consecutive probations that this validator has failed. + consecutive_bans: u32 + } + + #[event] + /// Emitted when a validator's ban is lifted and its probation period starts. A validator that is on probation is + /// eligible for election again, but will be banned for longer if it once again fails to propose a canonical block. + struct ReinstatedWithProbation has drop, store { + /// Validator's pool address + pool_address: address, + /// Epoch + epoch: u64, + /// Round + round: u64 + } + + #[event] + /// Emitted when a validator's probation period ends without the validator earning a new ban. + struct Reinstated has drop, store { + /// Validator's pool address + pool_address: address, + /// Epoch + epoch: u64, + /// Round + round: u64 + } + + /// Initialise leader ban registry + public(friend) fun initialize_leader_ban_registry( + supra_framework: &signer + ) { + system_addresses::assert_supra_framework(supra_framework); + assert!( + !exists(@supra_framework), + error::already_exists(EBAN_REGISTRY_ALREADY_EXISTS) + ); + assert!( + !exists(@supra_framework), + error::already_exists(EBAN_REGISTRY_ALREADY_EXISTS) + ); + move_to(supra_framework, BanRegistry { bans: vector::empty() }); + move_to(supra_framework, LatestView { epoch: 0, round: 0 }); + } + + #[view] + /// Returns list of validators active ban with it's pool address + public fun get_ban_registry(): vector acquires BanRegistry { + if (!exists(@supra_framework)) { + return vector::empty() + }; + let ban_registry = borrow_global(@supra_framework); + ban_registry.bans + } + + #[view] + /// Return latest view + public fun get_latest_view(): LatestView acquires LatestView { + if (!exists(@supra_framework)) { + return LatestView { epoch: 0, round: 0 } + }; + let latest_view = borrow_global(@supra_framework); + *latest_view + } + + #[view] + /// Returns the number of consensus rounds that a validator is banned for when it fails to propose a + /// canonical block when elected as leader whilst not on probation. + public fun get_initial_ban_duration(): u64 { + let initial_elections_denied = + leader_ban_registry_config::get_initial_elections_denied(); + let committee_size = stake::get_committee_size(); + committee_size * (initial_elections_denied as u64) + } + + #[view] + /// Returns the maximum number of consensus rounds that a validator may banned for when it repeatedly fails to + /// propose a canonical block when elected as leader whilst on probation. + public fun get_max_ban_duration(): u64 { + let max_elections_denied = leader_ban_registry_config::get_max_elections_denied(); + let committee_size = stake::get_committee_size(); + committee_size * (max_elections_denied as u64) + } + + #[view] + /// Returns the number of consensus rounds that a validator is considered to be on probation for after having + /// served its most recent ban. + public fun get_probation_duration(): u64 { + let probation_elections = leader_ban_registry_config::get_probation_elections(); + let committee_size = stake::get_committee_size(); + committee_size * (probation_elections as u64) + } + + #[view] + /// Returns the number of consensus rounds remaining in the ban for the validator with the given + /// pool address. Returns 0 if the validator is not banned (including if it is on probation). + public fun get_remaining_ban_duration( + pool_address: address + ): u64 acquires BanRegistry, LatestView { + if (!exists(@supra_framework) + || !exists(@supra_framework)) { + return 0 + }; + let ban_registry = borrow_global(@supra_framework); + let latest_view = borrow_global(@supra_framework); + let (found, index) = vector::find( + &ban_registry.bans, + |v| { + let v: &ValidatorBans = v; + v.pool_address == pool_address && !v.active.on_probation + } + ); + if (found) { + remaining_ban_duration( + vector::borrow(&ban_registry.bans, index), latest_view + ) + } else { 0 } + } + + #[view] + /// Returns the number of consensus rounds remaining in the probation period for the validator + /// with the given pool address. Returns 0 if the validator is not on probation. + public fun get_remaining_probation_duration( + pool_address: address + ): u64 acquires BanRegistry, LatestView { + if (!exists(@supra_framework) + || !exists(@supra_framework)) { + return 0 + }; + let ban_registry = borrow_global(@supra_framework); + let latest_view = borrow_global(@supra_framework); + let (found, index) = vector::find( + &ban_registry.bans, + |v| { + let v: &ValidatorBans = v; + v.pool_address == pool_address && v.active.on_probation + } + ); + if (found) { + let probation_dur = get_probation_duration(); + remaining_probation_duration( + vector::borrow(&ban_registry.bans, index), + latest_view, + probation_dur + ) + } else { 0 } + } + + /// Add or update the ban registry as per block metadata + public(friend) fun update_ban_registry( + current_epoch: u64, + current_round: u64, + proposer_index: Option, + failed_proposer_indices: vector + ) acquires BanRegistry, LatestView { + if (!exists(@supra_framework)) { return }; + if (!exists(@supra_framework)) { return }; + let ban_registry = borrow_global_mut(@supra_framework); + let latest_view = borrow_global_mut(@supra_framework); + + // Save the previous view before updating. Each failed proposer failed at a + // distinct round between the previous commit and the current commit, so we + // need this to reconstruct the actual round at which each ban was earned. + let previous_epoch = latest_view.epoch; + let previous_round = latest_view.round; + + // we expect that current_epoch == latest_view.epoch || current_epoch == latest_view.epoch + 1, + // but we don't assert this to be true here because it should be ensured by the consensus. + if (current_epoch < latest_view.epoch) { return }; + + latest_view.epoch = current_epoch; + latest_view.round = current_round; + + // ban the failed proposers + ban_failed_proposers( + current_epoch, previous_epoch, previous_round, + failed_proposer_indices, ban_registry + ); + + // remove expired bans + reinstate_expired_bans(latest_view, ban_registry); + } + + /// Adds failed proposer indices to ban registry. Each failed proposer failed at a + /// consecutive round between the previous commit and the current commit. The actual + /// failed round is reconstructed from the previous view: + /// - Same epoch: failed rounds start at `previous_round + 1` + /// - Epoch boundary: failed rounds start at `0` (new epoch resets round to 0) + fun ban_failed_proposers( + current_epoch: u64, + previous_epoch: u64, + previous_round: u64, + failed_proposer_indices: vector, + ban_registry: &mut BanRegistry + ) { + let initial_ban_duration = get_initial_ban_duration(); + if (initial_ban_duration == 0) { return }; + + // Compute the first failed round based on whether the epoch changed. + let first_failed_round = if (previous_epoch == current_epoch) { + previous_round + 1 + } else { + // Epoch boundary: the last block of the previous epoch was committed + // successfully, so failures start from round 0 of the new epoch. + 0 + }; + + let i = 0; + let len = vector::length(&failed_proposer_indices); + while (i < len) { + let failed_validator_index = *vector::borrow(&failed_proposer_indices, i); + let failed_round = first_failed_round + i; + + let validator_pool_address_opt = + stake::get_pool_address_from_index(failed_validator_index); + + if (option::is_some(&validator_pool_address_opt)) { + let validator_pool_address = + option::extract(&mut validator_pool_address_opt); + let (is_banned, index) = vector::find( + &ban_registry.bans, + |v| { + let v: &ValidatorBans = v; + validator_pool_address == v.pool_address + } + ); + if (is_banned) { + // Validator is already in registry (either banned or on probation). + // Re-banning resets the ban period and increases consecutive count. + // If the consensus code is implemented correctly then the validator should + // not be re-banned whilst serving a ban as it should not be eligible for election + // when banned (i.e. this branch should only be taken when a validator is on probation). + let bans = vector::borrow_mut(&mut ban_registry.bans, index); + bans.consecutive_bans = bans.consecutive_bans + 1; + bans.active.round_earned = failed_round; + bans.active.epoch_earned = current_epoch; + bans.active.rounds_served_in_previous_epochs = 0; + bans.active.on_probation = false; // Reset to banned state + + if (features::module_event_enabled()) { + event::emit( + Banned { + pool_address: validator_pool_address, + epoch: current_epoch, + round: failed_round, + consecutive_bans: bans.consecutive_bans + } + ); + } + } else { + let ban_registry_len = vector::length(&ban_registry.bans); + if (can_be_banned(ban_registry_len)) { + let ban_with_address = ValidatorBans { + active: ActiveBan { + epoch_earned: current_epoch, + round_earned: failed_round, + rounds_served_in_previous_epochs: 0, + on_probation: false + }, + consecutive_bans: 0, + pool_address: validator_pool_address + }; + vector::push_back(&mut ban_registry.bans, ban_with_address); + + if (features::module_event_enabled()) { + event::emit( + Banned { + pool_address: ban_with_address.pool_address, + epoch: ban_with_address.active.epoch_earned, + round: ban_with_address.active.round_earned, + consecutive_bans: ban_with_address.consecutive_bans + } + ); + } + } + }; + }; + + i = i + 1; + }; + } + + /// Handles ban and probation expiry: + /// - When probation expires: removes from registry, emits Reinstated + /// - When ban expires and probation_duration > 0: transitions to probation, emits ReinstatedWithProbation + /// - When ban expires and probation_duration == 0: removes from registry, emits Reinstated + fun reinstate_expired_bans( + latest_view: &LatestView, ban_registry: &mut BanRegistry + ) { + let probation_duration = get_probation_duration(); + + // First pass: remove validators whose probation has expired. + // Done before ban-to-probation transitions to avoid iterating just-transitioned validators. + // Always runs (even when probation_duration == 0) to clean up validators that were already + // on probation before a config change set probation_duration to 0. + let pool_addresses_for_full_reinstatement = vector::empty(); + vector::for_each_ref( + &ban_registry.bans, + |v| { + let v: &ValidatorBans = v; + if (v.active.on_probation + && remaining_probation_duration(v, latest_view, probation_duration) + == 0) { + vector::push_back( + &mut pool_addresses_for_full_reinstatement, v.pool_address + ); + } + } + ); + + vector::for_each_ref( + &pool_addresses_for_full_reinstatement, + |p| { + let (found, index) = vector::find( + &ban_registry.bans, + |v| { + let v: &ValidatorBans = v; + &v.pool_address == p + } + ); + if (found) { + vector::swap_remove(&mut ban_registry.bans, index); + + if (features::module_event_enabled()) { + event::emit( + Reinstated { + epoch: latest_view.epoch, + round: latest_view.round, + pool_address: *p + } + ) + } + } + } + ); + + // Second pass: handle expired bans + let pool_addresses_with_expired_bans = vector::empty(); + vector::for_each_ref( + &ban_registry.bans, + |v| { + let v: &ValidatorBans = v; + if (!v.active.on_probation + && remaining_ban_duration(v, latest_view) == 0) { + vector::push_back( + &mut pool_addresses_with_expired_bans, v.pool_address + ); + } + } + ); + + if (probation_duration > 0) { + // Transition expired bans to probation + vector::for_each_ref( + &pool_addresses_with_expired_bans, + |p| { + let (found, index) = vector::find( + &ban_registry.bans, + |v| { + let v: &ValidatorBans = v; + &v.pool_address == p + } + ); + if (found) { + let ban = vector::borrow_mut(&mut ban_registry.bans, index); + ban.active.on_probation = true; + // Reset active fields so probation duration is calculated from this point + ban.active.epoch_earned = latest_view.epoch; + ban.active.round_earned = latest_view.round; + ban.active.rounds_served_in_previous_epochs = 0; + + if (features::module_event_enabled()) { + event::emit( + ReinstatedWithProbation { + epoch: latest_view.epoch, + round: latest_view.round, + pool_address: *p + } + ) + } + } + } + ); + } else { + // No probation period - directly remove validators whose ban expired + vector::for_each_ref( + &pool_addresses_with_expired_bans, + |p| { + let (found, index) = vector::find( + &ban_registry.bans, + |v| { + let v: &ValidatorBans = v; + &v.pool_address == p + } + ); + if (found) { + vector::swap_remove(&mut ban_registry.bans, index); + + if (features::module_event_enabled()) { + event::emit( + Reinstated { + epoch: latest_view.epoch, + round: latest_view.round, + pool_address: *p + } + ) + } + } + } + ); + }; + } + + /// Increments the total number of consensus rounds served by each banned validator and removes + /// registry entries for validators that have left the validator set. + /// + /// The number of rounds in each epoch may vary due to network asynchrony, so we must record the + /// number of rounds served in previous epochs to be able to ensure that a banned validator serves its + /// full ban period when its ban span multiple epochs. + public(friend) fun on_new_epoch() acquires BanRegistry, LatestView { + if (!exists(@supra_framework)) { return }; + if (!exists(@supra_framework)) { return }; + let latest_view = borrow_global(@supra_framework); + let ban_registry = borrow_global_mut(@supra_framework); + + // The pool addresses of the validators for the new epoch. + let new_committee_pool_addresses = stake::get_committee_pool_addresses(); + // The pool addresses of the validators that have left the committee. + let retired_validators = vector::empty(); + vector::for_each_mut( + &mut ban_registry.bans, + |v| { + let v: &mut ValidatorBans = v; + if (vector::contains(&new_committee_pool_addresses, &v.pool_address)) { + if (latest_view.epoch > v.active.epoch_earned) { + v.active.rounds_served_in_previous_epochs = + v.active.rounds_served_in_previous_epochs + + latest_view.round; + } else if (latest_view.epoch == v.active.epoch_earned + && latest_view.round > v.active.round_earned) { + v.active.rounds_served_in_previous_epochs = + latest_view.round - v.active.round_earned; + }; + // else: The ban hasn't started yet. + } else { + vector::push_back(&mut retired_validators, v.pool_address) + } + } + ); + + vector::for_each_ref( + &retired_validators, + |p| { + let (is_banned, index) = vector::find( + &ban_registry.bans, + |v| { + let v: &ValidatorBans = v; + &v.pool_address == p + } + ); + if (is_banned) { + vector::swap_remove(&mut ban_registry.bans, index); + + if (features::module_event_enabled()) { + event::emit( + Reinstated { + pool_address: *p, + epoch: latest_view.epoch, + round: latest_view.round + } + ); + } + } + } + ); + } + + /// Calculate the number of rounds remaining in a given ban (not including probation). + fun remaining_ban_duration( + ban: &ValidatorBans, latest_view: &LatestView + ): u64 { + let initial_ban_duration = get_initial_ban_duration(); + let max_ban_duration = get_max_ban_duration(); + // Guard against overflow: pow(2, n) overflows u64 when n >= 64, and the + // subsequent multiplication can overflow for smaller exponents. In both cases + // the uncapped result would exceed max_ban_duration, so we short-circuit. + let duration = if ((ban.consecutive_bans as u64) >= 64) { + max_ban_duration + } else { + let scale = pow(2, (ban.consecutive_bans as u64)); + if (initial_ban_duration > 0 && scale > max_ban_duration / initial_ban_duration) { + max_ban_duration + } else { + min(initial_ban_duration * scale, max_ban_duration) + } + }; + let rounds_served = + if (latest_view.epoch > ban.active.epoch_earned) { + ban.active.rounds_served_in_previous_epochs + latest_view.round + } else if (latest_view.epoch == ban.active.epoch_earned + && latest_view.round > ban.active.round_earned) { + latest_view.round - ban.active.round_earned + } else { + // The ban hasn't started yet. + 0 + }; + if (duration > rounds_served) { + duration - rounds_served + } else { 0 } + } + + /// Calculate the number of rounds remaining in probation. + /// Probation duration is constant and does not scale with consecutive bans. + fun remaining_probation_duration( + ban: &ValidatorBans, latest_view: &LatestView, probation_duration: u64 + ): u64 { + let rounds_served = + if (latest_view.epoch > ban.active.epoch_earned) { + ban.active.rounds_served_in_previous_epochs + latest_view.round + } else if (latest_view.epoch == ban.active.epoch_earned + && latest_view.round > ban.active.round_earned) { + latest_view.round - ban.active.round_earned + } else { + // The ban hasn't started yet. + 0 + }; + if (probation_duration > rounds_served) { + probation_duration - rounds_served + } else { 0 } + } + + /// Returns true until ban registry size + minimum proposers required count less than committee size + fun can_be_banned(ban_registry_len: u64): bool { + let minimum_unbanned_proposers = + leader_ban_registry_config::get_minimum_unbanned_proposers(); + let committee_size = stake::get_committee_size(); + committee_size > ban_registry_len + (minimum_unbanned_proposers as u64) + } + + /// Validates registry initialised if not aborted with `EBAN_REGISTRY_NOT_INITIALIZED` + fun assert_registry_initialized() { + assert!( + exists(@supra_framework), + error::invalid_state(EBAN_REGISTRY_NOT_INITIALIZED) + ); + } + + #[test_only] + public fun get_pool_address_from_vp( + validator_with_pool_addr: &ValidatorBans + ): address { + validator_with_pool_addr.pool_address + } + + #[test_only] + public fun get_consecutive_count_from_vp( + validator_with_pool_addr: &ValidatorBans + ): u32 { + validator_with_pool_addr.consecutive_bans + } + + #[test_only] + public fun is_on_probation_from_vp( + validator_with_pool_addr: &ValidatorBans + ): bool { + validator_with_pool_addr.active.on_probation + } +} diff --git a/aptos-move/framework/supra-framework/sources/multisig_voting.move b/aptos-move/framework/supra-framework/sources/multisig_voting.move index 193c24865e8..7c36e16803c 100644 --- a/aptos-move/framework/supra-framework/sources/multisig_voting.move +++ b/aptos-move/framework/supra-framework/sources/multisig_voting.move @@ -657,7 +657,11 @@ module supra_framework::multisig_voting { ): u64 acquires VotingForum { if (is_voting_closed(voting_forum_address, proposal_id)) { let proposal = get_proposal(voting_forum_address, proposal_id); - if (proposal.yes_votes >= proposal.min_vote_threshold) { + let yes_votes = proposal.yes_votes; + let no_votes = proposal.no_votes; + + if (yes_votes > no_votes && + yes_votes + no_votes >= proposal.min_vote_threshold) { PROPOSAL_STATE_SUCCEEDED } else { PROPOSAL_STATE_FAILED diff --git a/aptos-move/framework/supra-framework/sources/pbo_delegation_pool.move b/aptos-move/framework/supra-framework/sources/pbo_delegation_pool.move index 848188e4aae..f26bea1a75c 100644 --- a/aptos-move/framework/supra-framework/sources/pbo_delegation_pool.move +++ b/aptos-move/framework/supra-framework/sources/pbo_delegation_pool.move @@ -256,8 +256,12 @@ module supra_framework::pbo_delegation_pool { /// amount of stake available in the specified stake pool. const EINSUFFICIENT_STAKE_TO_LOCK: u64 = 40; + /// Unlocking has already started, so unlock schedule can not be updated const EUNLOCKING_ALREADY_STARTED: u64 = 41; + /// Can not increase last unlock period if not at the last element of schedule + const EINVALID_STATE_FOR_OPERATION: u64 = 42; + const MAX_U64: u64 = 18446744073709551615; /// Maximum operator percentage fee(of double digit precision): 22.85% is represented as 2285 @@ -524,8 +528,9 @@ module supra_framework::pbo_delegation_pool { #[view] /// Return whether a delegation pool has already enabled partial govnernance voting. public fun partial_governance_voting_enabled(pool_address: address): bool { - exists(pool_address) - && stake::get_delegated_voter(pool_address) == pool_address + exists(pool_address) && stake::get_delegated_voter( + pool_address + ) == pool_address } #[view] @@ -540,16 +545,13 @@ module supra_framework::pbo_delegation_pool { public fun is_next_commission_percentage_effective( pool_address: address ): bool acquires NextCommissionPercentage { - exists(pool_address) - && timestamp::now_seconds() - >= borrow_global(pool_address).effective_after_secs + exists(pool_address) && timestamp::now_seconds() >= borrow_global< + NextCommissionPercentage>(pool_address).effective_after_secs } #[view] /// Return the operator commission percentage set on the delegation pool `pool_address`. - public fun operator_commission_percentage( - pool_address: address - ): u64 acquires DelegationPool, NextCommissionPercentage { + public fun operator_commission_percentage(pool_address: address): u64 acquires DelegationPool, NextCommissionPercentage { assert_delegation_pool_exists(pool_address); if (is_next_commission_percentage_effective(pool_address)) { operator_commission_percentage_next_lockup_cycle(pool_address) @@ -576,7 +578,7 @@ module supra_framework::pbo_delegation_pool { public fun shareholders_count_active_pool(pool_address: address): u64 acquires DelegationPool { assert_delegation_pool_exists(pool_address); pool_u64::shareholders_count( - &borrow_global(pool_address).active_shares + &borrow_global(pool_address).active_shares, ) } @@ -596,11 +598,13 @@ module supra_framework::pbo_delegation_pool { ): (bool, u64) acquires DelegationPool { assert_delegation_pool_exists(pool_address); let pool = borrow_global(pool_address); - let (lockup_cycle_ended, _, pending_inactive, _, commission_pending_inactive) = - calculate_stake_pool_drift(pool); + let (lockup_cycle_ended, _, pending_inactive, _, commission_pending_inactive) = calculate_stake_pool_drift( + pool + ); - let (withdrawal_exists, withdrawal_olc) = - pending_withdrawal_exists(pool, delegator_address); + let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists( + pool, delegator_address + ); if (!withdrawal_exists) { // if no pending withdrawal, there is neither inactive nor pending_inactive stake (false, 0) @@ -615,7 +619,7 @@ module supra_framework::pbo_delegation_pool { inactive_shares, pool_u64::shares(inactive_shares, delegator_address), // exclude operator pending_inactive rewards not converted to shares yet - pending_inactive - commission_pending_inactive + pending_inactive - commission_pending_inactive, ); // if withdrawal's lockup cycle ended ONLY on stake pool then it is also inactive (lockup_cycle_ended, pending_inactive) @@ -632,19 +636,20 @@ module supra_framework::pbo_delegation_pool { assert_delegation_pool_exists(pool_address); let pool = borrow_global(pool_address); let (lockup_cycle_ended, active, _, commission_active, commission_pending_inactive) = - - calculate_stake_pool_drift(pool); + calculate_stake_pool_drift(pool); let total_active_shares = pool_u64::total_shares(&pool.active_shares); - let delegator_active_shares = - pool_u64::shares(&pool.active_shares, delegator_address); + let delegator_active_shares = pool_u64::shares( + &pool.active_shares, delegator_address + ); let (_, _, pending_active, _) = stake::get_stake(pool_address); if (pending_active == 0) { // zero `pending_active` stake indicates that either there are no `add_stake` fees or // previous epoch has ended and should identify shares owning these fees as released - total_active_shares = total_active_shares - - pool_u64::shares(&pool.active_shares, NULL_SHAREHOLDER); + total_active_shares = total_active_shares - pool_u64::shares( + &pool.active_shares, NULL_SHAREHOLDER + ); if (delegator_address == NULL_SHAREHOLDER) { delegator_active_shares = 0 } @@ -654,16 +659,16 @@ module supra_framework::pbo_delegation_pool { delegator_active_shares, // exclude operator active rewards not converted to shares yet active - commission_active, - total_active_shares + total_active_shares, ); // get state and stake (0 if there is none) of the pending withdrawal - let (withdrawal_inactive, withdrawal_stake) = - get_pending_withdrawal(pool_address, delegator_address); + let (withdrawal_inactive, withdrawal_stake) = get_pending_withdrawal( + pool_address, delegator_address + ); // report non-active stakes accordingly to the state of the pending withdrawal let (inactive, pending_inactive) = - if (withdrawal_inactive) (withdrawal_stake, 0) - else (0, withdrawal_stake); + if (withdrawal_inactive) (withdrawal_stake, 0) else (0, withdrawal_stake); // should also include commission rewards in case of the operator account // operator rewards are actually used to buy shares which is introducing @@ -691,21 +696,24 @@ module supra_framework::pbo_delegation_pool { /// To mitigate this, some of the added stake is extracted and fed back into the pool as placeholder /// for the rewards the remaining stake would have earned if active: /// extracted-fee = (amount - extracted-fee) * reward-rate% * (100% - operator-commission%) - public fun get_add_stake_fee( - pool_address: address, amount: u64 - ): u64 acquires DelegationPool, NextCommissionPercentage { + public fun get_add_stake_fee(pool_address: address, amount: u64): u64 acquires DelegationPool, NextCommissionPercentage { if (stake::is_current_epoch_validator(pool_address)) { - let (rewards_rate, rewards_rate_denominator) = - staking_config::get_reward_rate(&staking_config::get()); + let (rewards_rate, rewards_rate_denominator) = staking_config::get_reward_rate( + &staking_config::get() + ); if (rewards_rate_denominator != 0) { assert_delegation_pool_exists(pool_address); - rewards_rate = rewards_rate - * (MAX_FEE - operator_commission_percentage(pool_address)); + rewards_rate = rewards_rate * ( + MAX_FEE - operator_commission_percentage(pool_address) + ); rewards_rate_denominator = rewards_rate_denominator * MAX_FEE; ( - (((amount as u128) * (rewards_rate as u128)) - / ((rewards_rate as u128) + (rewards_rate_denominator as u128))) as u64 + ( + ((amount as u128) * (rewards_rate as u128)) / ( + (rewards_rate as u128) + (rewards_rate_denominator as u128) + ) + ) as u64 ) } else { 0 } } else { 0 } @@ -716,8 +724,8 @@ module supra_framework::pbo_delegation_pool { /// the delegation pool, implicitly its stake pool, in the special case /// the validator had gone inactive before its lockup expired. public fun can_withdraw_pending_inactive(pool_address: address): bool { - stake::get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE - && timestamp::now_seconds() >= stake::get_lockup_secs(pool_address) + stake::get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE && timestamp::now_seconds() + >= stake::get_lockup_secs(pool_address) } #[view] @@ -732,8 +740,9 @@ module supra_framework::pbo_delegation_pool { synchronize_delegation_pool(pool_address); let pool = borrow_global(pool_address); let governance_records = borrow_global_mut(pool_address); - let latest_delegated_votes = - update_and_borrow_mut_delegated_votes(pool, governance_records, voter); + let latest_delegated_votes = update_and_borrow_mut_delegated_votes( + pool, governance_records, voter + ); calculate_total_voting_power(pool, latest_delegated_votes) } @@ -747,7 +756,7 @@ module supra_framework::pbo_delegation_pool { calculate_and_update_delegator_voter_internal( borrow_global(pool_address), borrow_global_mut(pool_address), - delegator_address + delegator_address, ) } @@ -783,7 +792,7 @@ module supra_framework::pbo_delegation_pool { ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { assert!( coin::balance(signer::address_of(owner)) >= amount, - error::invalid_argument(EBALANCE_NOT_SUFFICIENT) + error::invalid_argument(EBALANCE_NOT_SUFFICIENT), ); let coin = coin::withdraw(owner, amount); @@ -798,7 +807,7 @@ module supra_framework::pbo_delegation_pool { unlock_numerators, unlock_denominator, unlock_start_time, - unlock_duration + unlock_duration, ) } @@ -817,7 +826,7 @@ module supra_framework::pbo_delegation_pool { ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { assert!( coin::balance(signer::address_of(owner)) >= amount, - error::invalid_argument(EBALANCE_NOT_SUFFICIENT) + error::invalid_argument(EBALANCE_NOT_SUFFICIENT), ); let coin = coin::withdraw(owner, amount); @@ -832,17 +841,17 @@ module supra_framework::pbo_delegation_pool { unlock_numerators, unlock_denominator, unlock_start_time, - unlock_duration + unlock_duration, ) } #[view] /// Return the unlock schedule of the pool as (schedule, start_time, period_duration, last_unlock_period, cumulative_unlocked_fraction) - public fun get_unlock_schedule( - pool_address: address - ): (vector, u64, u64, u64, FixedPoint64) acquires DelegationPool { - let uschedule = - borrow_global(pool_address).principle_unlock_schedule; + public fun get_unlock_schedule(pool_address: address) + : ( + vector, u64, u64, u64, FixedPoint64 + ) acquires DelegationPool { + let uschedule = borrow_global(pool_address).principle_unlock_schedule; ( uschedule.schedule, uschedule.start_timestamp_secs, @@ -856,25 +865,73 @@ module supra_framework::pbo_delegation_pool { // Create `vector` for schedule fractions from numerators and a denominator // Pre-condition: It is assumed that `validate_unlock_schedule_params` is called before this // If the denominator is zero, this function would fail in `create_from_rational` - fun create_schedule_fractions(unlock_numerators: &vector, unlock_denominator: u64) : vector { + fun create_schedule_fractions( + unlock_numerators: &vector, unlock_denominator: u64 + ): vector { - //Create unlock schedule + //Create unlock schedule let schedule = vector::empty(); vector::for_each_ref( unlock_numerators, |e| { - let fraction = - fixed_point64::create_from_rational( - (*e as u128), (unlock_denominator as u128) - ); + let fraction = fixed_point64::create_from_rational( + (*e as u128), + (unlock_denominator as u128), + ); vector::push_back(&mut schedule, fraction); - } + }, ); schedule } + // CAUTION: No pre-conditions checks are done, admin must use this with utmost care + // Does not change `cumulative_unlocked_fraction` to avoid certain inconsistency + public entry fun update_unlocking_schedule_unchecked( + multisig_admin: &signer, + pool_address: address, + unlock_numerators: vector, + unlock_denominator: u64, + unlock_start_time: u64, + unlock_duration: u64, + last_unlock_period: u64 + ) acquires DelegationPool { + assert!( + is_admin(signer::address_of(multisig_admin), pool_address), + error::permission_denied(ENOT_AUTHORIZED), + ); + let pool = borrow_global_mut(pool_address); + + validate_unlock_schedule_params( + &unlock_numerators, + unlock_denominator, + unlock_start_time, + unlock_duration, + ); + + //Create unlock schedule fractions + let schedule = create_schedule_fractions(&unlock_numerators, unlock_denominator); + + pool.principle_unlock_schedule = UnlockSchedule { + schedule: schedule, + start_timestamp_secs: unlock_start_time, + period_duration: unlock_duration, + last_unlock_period: last_unlock_period, + cumulative_unlocked_fraction: pool.principle_unlock_schedule.cumulative_unlocked_fraction + }; + event::emit( + UnlockScheduleUpdated { + pool_address, + unlock_numerators, + unlock_denominator, + unlock_start_time, + unlock_duration + }, + ); + + } + /// Pre-condition: `cumulative_unlocked_fraction` should be zero, which would indicate that even /// though there are principle stake holders, none of those have yet called `unlock` on the pool /// thus it is ``safe'' to change the schedule @@ -891,25 +948,25 @@ module supra_framework::pbo_delegation_pool { ) acquires DelegationPool { assert!( is_admin(signer::address_of(multisig_admin), pool_address), - error::permission_denied(ENOT_AUTHORIZED) + error::permission_denied(ENOT_AUTHORIZED), ); let pool = borrow_global_mut(pool_address); assert!( fixed_point64::is_zero( pool.principle_unlock_schedule.cumulative_unlocked_fraction ), - error::invalid_state(EUNLOCKING_ALREADY_STARTED) + error::invalid_state(EUNLOCKING_ALREADY_STARTED), ); validate_unlock_schedule_params( &unlock_numerators, unlock_denominator, unlock_start_time, - unlock_duration + unlock_duration, ); //Create unlock schedule fractions - let schedule = create_schedule_fractions(&unlock_numerators,unlock_denominator); + let schedule = create_schedule_fractions(&unlock_numerators, unlock_denominator); pool.principle_unlock_schedule = UnlockSchedule { schedule: schedule, @@ -925,7 +982,7 @@ module supra_framework::pbo_delegation_pool { unlock_denominator, unlock_start_time, unlock_duration - } + }, ); } @@ -945,23 +1002,23 @@ module supra_framework::pbo_delegation_pool { //Fraction numerators can not be empty assert!( numerator_length != 0, - error::invalid_argument(EEMPTY_UNLOCK_SCHEDULE) + error::invalid_argument(EEMPTY_UNLOCK_SCHEDULE), ); //First and last numerator can not be zero assert!( *vector::borrow(unlock_numerators, 0) != 0, - error::invalid_argument(ESCHEDULE_WITH_ZERO_FRACTION) + error::invalid_argument(ESCHEDULE_WITH_ZERO_FRACTION), ); assert!( *vector::borrow(unlock_numerators, numerator_length - 1) != 0, - error::invalid_argument(ESCHEDULE_WITH_ZERO_FRACTION) + error::invalid_argument(ESCHEDULE_WITH_ZERO_FRACTION), ); let sum = vector::foldr(*unlock_numerators, 0, |e, a| { e + a }); //Sum of numerators can not be greater than denominators assert!( sum <= unlock_denominator, - error::invalid_argument(ENUMERATORS_GRATER_THAN_DENOMINATOR) + error::invalid_argument(ENUMERATORS_GRATER_THAN_DENOMINATOR), ); } @@ -990,53 +1047,53 @@ module supra_framework::pbo_delegation_pool { let ms_admin = option::get_with_default
(&multisig_admin, @0x0); assert!( ms_admin != @0x0, - error::invalid_argument(EADMIN_ADDRESS_CANNOT_BE_ZERO) + error::invalid_argument(EADMIN_ADDRESS_CANNOT_BE_ZERO), ); assert!( multisig_account::num_signatures_required(ms_admin) >= 2, - EADMIN_NOT_MULTISIG + EADMIN_NOT_MULTISIG, ); }; // fail if the length of delegator_address and principle_stake is not the same assert!( vector::length(&delegator_address) == vector::length(&principle_stake), - error::invalid_argument(EVECTOR_LENGTH_NOT_SAME) + error::invalid_argument(EVECTOR_LENGTH_NOT_SAME), ); //Delegation pool must be enabled assert!( features::delegation_pools_enabled(), - error::invalid_state(EDELEGATION_POOLS_DISABLED) + error::invalid_state(EDELEGATION_POOLS_DISABLED), ); - validate_unlock_schedule_params( &unlock_numerators, unlock_denominator, unlock_start_time, - unlock_duration + unlock_duration, ); let owner_address = signer::address_of(owner); assert!( !owner_cap_exists(owner_address), - error::already_exists(EOWNER_CAP_ALREADY_EXISTS) + error::already_exists(EOWNER_CAP_ALREADY_EXISTS), ); assert!( operator_commission_percentage <= MAX_FEE, - error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE) + error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE), ); let sum = vector::fold(principle_stake, 0, |a, e| { a + e }); // fail if the value of coin and the sum of principle_stake is not the same assert!( coin::value(&coin) == sum, - error::invalid_state(ECOIN_VALUE_NOT_SAME_AS_PRINCIPAL_STAKE) + error::invalid_state(ECOIN_VALUE_NOT_SAME_AS_PRINCIPAL_STAKE), ); // generate a seed to be used to create the resource account hosting the delegation pool let seed = create_resource_account_seed(delegation_pool_creation_seed); - let (stake_pool_signer, stake_pool_signer_cap) = - account::create_resource_account(owner, seed); + let (stake_pool_signer, stake_pool_signer_cap) = account::create_resource_account( + owner, seed + ); coin::register(&stake_pool_signer); // stake_pool_signer will be owner of the stake pool and have its `stake::OwnerCapability` @@ -1045,7 +1102,7 @@ module supra_framework::pbo_delegation_pool { &stake_pool_signer, 0, owner_address, - owner_address + owner_address, ); coin::deposit(pool_address, coin); @@ -1053,7 +1110,7 @@ module supra_framework::pbo_delegation_pool { table::add( &mut inactive_shares, olc_with_index(0), - pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR) + pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR), ); let delegator_address_copy = copy delegator_address; @@ -1068,7 +1125,7 @@ module supra_framework::pbo_delegation_pool { }; //Create unlock schedule - let schedule = create_schedule_fractions(&unlock_numerators,unlock_denominator); + let schedule = create_schedule_fractions(&unlock_numerators, unlock_denominator); move_to( &stake_pool_signer, @@ -1105,7 +1162,7 @@ module supra_framework::pbo_delegation_pool { ), distribute_commission_events: account::new_event_handle< DistributeCommissionEvent>(&stake_pool_signer) - } + }, ); // save delegation pool ownership and resource account address (inner stake pool address) on `owner` @@ -1120,15 +1177,13 @@ module supra_framework::pbo_delegation_pool { let (active_stake, _, _, _) = stake::get_stake(pool_address); // fail if coin in StakePool.active does not match with the balance in active_shares pool. assert!( - active_stake - == pool_u64::total_coins( - &borrow_global(pool_address).active_shares - ), - error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL) + active_stake == pool_u64::total_coins( + &borrow_global(pool_address).active_shares, + ), + error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL), ); // All delegation pool enable partial governace voting by default once the feature flag is enabled. - if (features::partial_governance_voting_enabled() - && features::delegation_pool_partial_governance_voting_enabled()) { + if (features::partial_governance_voting_enabled() && features::delegation_pool_partial_governance_voting_enabled()) { enable_partial_governance_voting(pool_address); } } @@ -1142,11 +1197,12 @@ module supra_framework::pbo_delegation_pool { { assert!( is_admin(signer::address_of(funder), pool_address), - error::permission_denied(ENOT_AUTHORIZED) + error::permission_denied(ENOT_AUTHORIZED), ); }; - let principle_stake_table = - &mut (borrow_global_mut(pool_address).principle_stake); + let principle_stake_table = &mut ( + borrow_global_mut(pool_address).principle_stake + ); vector::zip_reverse( delegators, @@ -1157,8 +1213,9 @@ module supra_framework::pbo_delegation_pool { // Compute the actual stake that would be added, `principle_stake` has to be // populated in the table accordingly if (table::contains(principle_stake_table, delegator)) { - let stake_amount = - table::borrow_mut(principle_stake_table, delegator); + let stake_amount = table::borrow_mut( + principle_stake_table, delegator + ); *stake_amount = *stake_amount + stake; } else { table::add(principle_stake_table, delegator, stake); @@ -1170,7 +1227,7 @@ module supra_framework::pbo_delegation_pool { UnlockScheduleApplied { pool_address, delegator, amount: stake } ); } - } + }, ); fund_delegators_with_stake(funder, pool_address, delegators, stakes); @@ -1188,7 +1245,7 @@ module supra_framework::pbo_delegation_pool { stakes, |delegator, stake| { fund_delegator_stake(funder, pool_address, delegator, stake); - } + }, ); } @@ -1212,9 +1269,7 @@ module supra_framework::pbo_delegation_pool { public fun beneficiary_for_operator(operator: address): address acquires BeneficiaryForOperator { if (exists(operator)) { return borrow_global(operator).beneficiary_for_operator - } else { - operator - } + } else { operator } } /// Enable partial governance voting on a stake pool. The voter of this stake pool will be managed by this module. @@ -1224,11 +1279,11 @@ module supra_framework::pbo_delegation_pool { ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { assert!( features::partial_governance_voting_enabled(), - error::invalid_state(EDISABLED_FUNCTION) + error::invalid_state(EDISABLED_FUNCTION), ); assert!( features::delegation_pool_partial_governance_voting_enabled(), - error::invalid_state(EDISABLED_FUNCTION) + error::invalid_state(EDISABLED_FUNCTION), ); assert_delegation_pool_exists(pool_address); // synchronize delegation and stake pools before any user operation. @@ -1255,7 +1310,7 @@ module supra_framework::pbo_delegation_pool { ), delegate_voting_power_events: account::new_event_handle< DelegateVotingPowerEvent>(&stake_pool_signer) - } + }, ); } @@ -1266,7 +1321,7 @@ module supra_framework::pbo_delegation_pool { fun assert_delegation_pool_exists(pool_address: address) { assert!( delegation_pool_exists(pool_address), - error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST) + error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST), ); } @@ -1276,18 +1331,19 @@ module supra_framework::pbo_delegation_pool { let balance = pool_u64::balance(&pool.active_shares, delegator_address); assert!( balance >= MIN_COINS_ON_SHARES_POOL, - error::invalid_argument(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW) + error::invalid_argument(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW), ); } fun assert_min_pending_inactive_balance( pool: &DelegationPool, delegator_address: address ) { - let balance = - pool_u64::balance(pending_inactive_shares_pool(pool), delegator_address); + let balance = pool_u64::balance( + pending_inactive_shares_pool(pool), delegator_address + ); assert!( balance >= MIN_COINS_ON_SHARES_POOL, - error::invalid_argument(EDELEGATOR_PENDING_INACTIVE_BALANCE_TOO_LOW) + error::invalid_argument(EDELEGATOR_PENDING_INACTIVE_BALANCE_TOO_LOW), ); } @@ -1295,7 +1351,7 @@ module supra_framework::pbo_delegation_pool { assert_delegation_pool_exists(pool_address); assert!( partial_governance_voting_enabled(pool_address), - error::invalid_state(EPARTIAL_GOVERNANCE_VOTING_NOT_ENABLED) + error::invalid_state(EPARTIAL_GOVERNANCE_VOTING_NOT_ENABLED), ); } @@ -1303,11 +1359,10 @@ module supra_framework::pbo_delegation_pool { src_shares_pool: &pool_u64::Pool, shareholder: address, amount: u64 ): u64 { // find how many coins would be redeemed if supplying `amount` - let redeemed_coins = - pool_u64::shares_to_amount( - src_shares_pool, - amount_to_shares_to_redeem(src_shares_pool, shareholder, amount) - ); + let redeemed_coins = pool_u64::shares_to_amount( + src_shares_pool, + amount_to_shares_to_redeem(src_shares_pool, shareholder, amount), + ); // if balance drops under threshold then redeem it entirely let src_balance = pool_u64::balance(src_shares_pool, shareholder); if (src_balance - redeemed_coins < MIN_COINS_ON_SHARES_POOL) { @@ -1323,11 +1378,10 @@ module supra_framework::pbo_delegation_pool { amount: u64 ): u64 { // find how many coins would be redeemed from source if supplying `amount` - let redeemed_coins = - pool_u64::shares_to_amount( - src_shares_pool, - amount_to_shares_to_redeem(src_shares_pool, shareholder, amount) - ); + let redeemed_coins = pool_u64::shares_to_amount( + src_shares_pool, + amount_to_shares_to_redeem(src_shares_pool, shareholder, amount), + ); // if balance on destination would be less than threshold then redeem difference to threshold let dst_balance = pool_u64::balance(dst_shares_pool, shareholder); if (dst_balance + redeemed_coins < MIN_COINS_ON_SHARES_POOL) { @@ -1395,9 +1449,7 @@ module supra_framework::pbo_delegation_pool { /// Update VoteDelegation of a delegator to up-to-date then borrow_mut it. fun update_and_borrow_mut_delegator_vote_delegation( - pool: &DelegationPool, - governance_records: &mut GovernanceRecords, - delegator: address + pool: &DelegationPool, governance_records: &mut GovernanceRecords, delegator: address ): &mut VoteDelegation { let pool_address = get_pool_address(pool); let locked_until_secs = stake::get_lockup_secs(pool_address); @@ -1413,14 +1465,14 @@ module supra_framework::pbo_delegation_pool { voter: delegator, last_locked_until_secs: locked_until_secs, pending_voter: delegator - } + }, ) }; let vote_delegation = smart_table::borrow_mut(vote_delegation_table, delegator); // A lockup period has passed since last time `vote_delegation` was updated. Pending voter takes effect. - if (vote_delegation.last_locked_until_secs < locked_until_secs - && vote_delegation.voter != vote_delegation.pending_voter) { + if (vote_delegation.last_locked_until_secs < locked_until_secs && vote_delegation.voter != vote_delegation + .pending_voter) { vote_delegation.voter = vote_delegation.pending_voter; }; vote_delegation @@ -1447,7 +1499,7 @@ module supra_framework::pbo_delegation_pool { pending_inactive_shares: inactive_shares, active_shares_next_lockup: active_shares, last_locked_until_secs: locked_until_secs - } + }, ) }; @@ -1470,28 +1522,23 @@ module supra_framework::pbo_delegation_pool { fun calculate_total_voting_power( delegation_pool: &DelegationPool, latest_delegated_votes: &DelegatedVotes ): u64 { - let active_amount = - pool_u64::shares_to_amount( - &delegation_pool.active_shares, latest_delegated_votes.active_shares - ); - let pending_inactive_amount = - pool_u64::shares_to_amount( - pending_inactive_shares_pool(delegation_pool), - latest_delegated_votes.pending_inactive_shares - ); + let active_amount = pool_u64::shares_to_amount( + &delegation_pool.active_shares, latest_delegated_votes.active_shares + ); + let pending_inactive_amount = pool_u64::shares_to_amount( + pending_inactive_shares_pool(delegation_pool), + latest_delegated_votes.pending_inactive_shares, + ); active_amount + pending_inactive_amount } /// Update VoteDelegation of a delegator to up-to-date then return the latest voter. fun calculate_and_update_delegator_voter_internal( - pool: &DelegationPool, - governance_records: &mut GovernanceRecords, - delegator: address + pool: &DelegationPool, governance_records: &mut GovernanceRecords, delegator: address ): address { - let vote_delegation = - update_and_borrow_mut_delegator_vote_delegation( - pool, governance_records, delegator - ); + let vote_delegation = update_and_borrow_mut_delegator_vote_delegation( + pool, governance_records, delegator + ); vote_delegation.voter } @@ -1499,22 +1546,21 @@ module supra_framework::pbo_delegation_pool { fun calculate_and_update_delegated_votes( pool: &DelegationPool, governance_records: &mut GovernanceRecords, voter: address ): u64 { - let delegated_votes = - update_and_borrow_mut_delegated_votes(pool, governance_records, voter); + let delegated_votes = update_and_borrow_mut_delegated_votes( + pool, governance_records, voter + ); calculate_total_voting_power(pool, delegated_votes) } /// Allows an owner to change the operator of the underlying stake pool. - public entry fun set_operator( - owner: &signer, new_operator: address - ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun set_operator(owner: &signer, new_operator: address) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { let pool_address = get_owned_pool_address(signer::address_of(owner)); // synchronize delegation and stake pools before any user operation // ensure the old operator is paid its uncommitted commission rewards synchronize_delegation_pool(pool_address); stake::set_operator( &retrieve_stake_pool_owner(borrow_global(pool_address)), - new_operator + new_operator, ); } @@ -1527,7 +1573,7 @@ module supra_framework::pbo_delegation_pool { ) acquires BeneficiaryForOperator { assert!( features::operator_beneficiary_change_enabled(), - std::error::invalid_state(EOPERATOR_BENEFICIARY_CHANGE_NOT_SUPPORTED) + std::error::invalid_state(EOPERATOR_BENEFICIARY_CHANGE_NOT_SUPPORTED), ); // The beneficiay address of an operator is stored under the operator's address. // So, the operator does not need to be validated with respect to a staking pool. @@ -1535,11 +1581,11 @@ module supra_framework::pbo_delegation_pool { let old_beneficiary = beneficiary_for_operator(operator_addr); if (exists(operator_addr)) { borrow_global_mut(operator_addr).beneficiary_for_operator = - new_beneficiary; + new_beneficiary; } else { move_to( operator, - BeneficiaryForOperator { beneficiary_for_operator: new_beneficiary } + BeneficiaryForOperator { beneficiary_for_operator: new_beneficiary }, ); }; @@ -1548,7 +1594,7 @@ module supra_framework::pbo_delegation_pool { operator: operator_addr, old_beneficiary, new_beneficiary - } + }, ); } @@ -1558,23 +1604,21 @@ module supra_framework::pbo_delegation_pool { ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { assert!( features::commission_change_delegation_pool_enabled(), - error::invalid_state(ECOMMISSION_RATE_CHANGE_NOT_SUPPORTED) + error::invalid_state(ECOMMISSION_RATE_CHANGE_NOT_SUPPORTED), ); assert!( new_commission_percentage <= MAX_FEE, - error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE) + error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE), ); let owner_address = signer::address_of(owner); let pool_address = get_owned_pool_address(owner_address); assert!( - operator_commission_percentage(pool_address) + MAX_COMMISSION_INCREASE - >= new_commission_percentage, - error::invalid_argument(ETOO_LARGE_COMMISSION_INCREASE) + operator_commission_percentage(pool_address) + MAX_COMMISSION_INCREASE >= new_commission_percentage, + error::invalid_argument(ETOO_LARGE_COMMISSION_INCREASE), ); assert!( - stake::get_remaining_lockup_secs(pool_address) - >= min_remaining_secs_for_commission_change(), - error::invalid_state(ETOO_LATE_COMMISSION_CHANGE) + stake::get_remaining_lockup_secs(pool_address) >= min_remaining_secs_for_commission_change(), + error::invalid_state(ETOO_LATE_COMMISSION_CHANGE), ); // synchronize delegation and stake pools before any user operation. this ensures: @@ -1583,24 +1627,24 @@ module supra_framework::pbo_delegation_pool { synchronize_delegation_pool(pool_address); if (exists(pool_address)) { - let commission_percentage = - borrow_global_mut(pool_address); + let commission_percentage = borrow_global_mut( + pool_address + ); commission_percentage.commission_percentage_next_lockup_cycle = new_commission_percentage; commission_percentage.effective_after_secs = stake::get_lockup_secs( pool_address ); } else { let delegation_pool = borrow_global(pool_address); - let pool_signer = - account::create_signer_with_capability( - &delegation_pool.stake_pool_signer_cap - ); + let pool_signer = account::create_signer_with_capability( + &delegation_pool.stake_pool_signer_cap + ); move_to( &pool_signer, NextCommissionPercentage { commission_percentage_next_lockup_cycle: new_commission_percentage, effective_after_secs: stake::get_lockup_secs(pool_address) - } + }, ); }; @@ -1609,7 +1653,7 @@ module supra_framework::pbo_delegation_pool { pool_address, owner: owner_address, commission_percentage_next_lockup_cycle: new_commission_percentage - } + }, ); } @@ -1620,14 +1664,14 @@ module supra_framework::pbo_delegation_pool { // No one can change delegated_voter once the partial governance voting feature is enabled. assert!( !features::delegation_pool_partial_governance_voting_enabled(), - error::invalid_state(EDEPRECATED_FUNCTION) + error::invalid_state(EDEPRECATED_FUNCTION), ); let pool_address = get_owned_pool_address(signer::address_of(owner)); // synchronize delegation and stake pools before any user operation synchronize_delegation_pool(pool_address); stake::set_delegated_voter( &retrieve_stake_pool_owner(borrow_global(pool_address)), - new_voter + new_voter, ); } @@ -1644,30 +1688,28 @@ module supra_framework::pbo_delegation_pool { let delegator_address = signer::address_of(delegator); let delegation_pool = borrow_global(pool_address); let governance_records = borrow_global_mut(pool_address); - let delegator_vote_delegation = - update_and_borrow_mut_delegator_vote_delegation( - delegation_pool, governance_records, delegator_address - ); + let delegator_vote_delegation = update_and_borrow_mut_delegator_vote_delegation( + delegation_pool, governance_records, delegator_address + ); let pending_voter: address = delegator_vote_delegation.pending_voter; // No need to update if the voter doesn't really change. if (pending_voter != new_voter) { delegator_vote_delegation.pending_voter = new_voter; - let active_shares = - get_delegator_active_shares(delegation_pool, delegator_address); + let active_shares = get_delegator_active_shares( + delegation_pool, delegator_address + ); // of -= // of += - let pending_delegated_votes = - update_and_borrow_mut_delegated_votes( - delegation_pool, governance_records, pending_voter - ); + let pending_delegated_votes = update_and_borrow_mut_delegated_votes( + delegation_pool, governance_records, pending_voter + ); pending_delegated_votes.active_shares_next_lockup = pending_delegated_votes.active_shares_next_lockup - active_shares; - let new_delegated_votes = - update_and_borrow_mut_delegated_votes( - delegation_pool, governance_records, new_voter - ); + let new_delegated_votes = update_and_borrow_mut_delegated_votes( + delegation_pool, governance_records, new_voter + ); new_delegated_votes.active_shares_next_lockup = new_delegated_votes.active_shares_next_lockup + active_shares; }; @@ -1678,7 +1720,7 @@ module supra_framework::pbo_delegation_pool { pool_address, delegator: delegator_address, voter: new_voter - } + }, ); } @@ -1708,7 +1750,7 @@ module supra_framework::pbo_delegation_pool { // fail unlock of less than `MIN_COINS_ON_SHARES_POOL` assert!( amount >= MIN_COINS_ON_SHARES_POOL, - error::invalid_argument(EMINIMUM_UNLOCK_AMOUNT) + error::invalid_argument(EMINIMUM_UNLOCK_AMOUNT), ); // synchronize delegation and stake pools before any user operation synchronize_delegation_pool(pool_address); @@ -1739,7 +1781,7 @@ module supra_framework::pbo_delegation_pool { delegator_address, amount_added: amount, add_stake_fee - } + }, ); } @@ -1752,7 +1794,7 @@ module supra_framework::pbo_delegation_pool { delegator, pool_address, signer::address_of(delegator), - amount + amount, ) } @@ -1786,7 +1828,7 @@ module supra_framework::pbo_delegation_pool { // fail unlock of less than `MIN_COINS_ON_SHARES_POOL` assert!( amount >= MIN_COINS_ON_SHARES_POOL, - error::invalid_argument(EMINIMUM_UNLOCK_AMOUNT) + error::invalid_argument(EMINIMUM_UNLOCK_AMOUNT), ); // synchronize delegation and stake pools before any user operation synchronize_delegation_pool(pool_address); @@ -1797,7 +1839,7 @@ module supra_framework::pbo_delegation_pool { pending_inactive_shares_pool(pool), &pool.active_shares, delegator, - amount + amount, ); let observed_lockup_cycle = pool.observed_lockup_cycle; amount = redeem_inactive_shares(pool, delegator, amount, observed_lockup_cycle); @@ -1813,7 +1855,7 @@ module supra_framework::pbo_delegation_pool { pool_address, delegator_address: delegator, amount_reactivated: amount - } + }, ); } @@ -1834,7 +1876,7 @@ module supra_framework::pbo_delegation_pool { { assert!( is_admin(signer::address_of(multisig_admin), pool_address), - error::permission_denied(ENOT_AUTHORIZED) + error::permission_denied(ENOT_AUTHORIZED), ); }; assert!(amount != 0, error::invalid_argument(EWITHDRAW_ZERO_STAKE)); @@ -1842,8 +1884,34 @@ module supra_framework::pbo_delegation_pool { borrow_global_mut(pool_address), delegator_address, amount, - signer::address_of(multisig_admin) + signer::address_of(multisig_admin), + ); + } + + public entry fun admin_increase_last_unlock_period( + multisig_admin: &signer, pool_address: address, additional_periods: u64 + ) acquires DelegationPool { + // Ensure that the caller is the admin of the delegation pool. + { + assert!( + is_admin(signer::address_of(multisig_admin), pool_address), + error::permission_denied(ENOT_AUTHORIZED), + ); + }; + + let delegation_pool = borrow_global_mut(pool_address); + let last_unlocked_period = delegation_pool.principle_unlock_schedule.last_unlock_period; + let schedule_length = vector::length( + &delegation_pool.principle_unlock_schedule.schedule ); + // Current last_unlock_period must be greater or equal to schedule_length -1, this is because + // last_unlock_period is used as index into schedule vector. If we are not already at the last index or beyond + // increasing this would have undesirable effect. For example if schedule is [20%, 30%, 10%] and + // last_unlock_period = 1, increasing it by two would directly go to 10% unlock skipping 30% unlock part + assert!(schedule_length - 1 <= last_unlocked_period, EINVALID_STATE_FOR_OPERATION); + delegation_pool.principle_unlock_schedule.last_unlock_period = delegation_pool.principle_unlock_schedule + .last_unlock_period + additional_periods; + } /// Updates the `principle_stake` of each `delegator` in `delegators` according to the amount specified @@ -1865,7 +1933,7 @@ module supra_framework::pbo_delegation_pool { { assert!( is_admin(signer::address_of(multisig_admin), pool_address), - error::permission_denied(ENOT_AUTHORIZED) + error::permission_denied(ENOT_AUTHORIZED), ); }; @@ -1878,8 +1946,9 @@ module supra_framework::pbo_delegation_pool { delegators, new_principle_stakes, |delegator, principle_stake| { - let (active, inactive, pending_inactive) = - get_stake(pool_address, delegator); + let (active, inactive, pending_inactive) = get_stake( + pool_address, delegator + ); // Ensure that all stake to be locked is made `active`. if (active < principle_stake) { @@ -1906,8 +1975,7 @@ module supra_framework::pbo_delegation_pool { if (active_and_pending_inactive < principle_stake) { // Need to reactivate some of the `inactive` stake. - let amount_to_withdraw = - principle_stake - active_and_pending_inactive; + let amount_to_withdraw = principle_stake - active_and_pending_inactive; // Ensure that we do not try to withdraw more stake than the `inactive` stake. if (amount_to_withdraw > inactive) { @@ -1920,14 +1988,14 @@ module supra_framework::pbo_delegation_pool { multisig_admin, pool_address, delegator, - amount_to_withdraw + amount_to_withdraw, ); // Then allocate it to the delegator again. fund_delegator_stake( multisig_admin, pool_address, delegator, - amount_to_withdraw + amount_to_withdraw, ); } } @@ -1935,17 +2003,18 @@ module supra_framework::pbo_delegation_pool { // else: The amount to lock can be covered by the currently `active` stake. // Update the delegator's principle stake and record the details of the lockup event. - let principle_stake_table = - &mut (borrow_global_mut(pool_address).principle_stake); + let principle_stake_table = &mut ( + borrow_global_mut(pool_address).principle_stake + ); table::upsert(principle_stake_table, delegator, principle_stake); event::emit( UnlockScheduleApplied { pool_address, delegator, amount: principle_stake - } + }, ); - } + }, ); } @@ -1969,24 +2038,24 @@ module supra_framework::pbo_delegation_pool { let admin_addr = signer::address_of(multisig_admin); assert!( is_admin(admin_addr, pool_address), - error::permission_denied(ENOT_AUTHORIZED) + error::permission_denied(ENOT_AUTHORIZED), ); //Ensure replacement address is different assert!( old_delegator != new_delegator, - error::invalid_argument(ENEW_IS_SAME_AS_OLD_DELEGATOR) + error::invalid_argument(ENEW_IS_SAME_AS_OLD_DELEGATOR), ); //Ensure it is a valid `pool_addres` assert!( exists(pool_address), - error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST) + error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST), ); let pool: &mut DelegationPool = borrow_global_mut(pool_address); //Ensure `old_delegator` is part of original principle stakers before commencing the replacement assert!( table::contains(&pool.principle_stake, old_delegator), - error::unavailable(EDELEGATOR_DOES_NOT_EXIST) + error::unavailable(EDELEGATOR_DOES_NOT_EXIST), ); //replace in `active_shares` pool @@ -1997,22 +2066,24 @@ module supra_framework::pbo_delegation_pool { active_pool, old_delegator, new_delegator, - active_shares + active_shares, ); }; //replace in `inactive_shares` pool - let (withdrawal_exists, withdrawal_olc) = - pending_withdrawal_exists(pool, old_delegator); + let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists( + pool, old_delegator + ); if (withdrawal_exists) { - let inactive_pool = - table::borrow_mut(&mut pool.inactive_shares, withdrawal_olc); + let inactive_pool = table::borrow_mut( + &mut pool.inactive_shares, withdrawal_olc + ); let inactive_shares = pool_u64::shares(inactive_pool, old_delegator); pool_u64::transfer_shares( inactive_pool, old_delegator, new_delegator, - inactive_shares + inactive_shares, ); //replace in `pending_withdrawals` @@ -2046,12 +2117,12 @@ module supra_framework::pbo_delegation_pool { VotingRecordKey { voter: new_delegator, proposal_id: proposal_id - } + }, ); vector::push_back(&mut old_keys, *key); }; - } + }, ); vector::zip_ref( @@ -2059,7 +2130,7 @@ module supra_framework::pbo_delegation_pool { &new_keys, |old, new| { replace_in_smart_tables(&mut grecords.votes, *old, *new); - } + }, ); } }; @@ -2103,31 +2174,31 @@ module supra_framework::pbo_delegation_pool { ): u64 acquires DelegationPool { assert!( exists(pool_addr), - error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST) + error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST), ); let pool = borrow_global(pool_addr); - let delegator_active_balance = - pool_u64::balance(&pool.active_shares, delegator_addr); - let unlockable_fraction = - pool.principle_unlock_schedule.cumulative_unlocked_fraction; - let delegator_principle_stake = - *table::borrow(&pool.principle_stake, delegator_addr); + let delegator_active_balance = pool_u64::balance( + &pool.active_shares, delegator_addr + ); + let unlockable_fraction = pool.principle_unlock_schedule.cumulative_unlocked_fraction; + let delegator_principle_stake = *table::borrow( + &pool.principle_stake, delegator_addr + ); //To avoid problem even if fraction is slightly above 1 - let unlockable_principle_stake = - ( - math128::min( - fixed_point64::multiply_u128( - (delegator_principle_stake as u128), unlockable_fraction - ), - (delegator_principle_stake as u128) - ) as u64 - ); + let unlockable_principle_stake = ( + math128::min( + fixed_point64::multiply_u128( + (delegator_principle_stake as u128), unlockable_fraction + ), + (delegator_principle_stake as u128), + ) as u64 + ); let locked_amount = delegator_principle_stake - unlockable_principle_stake; assert!( delegator_active_balance >= locked_amount, - error::invalid_state(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW) + error::invalid_state(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW), ); delegator_active_balance - locked_amount @@ -2139,58 +2210,62 @@ module supra_framework::pbo_delegation_pool { delegator_addr: address, pool_address: address, amount: u64 ): bool acquires DelegationPool { - let principle_stake_table = - &borrow_global(pool_address).principle_stake; + let principle_stake_table = &borrow_global(pool_address).principle_stake; if (!table::contains(principle_stake_table, delegator_addr)) { return false }; - let unlock_schedule = - &mut borrow_global_mut(pool_address).principle_unlock_schedule; + let unlock_schedule = &mut borrow_global_mut(pool_address).principle_unlock_schedule; let one = fixed_point64::create_from_rational(1, 1); if (fixed_point64::greater_or_equal( - unlock_schedule.cumulative_unlocked_fraction, one - )) { + unlock_schedule.cumulative_unlocked_fraction, one + )) { return true }; if (unlock_schedule.start_timestamp_secs > timestamp::now_seconds()) { - let unlockable_amount = - cached_unlockable_balance(delegator_addr, pool_address); + let unlockable_amount = cached_unlockable_balance( + delegator_addr, pool_address + ); return amount <= unlockable_amount }; //subtraction safety due to check above - let unlock_periods_passed = - (timestamp::now_seconds() - unlock_schedule.start_timestamp_secs) - / unlock_schedule.period_duration; + let unlock_periods_passed = ( + timestamp::now_seconds() - unlock_schedule.start_timestamp_secs + ) / unlock_schedule.period_duration; let last_unlocked_period = unlock_schedule.last_unlock_period; let schedule_length = vector::length(&unlock_schedule.schedule); let cfraction = unlock_schedule.cumulative_unlocked_fraction; while (last_unlocked_period < unlock_periods_passed && fixed_point64::less(cfraction, one) && last_unlocked_period < schedule_length) { - let next_fraction = - *vector::borrow(&unlock_schedule.schedule, last_unlocked_period); + let next_fraction = *vector::borrow( + &unlock_schedule.schedule, last_unlocked_period + ); cfraction = fixed_point64::add(cfraction, next_fraction); last_unlocked_period = last_unlocked_period + 1; }; - if (last_unlocked_period < unlock_periods_passed - && fixed_point64::less(cfraction, one)) { - let final_fraction = - *vector::borrow(&unlock_schedule.schedule, schedule_length - 1); + if (last_unlocked_period < unlock_periods_passed && fixed_point64::less( + cfraction, one + )) { + let final_fraction = *vector::borrow( + &unlock_schedule.schedule, schedule_length - 1 + ); // Acclerate calculation to current period and don't update last_unlocked_period since it is not used anymore cfraction = fixed_point64::add( cfraction, fixed_point64::multiply_u128_return_fixpoint64( (unlock_periods_passed - last_unlocked_period as u128), - final_fraction - ) + final_fraction, + ), ); cfraction = fixed_point64::min(cfraction, one); }; unlock_schedule.cumulative_unlocked_fraction = cfraction; - unlock_schedule.last_unlock_period = unlock_periods_passed; + unlock_schedule.last_unlock_period = math64::max( + unlock_periods_passed, last_unlocked_period + ); let unlockable_amount = cached_unlockable_balance(delegator_addr, pool_address); amount <= unlockable_amount } @@ -2205,13 +2280,13 @@ module supra_framework::pbo_delegation_pool { // fail unlock of less than `MIN_COINS_ON_SHARES_POOL` assert!( amount >= MIN_COINS_ON_SHARES_POOL, - error::invalid_argument(EMINIMUM_UNLOCK_AMOUNT) + error::invalid_argument(EMINIMUM_UNLOCK_AMOUNT), ); // fail unlock of more stake than `active` on the stake pool let (active, _, _, _) = stake::get_stake(pool_address); assert!( amount <= active, - error::invalid_argument(ENOT_ENOUGH_ACTIVE_STAKE_TO_UNLOCK) + error::invalid_argument(ENOT_ENOUGH_ACTIVE_STAKE_TO_UNLOCK), ); // synchronize delegation and stake pools before any user operation @@ -2222,7 +2297,7 @@ module supra_framework::pbo_delegation_pool { if (is_principle_stakeholder(delegator_address, pool_address)) { assert!( can_principle_unlock(delegator_address, pool_address, amount), - error::invalid_argument(EAMOUNT_REQUESTED_NOT_UNLOCKABLE) + error::invalid_argument(EAMOUNT_REQUESTED_NOT_UNLOCKABLE), ); }; let pool = borrow_global_mut(pool_address); @@ -2230,7 +2305,7 @@ module supra_framework::pbo_delegation_pool { &pool.active_shares, pending_inactive_shares_pool(pool), delegator_address, - amount + amount, ); amount = redeem_active_shares(pool, delegator_address, amount); stake::unlock(&retrieve_stake_pool_owner(pool), amount); @@ -2240,12 +2315,12 @@ module supra_framework::pbo_delegation_pool { event::emit_event( &mut pool.unlock_stake_events, - UnlockStakeEvent { pool_address, delegator_address, amount_unlocked: amount } + UnlockStakeEvent { pool_address, delegator_address, amount_unlocked: amount }, ); let (active_stake, _, pending_active, _) = stake::get_stake(pool_address); assert!( active_stake + pending_active == pool_u64::total_coins(&pool.active_shares), - error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL) + error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL), ); } @@ -2269,7 +2344,7 @@ module supra_framework::pbo_delegation_pool { borrow_global_mut(pool_address), delegator_address, amount, - delegator_address + delegator_address, ); } @@ -2286,29 +2361,31 @@ module supra_framework::pbo_delegation_pool { if (amount == 0) { return }; let pool_address = get_pool_address(pool); - let (withdrawal_exists, withdrawal_olc) = - pending_withdrawal_exists(pool, delegator_address); + let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists( + pool, delegator_address + ); // exit if no withdrawal or (it is pending and cannot withdraw pending_inactive stake from stake pool) if (!( - withdrawal_exists + withdrawal_exists && ( - withdrawal_olc.index < pool.observed_lockup_cycle.index - || can_withdraw_pending_inactive(pool_address) + withdrawal_olc.index < pool.observed_lockup_cycle.index || can_withdraw_pending_inactive( + pool_address + ) ) - )) { return }; + )) { return }; if (withdrawal_olc.index == pool.observed_lockup_cycle.index) { amount = coins_to_redeem_to_ensure_min_stake( pending_inactive_shares_pool(pool), delegator_address, - amount + amount, ) }; amount = redeem_inactive_shares( pool, delegator_address, amount, - withdrawal_olc + withdrawal_olc, ); let stake_pool_owner = &retrieve_stake_pool_owner(pool); @@ -2340,7 +2417,7 @@ module supra_framework::pbo_delegation_pool { event::emit_event( &mut pool.withdraw_stake_events, - WithdrawStakeEvent { pool_address, delegator_address, amount_withdrawn: amount } + WithdrawStakeEvent { pool_address, delegator_address, amount_withdrawn: amount }, ); } @@ -2352,9 +2429,7 @@ module supra_framework::pbo_delegation_pool { ): (bool, ObservedLockupCycle) { if (table::contains(&pool.pending_withdrawals, delegator_address)) { (true, *table::borrow(&pool.pending_withdrawals, delegator_address)) - } else { - (false, olc_with_index(0)) - } + } else { (false, olc_with_index(0)) } } /// Return a mutable reference to the shares pool of `pending_inactive` stake on the @@ -2375,15 +2450,15 @@ module supra_framework::pbo_delegation_pool { fun execute_pending_withdrawal( pool: &mut DelegationPool, delegator_address: address ) acquires GovernanceRecords { - let (withdrawal_exists, withdrawal_olc) = - pending_withdrawal_exists(pool, delegator_address); - if (withdrawal_exists - && withdrawal_olc.index < pool.observed_lockup_cycle.index) { + let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists( + pool, delegator_address + ); + if (withdrawal_exists && withdrawal_olc.index < pool.observed_lockup_cycle.index) { withdraw_internal( pool, delegator_address, MAX_U64, - delegator_address + delegator_address, ); } } @@ -2418,10 +2493,9 @@ module supra_framework::pbo_delegation_pool { fun buy_in_pending_inactive_shares( pool: &mut DelegationPool, shareholder: address, coins_amount: u64 ): u128 acquires GovernanceRecords { - let new_shares = - pool_u64::amount_to_shares( - pending_inactive_shares_pool(pool), coins_amount - ); + let new_shares = pool_u64::amount_to_shares( + pending_inactive_shares_pool(pool), coins_amount + ); // never create a new pending withdrawal unless delegator owns some pending_inactive shares if (new_shares == 0) { return 0 @@ -2449,7 +2523,7 @@ module supra_framework::pbo_delegation_pool { *table::borrow_mut_with_default( &mut pool.pending_withdrawals, shareholder, observed_lockup_cycle ) == observed_lockup_cycle, - error::invalid_state(EPENDING_WITHDRAWAL_EXISTS) + error::invalid_state(EPENDING_WITHDRAWAL_EXISTS), ); new_shares @@ -2475,8 +2549,9 @@ module supra_framework::pbo_delegation_pool { fun redeem_active_shares( pool: &mut DelegationPool, shareholder: address, coins_amount: u64 ): u64 acquires GovernanceRecords { - let shares_to_redeem = - amount_to_shares_to_redeem(&pool.active_shares, shareholder, coins_amount); + let shares_to_redeem = amount_to_shares_to_redeem( + &pool.active_shares, shareholder, coins_amount + ); // silently exit if not a shareholder otherwise redeem would fail with `ESHAREHOLDER_NOT_FOUND` if (shares_to_redeem == 0) return 0; @@ -2487,7 +2562,7 @@ module supra_framework::pbo_delegation_pool { pool, pool_address, shares_to_redeem, - shareholder + shareholder, ); }; @@ -2506,32 +2581,32 @@ module supra_framework::pbo_delegation_pool { coins_amount: u64, lockup_cycle: ObservedLockupCycle ): u64 acquires GovernanceRecords { - let shares_to_redeem = - amount_to_shares_to_redeem( - table::borrow(&pool.inactive_shares, lockup_cycle), - shareholder, - coins_amount - ); + let shares_to_redeem = amount_to_shares_to_redeem( + table::borrow(&pool.inactive_shares, lockup_cycle), + shareholder, + coins_amount, + ); // silently exit if not a shareholder otherwise redeem would fail with `ESHAREHOLDER_NOT_FOUND` if (shares_to_redeem == 0) return 0; // Always update governance records before any change to the shares pool. let pool_address = get_pool_address(pool); // Only redeem shares from the pending_inactive pool at `lockup_cycle` == current OLC. - if (partial_governance_voting_enabled(pool_address) - && lockup_cycle.index == pool.observed_lockup_cycle.index) { + if (partial_governance_voting_enabled(pool_address) && lockup_cycle.index == pool.observed_lockup_cycle + .index) { update_governanace_records_for_redeem_pending_inactive_shares( pool, pool_address, shares_to_redeem, - shareholder + shareholder, ); }; let inactive_shares = table::borrow_mut(&mut pool.inactive_shares, lockup_cycle); // 1. reaching here means delegator owns inactive/pending_inactive shares at OLC `lockup_cycle` - let redeemed_coins = - pool_u64::redeem_shares(inactive_shares, shareholder, shares_to_redeem); + let redeemed_coins = pool_u64::redeem_shares( + inactive_shares, shareholder, shares_to_redeem + ); // if entirely reactivated pending_inactive stake or withdrawn inactive one, // re-enable unlocking for delegator by deleting this pending withdrawal @@ -2541,8 +2616,9 @@ module supra_framework::pbo_delegation_pool { table::remove(&mut pool.pending_withdrawals, shareholder); }; // destroy inactive shares pool of past OLC if all its stake has been withdrawn - if (lockup_cycle.index < pool.observed_lockup_cycle.index - && total_coins(inactive_shares) == 0) { + if (lockup_cycle.index < pool.observed_lockup_cycle.index && total_coins( + inactive_shares + ) == 0) { pool_u64::destroy_empty( table::remove(&mut pool.inactive_shares, lockup_cycle) ); @@ -2555,11 +2631,12 @@ module supra_framework::pbo_delegation_pool { /// capture the rewards earned in the meantime, resulted operator commission and /// whether the lockup expired on the stake pool. fun calculate_stake_pool_drift(pool: &DelegationPool): (bool, u64, u64, u64, u64) { - let (active, inactive, pending_active, pending_inactive) = - stake::get_stake(get_pool_address(pool)); + let (active, inactive, pending_active, pending_inactive) = stake::get_stake( + get_pool_address(pool) + ); assert!( inactive >= pool.total_coins_inactive, - error::invalid_state(ESLASHED_INACTIVE_STAKE_ON_PAST_OLC) + error::invalid_state(ESLASHED_INACTIVE_STAKE_ON_PAST_OLC), ); // determine whether a new lockup cycle has been ended on the stake pool and // inactivated SOME `pending_inactive` stake which should stop earning rewards now, @@ -2590,8 +2667,7 @@ module supra_framework::pbo_delegation_pool { ) } else { // handle any slashing applied to `active` stake - 0 - }; + 0 }; // operator `pending_inactive` rewards not persisted yet to the pending_inactive shares pool let pool_pending_inactive = total_coins(pending_inactive_shares_pool(pool)); let commission_pending_inactive = @@ -2599,12 +2675,11 @@ module supra_framework::pbo_delegation_pool { math64::mul_div( pending_inactive - pool_pending_inactive, pool.operator_commission_percentage, - MAX_FEE + MAX_FEE, ) } else { // handle any slashing applied to `pending_inactive` stake - 0 - }; + 0 }; ( lockup_cycle_ended, @@ -2617,9 +2692,7 @@ module supra_framework::pbo_delegation_pool { /// Synchronize delegation and stake pools: distribute yet-undetected rewards to the corresponding internal /// shares pools, assign commission to operator and eventually prepare delegation pool for a new lockup cycle. - public entry fun synchronize_delegation_pool( - pool_address: address - ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun synchronize_delegation_pool(pool_address: address) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { assert_delegation_pool_exists(pool_address); let pool = borrow_global_mut(pool_address); let ( @@ -2645,25 +2718,24 @@ module supra_framework::pbo_delegation_pool { // update total coins accumulated by `active` + `pending_active` shares // redeemed `add_stake` fees are restored and distributed to the rest of the pool as rewards - pool_u64::update_total_coins(&mut pool.active_shares, active - - commission_active); + pool_u64::update_total_coins(&mut pool.active_shares, active - commission_active); // update total coins accumulated by `pending_inactive` shares at current observed lockup cycle pool_u64::update_total_coins( pending_inactive_shares_pool_mut(pool), - pending_inactive - commission_pending_inactive + pending_inactive - commission_pending_inactive, ); // reward operator its commission out of uncommitted active rewards (`add_stake` fees already excluded) buy_in_active_shares( pool, beneficiary_for_operator(stake::get_operator(pool_address)), - commission_active + commission_active, ); // reward operator its commission out of uncommitted pending_inactive rewards buy_in_pending_inactive_shares( pool, beneficiary_for_operator(stake::get_operator(pool_address)), - commission_pending_inactive + commission_pending_inactive, ); event::emit_event( @@ -2673,7 +2745,7 @@ module supra_framework::pbo_delegation_pool { operator: stake::get_operator(pool_address), commission_active, commission_pending_inactive - } + }, ); if (features::operator_beneficiary_change_enabled()) { @@ -2686,7 +2758,7 @@ module supra_framework::pbo_delegation_pool { ), commission_active, commission_pending_inactive - } + }, ) }; @@ -2702,7 +2774,7 @@ module supra_framework::pbo_delegation_pool { table::add( &mut pool.inactive_shares, pool.observed_lockup_cycle, - pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR) + pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR), ); }; @@ -2723,26 +2795,22 @@ module supra_framework::pbo_delegation_pool { // of += // of += let governance_records = borrow_global_mut(pool_address); - let vote_delegation = - update_and_borrow_mut_delegator_vote_delegation( - pool, governance_records, shareholder - ); + let vote_delegation = update_and_borrow_mut_delegator_vote_delegation( + pool, governance_records, shareholder + ); let current_voter = vote_delegation.voter; let pending_voter = vote_delegation.pending_voter; - let current_delegated_votes = - update_and_borrow_mut_delegated_votes( - pool, governance_records, current_voter - ); - current_delegated_votes.active_shares = current_delegated_votes.active_shares - + new_shares; + let current_delegated_votes = update_and_borrow_mut_delegated_votes( + pool, governance_records, current_voter + ); + current_delegated_votes.active_shares = current_delegated_votes.active_shares + new_shares; if (pending_voter == current_voter) { current_delegated_votes.active_shares_next_lockup = current_delegated_votes.active_shares_next_lockup + new_shares; } else { - let pending_delegated_votes = - update_and_borrow_mut_delegated_votes( - pool, governance_records, pending_voter - ); + let pending_delegated_votes = update_and_borrow_mut_delegated_votes( + pool, governance_records, pending_voter + ); pending_delegated_votes.active_shares_next_lockup = pending_delegated_votes.active_shares_next_lockup + new_shares; }; @@ -2758,14 +2826,12 @@ module supra_framework::pbo_delegation_pool { // of += // no impact on of let governance_records = borrow_global_mut(pool_address); - let current_voter = - calculate_and_update_delegator_voter_internal( - pool, governance_records, shareholder - ); - let current_delegated_votes = - update_and_borrow_mut_delegated_votes( - pool, governance_records, current_voter - ); + let current_voter = calculate_and_update_delegator_voter_internal( + pool, governance_records, shareholder + ); + let current_delegated_votes = update_and_borrow_mut_delegated_votes( + pool, governance_records, current_voter + ); current_delegated_votes.pending_inactive_shares = current_delegated_votes.pending_inactive_shares + new_shares; } @@ -2780,26 +2846,22 @@ module supra_framework::pbo_delegation_pool { // of -= // of -= let governance_records = borrow_global_mut(pool_address); - let vote_delegation = - update_and_borrow_mut_delegator_vote_delegation( - pool, governance_records, shareholder - ); + let vote_delegation = update_and_borrow_mut_delegator_vote_delegation( + pool, governance_records, shareholder + ); let current_voter = vote_delegation.voter; let pending_voter = vote_delegation.pending_voter; - let current_delegated_votes = - update_and_borrow_mut_delegated_votes( - pool, governance_records, current_voter - ); - current_delegated_votes.active_shares = current_delegated_votes.active_shares - - shares_to_redeem; + let current_delegated_votes = update_and_borrow_mut_delegated_votes( + pool, governance_records, current_voter + ); + current_delegated_votes.active_shares = current_delegated_votes.active_shares - shares_to_redeem; if (current_voter == pending_voter) { current_delegated_votes.active_shares_next_lockup = current_delegated_votes.active_shares_next_lockup - shares_to_redeem; } else { - let pending_delegated_votes = - update_and_borrow_mut_delegated_votes( - pool, governance_records, pending_voter - ); + let pending_delegated_votes = update_and_borrow_mut_delegated_votes( + pool, governance_records, pending_voter + ); pending_delegated_votes.active_shares_next_lockup = pending_delegated_votes.active_shares_next_lockup - shares_to_redeem; }; @@ -2815,14 +2877,12 @@ module supra_framework::pbo_delegation_pool { // of -= // no impact on of let governance_records = borrow_global_mut(pool_address); - let current_voter = - calculate_and_update_delegator_voter_internal( - pool, governance_records, shareholder - ); - let current_delegated_votes = - update_and_borrow_mut_delegated_votes( - pool, governance_records, current_voter - ); + let current_voter = calculate_and_update_delegator_voter_internal( + pool, governance_records, shareholder + ); + let current_delegated_votes = update_and_borrow_mut_delegated_votes( + pool, governance_records, current_voter + ); current_delegated_votes.pending_inactive_shares = current_delegated_votes.pending_inactive_shares - shares_to_redeem; } @@ -2841,7 +2901,7 @@ module supra_framework::pbo_delegation_pool { use supra_framework::timestamp::fast_forward_seconds; #[test_only] - const CONSENSUS_KEY_1: vector = x"c1bd3bcb387e4ee9a909f6304a1c9902661b0ecfb1e148c7892b210c7f353dfd"; + const CONSENSUS_KEY_1: vector = x"20ed28c35dc60a6c9629a7eb0a8dfa815c85c6cf2cedc9e43314cc26f02d741dc430b40c7239278dae17d68d06950d51ce61c2c16c032ceea62c9715611be7f577f48525ad610432bb5d13fa5826fc07c6650000000000000080090192000000000000007bb0b330cbdcec145d2671ef2532bb7a856a5155c66d7ad89ef2cb65e854fc08a5d43cd159a7abc77adfee05e764ec9abdfc133db8e8621398dcbe53db1069de56405f02a1347d5399502fe849b44cfa673ad95bdbf33b417f3f8e4fa854b87b4a60eff6426b277d6036ffc0cfcdd25c971d53c2b612ed1df66f33eff839c0064ac16d7e04650d13984b08b2f9e7bb240fe3ff920000000000000014a973f3c74f41cecc3c596a125835264d72803ba1ef9c9270fa2228e8f8442889f20ddfffc60bc073758c3fd13a29219ad4532c512d2a97c3a8421dedfa41e4d8d9ffaa3581049a65a64f57ea533ab831c88527bb3d7ce46b6eebd6fef6d3303cf7716455381c74da2bcbfc3e02de2e5fadb014ed4f7ecf6b62a4ce6c0db90b91f084512a18be5cb8892b1615a7bb7ef35d0192000000000000008c49908494889c8d07e0b6f0cb6871aaf7e97506476d0a63530ce06b58928225a4292dff8ffaccd4f217fd65c2afbac848ac5d5957d15aa83fb8d2f261d85ddf4f16feee49d07f274dd421f84862bd73634925c41d2b470066d751732cc4f9630e886df15e63f962959c8f765b48434b6124fe051c2a02ba91bd94a7d8fc3cf7240ffba508ff73d8bb95a8ba661fa59ed9c9b8030000000000000192000000000000007bb0b330cbdcec145d2671ef2532bb7a856a5155c66d7ad89ef2cb65e854fc08a5d43cd159a7abc77adfee05e764ec9abdfc133db8e8621398dcbe53db1069de56405f02a1347d5399502fe849b44cfa673ad95bdbf33b417f3f8e4fa854b87b4a60eff6426b277d6036ffc0cfcdd25c971d53c2b612ed1df66f33eff839c0064ac16d7e04650d13984b08b2f9e7bb240fe3ff920000000000000014a973f3c74f41cecc3c596a125835264d72803ba1ef9c9270fa2228e8f8442889f20ddfffc60bc073758c3fd13a29219ad4532c512d2a97c3a8421dedfa41e4d8d9ffaa3581049a65a64f57ea533ab831c88527bb3d7ce46b6eebd6fef6d3303cf7716455381c74da2bcbfc3e02de2e5fadb014ed4f7ecf6b62a4ce6c0db90b91f084512a18be5cb8892b1615a7bb7ef35d0192000000000000008c49908494889c8d07e0b6f0cb6871aaf7e97506476d0a63530ce06b58928225a4292dff8ffaccd4f217fd65c2afbac848ac5d5957d15aa83fb8d2f261d85ddf4f16feee49d07f274dd421f84862bd73634925c41d2b470066d751732cc4f9630e886df15e63f962959c8f765b48434b6124fe051c2a02ba91bd94a7d8fc3cf7240ffba508ff73d8bb95a8ba661fa59ed9c9b8030000000000000120000000000000000da685763a376d42546959f3e2d96ff46256cd3e539dd458b800c9d0daf4d981019c00000000000000a529edcfd13d9f5014b4e2fab134f833d266876a0a0fbcf3577ef87ced2656924e235d4a6f48169d0c6b1fd4d77b27f36b0eda1e78fb1691894e077333e7f278444a3e6de72685de03564bcf61466567e34c79279fcdccc42c2354e4c0a836e785f909656badb5950ebcf77a1ef9a3680818abe674760bc09888a446b96d9765779222970aaeb804abaa939c4225c474c2bc925be1d24648c6298d69208e695ae5888320393ef041be5f42d0f2eaac6036daffb8373eb80ad275fcc2b9"; #[test_only] const CONSENSUS_POP_1: vector = x"a9d6c1f1270f2d1454c89a83a4099f813a56dc7db55591d46aa4e6ccae7898b234029ba7052f18755e6fa5e6b73e235f14efc4e2eb402ca2b8f56bad69f965fc11b7b25eb1c95a06f83ddfd023eac4559b6582696cfea97b227f4ce5bdfdfed0"; @@ -2889,7 +2949,7 @@ module supra_framework::pbo_delegation_pool { true, 1, 100, - 1000000 + 1000000, ); } @@ -2903,7 +2963,7 @@ module supra_framework::pbo_delegation_pool { true, 0, 100, - 1000000 + 1000000, ); } @@ -2927,7 +2987,7 @@ module supra_framework::pbo_delegation_pool { allow_validator_set_change, rewards_rate_numerator, rewards_rate_denominator, - voting_power_increase_limit + voting_power_increase_limit, ); reconfiguration::initialize_for_test(supra_framework); features::change_feature_flags_for_testing( @@ -2936,9 +2996,8 @@ module supra_framework::pbo_delegation_pool { DELEGATION_POOLS, MODULE_EVENT, OPERATOR_BENEFICIARY_CHANGE, - COMMISSION_CHANGE_DELEGATION_POOL - ], - vector[] + COMMISSION_CHANGE_DELEGATION_POOL], + vector[], ); } @@ -2974,11 +3033,15 @@ module supra_framework::pbo_delegation_pool { unlock_numerators, unlock_denominator, principle_lockup_time, - unlock_duration + unlock_duration, ); let pool_address = get_owned_pool_address(validator_address); - stake::rotate_consensus_key(validator, pool_address, CONSENSUS_KEY_1); + stake::rotate_consensus_key( + validator, + pool_address, + stake::generate_unique_consensus_pubkey_bytes() + ); if (amount > 0) { stake::mint(validator, amount); @@ -3033,7 +3096,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ) } @@ -3058,7 +3121,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let pool_address = get_owned_pool_address(validator_address); @@ -3113,7 +3176,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let coin = stake::mint_coins(100 * ONE_SUPRA); initialize_delegation_pool( @@ -3127,7 +3190,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, 0, - 12 + 12, ); } @@ -3152,7 +3215,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); withdraw(validator, get_owned_pool_address(signer::address_of(validator)), 0); } @@ -3178,7 +3241,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); assert_owner_cap_exists(validator_address); @@ -3196,14 +3259,7 @@ module supra_framework::pbo_delegation_pool { stake::assert_stake_pool(pool_address, 0, 0, 0, 0); } - #[ - test( - supra_framework = @supra_framework, - validator = @0x123, - delegator1 = @0x010, - delegator2 = @0x020 - ) - ] + #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] public entry fun test_add_stake_fee( supra_framework: &signer, validator: &signer, @@ -3218,7 +3274,7 @@ module supra_framework::pbo_delegation_pool { true, 1, 100, - 1000000 + 1000000, ); let delegator_address = vector[@0x010, @0x020]; let principle_stake = vector[0, 0]; @@ -3239,16 +3295,20 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let pool_address = get_owned_pool_address(validator_address); - stake::rotate_consensus_key(validator, pool_address, CONSENSUS_KEY_1); + stake::rotate_consensus_key( + validator, + pool_address, + stake::generate_unique_consensus_pubkey_bytes() + ); // zero `add_stake` fee as validator is not producing rewards this epoch assert!( get_add_stake_fee(pool_address, 1000000 * ONE_SUPRA) == 0, - 0 + 0, ); // add 1M SUPRA, join the validator set and activate this stake @@ -3267,7 +3327,7 @@ module supra_framework::pbo_delegation_pool { // `add_stake` fee for 100000 coins: 100000 * 0.006265 / (1 + 0.006265) assert!( get_add_stake_fee(pool_address, 100000 * ONE_SUPRA) == 62259941466, - 0 + 0, ); // add pending_active stake from multiple delegators @@ -3283,14 +3343,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 10000000000000, 0, - 0 + 0, ); assert_delegation( delegator2_address, pool_address, 1000000000000, 0, - 0 + 0, ); // add more stake from delegator 1 @@ -3304,7 +3364,7 @@ module supra_framework::pbo_delegation_pool { pool_address, delegator1_active + 10000 * ONE_SUPRA - fee, 0, - 0 + 0, ); // delegator 2 should not benefit in any way from this new stake @@ -3313,7 +3373,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1000000000000, 0, - 0 + 0, ); // add more stake from delegator 2 @@ -3328,7 +3388,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 11062650000001, 0, - 0 + 0, ); // 1000000000000 * 1% * (100 - 37.35)% assert_delegation( @@ -3336,7 +3396,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 11006265000001, 0, - 0 + 0, ); // in-flight operator commission rewards do not automatically restake/compound @@ -3348,14 +3408,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 11062650000001, 0, - 0 + 0, ); assert_delegation( delegator2_address, pool_address, 11006265000001, 0, - 0 + 0, ); end_aptos_epoch(); @@ -3365,14 +3425,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 11131957502251, 0, - 0 + 0, ); assert_delegation( delegator2_address, pool_address, 11075219250226, 0, - 0 + 0, ); // add more stake from delegator 1 @@ -3386,7 +3446,7 @@ module supra_framework::pbo_delegation_pool { pool_address, delegator1_active + 20000 * ONE_SUPRA - fee, 0, - 0 + 0, ); // delegator 1 unlocks his entire newly added stake @@ -3398,7 +3458,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 11201699216002, 0, - 2000000000000 + 2000000000000, ); // stakes should remain the same - `Self::get_stake` correctly calculates them @@ -3408,7 +3468,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 11201699216002, 0, - 2000000000000 + 2000000000000, ); let reward_period_start_time_in_sec = timestamp::now_seconds(); @@ -3420,12 +3480,12 @@ module supra_framework::pbo_delegation_pool { fixed_point64::create_from_rational(6, 1000), one_year_in_secs, reward_period_start_time_in_sec, - fixed_point64::create_from_rational(50, 100) + fixed_point64::create_from_rational(50, 100), ); features::change_feature_flags_for_testing( supra_framework, vector[features::get_periodical_reward_rate_decrease_feature()], - vector[] + vector[], ); // add more stake from delegator 1 @@ -3442,7 +3502,7 @@ module supra_framework::pbo_delegation_pool { pool_address, delegator1_active + 20000 * ONE_SUPRA - fee, 0, - delegator1_pending_inactive + delegator1_pending_inactive, ); // delegator 1 unlocks his entire newly added stake @@ -3454,7 +3514,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 11342056366822, 0, - 4025059974939 + 4025059974939, ); // stakes should remain the same - `Self::get_stake` correctly calculates them @@ -3464,7 +3524,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 11342056366822, 0, - 4025059974939 + 4025059974939, ); fast_forward_seconds(one_year_in_secs); @@ -3492,7 +3552,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); @@ -3519,7 +3579,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1009999999, 0, - 0 + 0, ); assert_pending_withdrawal( delegator_address, @@ -3527,7 +3587,7 @@ module supra_framework::pbo_delegation_pool { false, 0, false, - 0 + 0, ); unlock_with_min_stake_disabled(delegator, pool_address, 2); @@ -3540,7 +3600,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1009999997, 0, - 0 + 0, ); // the pending withdrawal has been created as > 0 pending_inactive shares have been bought assert_pending_withdrawal( @@ -3549,7 +3609,7 @@ module supra_framework::pbo_delegation_pool { true, 0, false, - 0 + 0, ); // successfully delete the pending withdrawal (redeem all owned shares even worth 0 coins) @@ -3559,7 +3619,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1009999997, 0, - 0 + 0, ); assert_pending_withdrawal( delegator_address, @@ -3567,7 +3627,7 @@ module supra_framework::pbo_delegation_pool { false, 0, false, - 0 + 0, ); // unlock min coins to own some pending_inactive balance (have to disable min-balance checks) @@ -3581,7 +3641,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1009999994, 0, - 1 + 1, ); // the pending withdrawal has been created as > 0 pending_inactive shares have been bought assert_pending_withdrawal( @@ -3590,7 +3650,7 @@ module supra_framework::pbo_delegation_pool { true, 0, false, - 1 + 1, ); reactivate_stake(delegator, pool_address, MIN_COINS_ON_SHARES_POOL); @@ -3600,7 +3660,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1009999995, 0, - 0 + 0, ); // the pending withdrawal has been deleted as delegator has 0 pending_inactive shares now assert_pending_withdrawal( @@ -3609,7 +3669,7 @@ module supra_framework::pbo_delegation_pool { false, 0, false, - 0 + 0, ); } @@ -3637,7 +3697,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); } @@ -3663,7 +3723,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); @@ -3676,13 +3736,13 @@ module supra_framework::pbo_delegation_pool { pool_address, 1000 * ONE_SUPRA, 0, - 0 + 0, ); // zero `add_stake` fee as validator is not producing rewards this epoch assert!( get_add_stake_fee(pool_address, 250 * ONE_SUPRA) == 0, - 0 + 0, ); // check `add_stake` increases `active` stakes of delegator and stake pool @@ -3693,7 +3753,7 @@ module supra_framework::pbo_delegation_pool { // check added stake have been transferred out of delegator account assert!( coin::balance(validator_address) == balance - 250 * ONE_SUPRA, - 0 + 0, ); // zero `add_stake` fee charged from added stake assert_delegation( @@ -3701,7 +3761,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1250 * ONE_SUPRA, 0, - 0 + 0, ); // zero `add_stake` fee transferred to null shareholder assert_delegation(NULL_SHAREHOLDER, pool_address, 0, 0, 0); @@ -3722,7 +3782,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1500 * ONE_SUPRA - fee1, 0, - 0 + 0, ); // check `add_stake` fee has been transferred to the null shareholder assert_delegation(NULL_SHAREHOLDER, pool_address, fee1, 0, 0); @@ -3731,7 +3791,7 @@ module supra_framework::pbo_delegation_pool { 1250 * ONE_SUPRA, 0, 250 * ONE_SUPRA, - 0 + 0, ); // add 100 additional coins being pending_active until next epoch @@ -3744,7 +3804,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1600 * ONE_SUPRA - fee1 - fee2, 0, - 0 + 0, ); // check `add_stake` fee has been transferred to the null shareholder assert_delegation(NULL_SHAREHOLDER, pool_address, fee1 + fee2, 0, 0); @@ -3753,7 +3813,7 @@ module supra_framework::pbo_delegation_pool { 1250 * ONE_SUPRA, 0, 350 * ONE_SUPRA, - 0 + 0, ); end_aptos_epoch(); @@ -3763,7 +3823,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 161250000000, 0, - 0 + 0, ); stake::assert_stake_pool(pool_address, 161250000000, 0, 0, 0); @@ -3773,9 +3833,9 @@ module supra_framework::pbo_delegation_pool { assert!( pool_u64::shares( &borrow_global(pool_address).active_shares, - NULL_SHAREHOLDER + NULL_SHAREHOLDER, ) == 0, - 0 + 0, ); assert_delegation(NULL_SHAREHOLDER, pool_address, 0, 0, 0); @@ -3789,7 +3849,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 181250000000 - fee1, 0, - 0 + 0, ); // check `add_stake` fee has been transferred to the null shareholder assert_delegation(NULL_SHAREHOLDER, pool_address, fee1 - 1, 0, 0); @@ -3802,7 +3862,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 182862500000, 0, - 0 + 0, ); stake::assert_stake_pool(pool_address, 182862500000, 0, 0, 0); @@ -3812,9 +3872,9 @@ module supra_framework::pbo_delegation_pool { assert!( pool_u64::shares( &borrow_global(pool_address).active_shares, - NULL_SHAREHOLDER + NULL_SHAREHOLDER, ) == 0, - 0 + 0, ); assert_delegation(NULL_SHAREHOLDER, pool_address, 0, 0, 0); } @@ -3841,7 +3901,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); @@ -3856,7 +3916,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1000 * ONE_SUPRA, 0, - 0 + 0, ); // add 250 coins from second account @@ -3869,21 +3929,21 @@ module supra_framework::pbo_delegation_pool { pool_address, 250 * ONE_SUPRA - fee1, 0, - 0 + 0, ); assert_delegation( validator_address, pool_address, 1000 * ONE_SUPRA, 0, - 0 + 0, ); stake::assert_stake_pool( pool_address, 1000 * ONE_SUPRA, 0, 250 * ONE_SUPRA, - 0 + 0, ); end_aptos_epoch(); @@ -3895,7 +3955,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 250 * ONE_SUPRA, 0, - 0 + 0, ); // actual active rewards have been distributed to their earner(s) assert_delegation( @@ -3903,7 +3963,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 100999999999, 0, - 0 + 0, ); // add another 250 coins from first account @@ -3916,21 +3976,21 @@ module supra_framework::pbo_delegation_pool { pool_address, 125999999999 - fee1, 0, - 0 + 0, ); assert_delegation( delegator_address, pool_address, 250 * ONE_SUPRA, 0, - 0 + 0, ); stake::assert_stake_pool( pool_address, 1260 * ONE_SUPRA, 0, 250 * ONE_SUPRA, - 0 + 0, ); // add another 100 coins from second account @@ -3943,21 +4003,21 @@ module supra_framework::pbo_delegation_pool { pool_address, 350 * ONE_SUPRA - fee2, 0, - 0 + 0, ); assert_delegation( validator_address, pool_address, 125999999999 - fee1, 0, - 0 + 0, ); stake::assert_stake_pool( pool_address, 1260 * ONE_SUPRA, 0, 350 * ONE_SUPRA, - 0 + 0, ); end_aptos_epoch(); @@ -3968,7 +4028,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 35250000001, 0, - 0 + 0, ); // 1010 * 1.01 active stake + 250 pending_active stake assert_delegation( @@ -3976,7 +4036,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 127009999998, 0, - 0 + 0, ); stake::assert_stake_pool(pool_address, 162260000000, 0, 0, 0); } @@ -4003,7 +4063,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); @@ -4022,14 +4082,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 300 * ONE_SUPRA - fee, 0, - 0 + 0, ); stake::assert_stake_pool( pool_address, 100 * ONE_SUPRA, 0, 200 * ONE_SUPRA, - 0 + 0, ); // cannot unlock pending_active stake (only 100/300 stake can be displaced) @@ -4039,7 +4099,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 200 * ONE_SUPRA - fee, 0, - 100 * ONE_SUPRA + 100 * ONE_SUPRA, ); assert_pending_withdrawal( validator_address, @@ -4047,14 +4107,14 @@ module supra_framework::pbo_delegation_pool { true, 0, false, - 100 * ONE_SUPRA + 100 * ONE_SUPRA, ); stake::assert_stake_pool( pool_address, 0, 0, 200 * ONE_SUPRA, - 100 * ONE_SUPRA + 100 * ONE_SUPRA, ); assert_inactive_shares_pool(pool_address, 0, true, 100 * ONE_SUPRA); @@ -4066,7 +4126,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 250 * ONE_SUPRA - fee, 0, - 50 * ONE_SUPRA + 50 * ONE_SUPRA, ); assert_pending_withdrawal( validator_address, @@ -4074,14 +4134,14 @@ module supra_framework::pbo_delegation_pool { true, 0, false, - 50 * ONE_SUPRA + 50 * ONE_SUPRA, ); stake::assert_stake_pool( pool_address, 50 * ONE_SUPRA, 0, 200 * ONE_SUPRA, - 50 * ONE_SUPRA + 50 * ONE_SUPRA, ); reactivate_stake(validator, pool_address, 50 * ONE_SUPRA); @@ -4091,7 +4151,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 300 * ONE_SUPRA - fee, 0, - 0 + 0, ); assert_pending_withdrawal( validator_address, @@ -4099,14 +4159,14 @@ module supra_framework::pbo_delegation_pool { false, 0, false, - 0 + 0, ); stake::assert_stake_pool( pool_address, 100 * ONE_SUPRA, 0, 200 * ONE_SUPRA, - 0 + 0, ); // pending_inactive shares pool has not been deleted (as can still `unlock` this OLC) assert_inactive_shares_pool(pool_address, 0, true, 0); @@ -4118,7 +4178,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 301 * ONE_SUPRA, 0, - 0 + 0, ); stake::assert_stake_pool(pool_address, 301 * ONE_SUPRA, 0, 0, 0); @@ -4129,7 +4189,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 15100000001, 0, - 14999999999 + 14999999999, ); stake::assert_stake_pool(pool_address, 15100000001, 0, 0, 14999999999); assert_pending_withdrawal( @@ -4138,13 +4198,12 @@ module supra_framework::pbo_delegation_pool { true, 0, false, - 14999999999 + 14999999999, ); assert!( - stake::get_remaining_lockup_secs(pool_address) - == LOCKUP_CYCLE_SECONDS - EPOCH_DURATION, - 0 + stake::get_remaining_lockup_secs(pool_address) == LOCKUP_CYCLE_SECONDS - EPOCH_DURATION, + 0, ); end_aptos_epoch(); // additionally forwards EPOCH_DURATION seconds @@ -4155,7 +4214,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 15251000001, 0, - 15149999998 + 15149999998, ); assert_pending_withdrawal( validator_address, @@ -4163,7 +4222,7 @@ module supra_framework::pbo_delegation_pool { true, 0, false, - 15149999998 + 15149999998, ); stake::assert_stake_pool(pool_address, 15251000001, 0, 0, 15149999998); @@ -4176,7 +4235,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 15403510001, 15301499997, - 0 + 0, ); assert_pending_withdrawal( validator_address, @@ -4184,7 +4243,7 @@ module supra_framework::pbo_delegation_pool { true, 0, true, - 15301499997 + 15301499997, ); stake::assert_stake_pool(pool_address, 15403510001, 15301499997, 0, 0); @@ -4201,21 +4260,21 @@ module supra_framework::pbo_delegation_pool { pool_address, 4999999999 - fee, 0, - 0 + 0, ); assert_delegation( validator_address, pool_address, 15403510001, 15301499997, - 0 + 0, ); stake::assert_stake_pool( pool_address, 15403510001, 15301499997, 50 * ONE_SUPRA, - 0 + 0, ); // cannot withdraw stake unlocked by others @@ -4230,7 +4289,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 15403510001, 0, - 0 + 0, ); // pending withdrawal has been executed and deleted assert_pending_withdrawal( @@ -4239,7 +4298,7 @@ module supra_framework::pbo_delegation_pool { false, 0, false, - 0 + 0, ); // inactive shares pool on OLC 0 has been deleted because its stake has been withdrawn assert_inactive_shares_pool(pool_address, 0, false, 0); @@ -4251,7 +4310,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 10000000000, 0, - 5403510000 + 5403510000, ); assert_pending_withdrawal( validator_address, @@ -4259,7 +4318,7 @@ module supra_framework::pbo_delegation_pool { true, 1, false, - 5403510000 + 5403510000, ); // end lockup cycle 1 @@ -4272,7 +4331,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 10100000000, 5457545100, - 0 + 0, ); assert_pending_withdrawal( validator_address, @@ -4280,7 +4339,7 @@ module supra_framework::pbo_delegation_pool { true, 1, true, - 5457545100 + 5457545100, ); // unlock when the pending withdrawal exists and gets automatically executed @@ -4288,14 +4347,14 @@ module supra_framework::pbo_delegation_pool { unlock(validator, pool_address, 10100000000); assert!( coin::balance(validator_address) == balance + 5457545100, - 0 + 0, ); assert_delegation( validator_address, pool_address, 0, 0, - 10100000000 + 10100000000, ); // this is the new pending withdrawal replacing the executed one assert_pending_withdrawal( @@ -4304,7 +4363,7 @@ module supra_framework::pbo_delegation_pool { true, 2, false, - 10100000000 + 10100000000, ); // create dummy validator to ensure the existing validator can leave the set @@ -4313,8 +4372,9 @@ module supra_framework::pbo_delegation_pool { let coin = stake::mint_coins(100 * ONE_SUPRA); // lockup time updated as you see above we `fast_forward_seconds` alog with `end_aptos_epoch` - principle_lockup_time = LOCKUP_CYCLE_SECONDS - + (LOCKUP_CYCLE_SECONDS - (3 * EPOCH_DURATION)) + (5 * EPOCH_DURATION); + principle_lockup_time = LOCKUP_CYCLE_SECONDS + ( + LOCKUP_CYCLE_SECONDS - (3 * EPOCH_DURATION) + ) + (5 * EPOCH_DURATION); initialize_test_validator( delegator, 100 * ONE_SUPRA, @@ -4328,7 +4388,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); // inactivate validator stake::leave_validator_set(validator, pool_address); @@ -4351,7 +4411,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 0, 0, - 10303010000 + 10303010000, ); // the pending withdrawal should be reported as still pending assert_pending_withdrawal( @@ -4360,7 +4420,7 @@ module supra_framework::pbo_delegation_pool { true, 2, false, - 10303010000 + 10303010000, ); // validator is inactive and lockup expired => pending_inactive stake is withdrawable @@ -4369,7 +4429,7 @@ module supra_framework::pbo_delegation_pool { assert!( coin::balance(validator_address) == balance + 10303010000, - 0 + 0, ); assert_delegation(validator_address, pool_address, 0, 0, 0); assert_pending_withdrawal( @@ -4378,7 +4438,7 @@ module supra_framework::pbo_delegation_pool { false, 0, false, - 0 + 0, ); stake::assert_stake_pool(pool_address, 5100500001, 0, 0, 0); // pending_inactive shares pool has not been deleted (as can still `unlock` this OLC) @@ -4386,7 +4446,7 @@ module supra_framework::pbo_delegation_pool { pool_address, observed_lockup_cycle(pool_address), true, - 0 + 0, ); stake::mint(validator, 30 * ONE_SUPRA); @@ -4398,7 +4458,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 2000000000, 0, - 999999999 + 999999999, ); // the pending withdrawal should be reported as still pending assert_pending_withdrawal( @@ -4407,7 +4467,7 @@ module supra_framework::pbo_delegation_pool { true, 2, false, - 999999999 + 999999999, ); balance = coin::balance(validator_address); @@ -4419,7 +4479,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 2000000000, 0, - 999999998 + 999999998, ); assert_pending_withdrawal( validator_address, @@ -4427,22 +4487,15 @@ module supra_framework::pbo_delegation_pool { true, 2, false, - 999999998 + 999999998, ); assert!( coin::balance(validator_address) == balance + 1, - 0 + 0, ); } - #[ - test( - supra_framework = @supra_framework, - validator = @0x123, - delegator1 = @0x010, - delegator2 = @0x020 - ) - ] + #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] public entry fun test_total_coins_inactive( supra_framework: &signer, validator: &signer, @@ -4467,7 +4520,7 @@ module supra_framework::pbo_delegation_pool { vector[1], 1, principle_lockup_time, - 60 + 60, ); let validator_address = signer::address_of(validator); @@ -4490,14 +4543,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 100 * ONE_SUPRA, 0, - 0 + 0, ); assert_delegation( delegator2_address, pool_address, 200 * ONE_SUPRA, 0, - 0 + 0, ); // unlock some stake from delegator 1 @@ -4507,7 +4560,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 5000000000, 0, - 4999999999 + 4999999999, ); // move to lockup cycle 1 @@ -4520,14 +4573,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 5050000000, 5049999998, - 0 + 0, ); assert_delegation( delegator2_address, pool_address, 202 * ONE_SUPRA, 0, - 0 + 0, ); synchronize_delegation_pool(pool_address); @@ -4540,7 +4593,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 15200000001, 0, - 4999999999 + 4999999999, ); // withdraw some of inactive stake of delegator 1 @@ -4550,7 +4603,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 5050000000, 3000000001, - 0 + 0, ); assert!(total_coins_inactive(pool_address) == 3000000001, 0); @@ -4565,14 +4618,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 5100500000, 3000000001, - 0 + 0, ); assert_delegation( delegator2_address, pool_address, 15352000001, 5049999998, - 0 + 0, ); // total_coins_inactive remains unchanged in the absence of user operations @@ -4580,9 +4633,9 @@ module supra_framework::pbo_delegation_pool { synchronize_delegation_pool(pool_address); // total_coins_inactive == previous inactive stake + previous pending_inactive stake and its rewards assert!( - total_coins_inactive(pool_address) - == inactive + pending_inactive + pending_inactive / 100, - 0 + total_coins_inactive(pool_address) == inactive + pending_inactive + pending_inactive + / 100, + 0, ); // withdraw some of inactive stake of delegator 2 @@ -4590,7 +4643,7 @@ module supra_framework::pbo_delegation_pool { withdraw(delegator2, pool_address, 3049999998); assert!( total_coins_inactive(pool_address) == total_coins_inactive - 3049999997, - 0 + 0, ); // unlock some stake from delegator `validator` @@ -4614,7 +4667,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); // inactivate validator stake::leave_validator_set(validator, pool_address); @@ -4670,7 +4723,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); @@ -4683,14 +4736,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 100 * ONE_SUPRA, 0, - 100 * ONE_SUPRA + 100 * ONE_SUPRA, ); stake::assert_stake_pool( pool_address, 100 * ONE_SUPRA, 0, 0, - 100 * ONE_SUPRA + 100 * ONE_SUPRA, ); assert_pending_withdrawal( validator_address, @@ -4698,7 +4751,7 @@ module supra_framework::pbo_delegation_pool { true, 0, false, - 100 * ONE_SUPRA + 100 * ONE_SUPRA, ); // add some stake to pending_active state @@ -4711,14 +4764,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 250 * ONE_SUPRA - fee, 0, - 100 * ONE_SUPRA + 100 * ONE_SUPRA, ); stake::assert_stake_pool( pool_address, 100 * ONE_SUPRA, 0, 150 * ONE_SUPRA, - 100 * ONE_SUPRA + 100 * ONE_SUPRA, ); // can reactivate only pending_inactive stake @@ -4729,14 +4782,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 350 * ONE_SUPRA - fee, 0, - 0 + 0, ); stake::assert_stake_pool( pool_address, 200 * ONE_SUPRA, 0, 150 * ONE_SUPRA, - 0 + 0, ); assert_pending_withdrawal( validator_address, @@ -4744,7 +4797,7 @@ module supra_framework::pbo_delegation_pool { false, 0, false, - 0 + 0, ); end_aptos_epoch(); @@ -4754,7 +4807,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 35200000000, 0, - 0 + 0, ); // unlock stake added at previous epoch (expect some imprecision when moving shares) @@ -4764,7 +4817,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 20200000001, 0, - 14999999999 + 14999999999, ); stake::assert_stake_pool(pool_address, 20200000001, 0, 0, 14999999999); @@ -4778,7 +4831,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 20402000001, 15149999998, - 0 + 0, ); assert_pending_withdrawal( validator_address, @@ -4786,7 +4839,7 @@ module supra_framework::pbo_delegation_pool { true, 0, true, - 15149999998 + 15149999998, ); // cannot reactivate inactive stake @@ -4796,7 +4849,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 20402000001, 15149999998, - 0 + 0, ); // unlock stake in the new lockup cycle (the pending withdrawal is executed) @@ -4807,7 +4860,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 10402000002, 0, - 9999999999 + 9999999999, ); assert_pending_withdrawal( validator_address, @@ -4815,7 +4868,7 @@ module supra_framework::pbo_delegation_pool { true, 1, false, - 9999999999 + 9999999999, ); // reactivate the new pending withdrawal almost entirely @@ -4826,7 +4879,7 @@ module supra_framework::pbo_delegation_pool { true, 1, false, - 1000000000 + 1000000000, ); // reactivate remaining stake of the new pending withdrawal reactivate_stake(validator, pool_address, 1000000000); @@ -4836,7 +4889,7 @@ module supra_framework::pbo_delegation_pool { false, 0, false, - 0 + 0, ); } @@ -4862,7 +4915,7 @@ module supra_framework::pbo_delegation_pool { vector[1], 1, principle_lockup_time, - 60 + 60, ); let validator_address = signer::address_of(validator); @@ -4881,7 +4934,7 @@ module supra_framework::pbo_delegation_pool { true, 0, false, - 100 * ONE_SUPRA + 100 * ONE_SUPRA, ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); @@ -4892,14 +4945,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 200 * ONE_SUPRA, 0, - 0 + 0, ); assert_delegation( validator_address, pool_address, 90899999999, 10100000000, - 0 + 0, ); assert_pending_withdrawal( validator_address, @@ -4907,7 +4960,7 @@ module supra_framework::pbo_delegation_pool { true, 0, true, - 10100000000 + 10100000000, ); assert_inactive_shares_pool(pool_address, 0, true, 100 * ONE_SUPRA); @@ -4918,14 +4971,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 200 * ONE_SUPRA, 0, - 0 + 0, ); assert_delegation( validator_address, pool_address, 90899999999, 10100000000, - 0 + 0, ); unlock(delegator, pool_address, 100 * ONE_SUPRA); @@ -4934,14 +4987,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 10000000000, 0, - 9999999999 + 9999999999, ); assert_delegation( validator_address, pool_address, 90900000000, 10100000000, - 0 + 0, ); assert_pending_withdrawal( delegator_address, @@ -4949,7 +5002,7 @@ module supra_framework::pbo_delegation_pool { true, 1, false, - 9999999999 + 9999999999, ); // check cannot withdraw inactive stake unlocked by others even if owning pending_inactive @@ -4959,14 +5012,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 10000000000, 0, - 9999999999 + 9999999999, ); assert_delegation( validator_address, pool_address, 90900000000, 10100000000, - 0 + 0, ); // withdraw entire owned inactive stake @@ -4974,7 +5027,7 @@ module supra_framework::pbo_delegation_pool { withdraw(validator, pool_address, MAX_U64); assert!( coin::balance(validator_address) == balance + 10100000000, - 0 + 0, ); assert_pending_withdrawal( validator_address, @@ -4982,7 +5035,7 @@ module supra_framework::pbo_delegation_pool { false, 0, false, - 0 + 0, ); assert_inactive_shares_pool(pool_address, 0, false, 0); @@ -4994,7 +5047,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 10100000000, 10099999998, - 0 + 0, ); assert_pending_withdrawal( delegator_address, @@ -5002,7 +5055,7 @@ module supra_framework::pbo_delegation_pool { true, 1, true, - 10099999998 + 10099999998, ); assert_inactive_shares_pool(pool_address, 1, true, 9999999999); @@ -5016,7 +5069,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 10100000000, 10099999998, - 0 + 0, ); assert_pending_withdrawal( delegator_address, @@ -5024,7 +5077,7 @@ module supra_framework::pbo_delegation_pool { true, 1, true, - 10099999998 + 10099999998, ); // implicitly execute the pending withdrawal by unlocking min stake to buy 1 share @@ -5035,7 +5088,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 10099999998, 0, - 1 + 1, ); // old pending withdrawal has been replaced assert_pending_withdrawal( @@ -5044,7 +5097,7 @@ module supra_framework::pbo_delegation_pool { true, 2, false, - 1 + 1, ); assert_inactive_shares_pool(pool_address, 1, false, 0); assert_inactive_shares_pool(pool_address, 2, true, 1); @@ -5072,7 +5125,7 @@ module supra_framework::pbo_delegation_pool { vector[1], 1, principle_lockup_time, - 60 + 60, ); let validator_address = signer::address_of(validator); @@ -5115,7 +5168,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); // inactivate validator stake::leave_validator_set(validator, pool_address); @@ -5136,21 +5189,21 @@ module supra_framework::pbo_delegation_pool { 113231100001, 20200000000, 0, - 10200999997 + 10200999997, ); assert_delegation( delegator_address, pool_address, 10201000000, 0, - 10200999997 + 10200999997, ); assert_delegation( validator_address, pool_address, 103030100000, 20200000000, - 0 + 0, ); // withdraw some inactive stake (remaining pending_inactive is not inactivated) @@ -5160,21 +5213,21 @@ module supra_framework::pbo_delegation_pool { 113231100001, 20000000001, 0, - 10200999997 + 10200999997, ); assert_delegation( delegator_address, pool_address, 10201000000, 0, - 10200999997 + 10200999997, ); assert_delegation( validator_address, pool_address, 103030100000, 20000000001, - 0 + 0, ); // withdraw some pending_inactive stake (remaining pending_inactive is not inactivated) @@ -5184,21 +5237,21 @@ module supra_framework::pbo_delegation_pool { 113231100001, 20000000001, 0, - 10000000001 + 10000000001, ); assert_delegation( delegator_address, pool_address, 10201000000, 0, - 10000000001 + 10000000001, ); assert_delegation( validator_address, pool_address, 103030100000, 20000000001, - 0 + 0, ); // no new inactive stake detected => OLC does not advance @@ -5213,14 +5266,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 0, 0, - 10000000002 + 10000000002, ); assert_delegation( validator_address, pool_address, 103030100001, 20000000001, - 0 + 0, ); assert_pending_withdrawal( validator_address, @@ -5228,7 +5281,7 @@ module supra_framework::pbo_delegation_pool { true, 0, true, - 20000000001 + 20000000001, ); assert_pending_withdrawal( delegator_address, @@ -5236,21 +5289,21 @@ module supra_framework::pbo_delegation_pool { true, 1, false, - 10000000002 + 10000000002, ); stake::assert_stake_pool( pool_address, 103030100001, 20000000001, 0, - 10000000002 + 10000000002, ); // reactivate validator stake::join_validator_set(validator, pool_address); assert!( stake::get_validator_state(pool_address) == VALIDATOR_STATUS_PENDING_ACTIVE, - 0 + 0, ); end_aptos_epoch(); @@ -5261,7 +5314,7 @@ module supra_framework::pbo_delegation_pool { 103030100001, 20000000001, 0, - 10000000002 + 10000000002, ); synchronize_delegation_pool(pool_address); @@ -5271,7 +5324,7 @@ module supra_framework::pbo_delegation_pool { true, 0, true, - 20000000001 + 20000000001, ); assert_pending_withdrawal( delegator_address, @@ -5279,7 +5332,7 @@ module supra_framework::pbo_delegation_pool { true, 1, false, - 10000000002 + 10000000002, ); assert!(observed_lockup_cycle(pool_address) == observed_lockup_cycle, 0); @@ -5291,7 +5344,7 @@ module supra_framework::pbo_delegation_pool { true, 1, false, - 10000000002 + 10000000002, ); // earning rewards is resumed from this epoch on @@ -5301,7 +5354,7 @@ module supra_framework::pbo_delegation_pool { 104060401001, 20000000001, 0, - 10100000002 + 10100000002, ); // new pending_inactive stake earns rewards but so does the old one @@ -5312,7 +5365,7 @@ module supra_framework::pbo_delegation_pool { true, 1, false, - 104060401000 + 104060401000, ); assert_pending_withdrawal( delegator_address, @@ -5320,7 +5373,7 @@ module supra_framework::pbo_delegation_pool { true, 1, false, - 10100000002 + 10100000002, ); end_aptos_epoch(); assert_pending_withdrawal( @@ -5329,7 +5382,7 @@ module supra_framework::pbo_delegation_pool { true, 1, false, - 105101005010 + 105101005010, ); assert_pending_withdrawal( delegator_address, @@ -5337,7 +5390,7 @@ module supra_framework::pbo_delegation_pool { true, 1, false, - 10201000002 + 10201000002, ); } @@ -5363,7 +5416,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); @@ -5376,7 +5429,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1010 * ONE_SUPRA, 0, - 0 + 0, ); // add stake in pending_active state @@ -5389,7 +5442,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1210 * ONE_SUPRA - fee, 0, - 0 + 0, ); end_aptos_epoch(); @@ -5399,7 +5452,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 122010000000, 0, - 0 + 0, ); end_aptos_epoch(); @@ -5409,7 +5462,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 123230100000, 0, - 0 + 0, ); // 123230100000 active stake * 1.01 @@ -5427,7 +5480,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 129516073574, 0, - 0 + 0, ); // unlock 200 coins from delegator `validator` @@ -5437,7 +5490,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 109516073575, 0, - 19999999999 + 19999999999, ); // end this lockup cycle @@ -5449,7 +5502,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 110611234310, 20199999998, - 0 + 0, ); end_aptos_epoch(); @@ -5459,7 +5512,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 111717346653, 20199999998, - 0 + 0, ); // add stake in pending_active state @@ -5472,7 +5525,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 211717346653 - fee, 20199999998, - 0 + 0, ); end_aptos_epoch(); @@ -5482,7 +5535,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 212834520119, 20199999998, - 0 + 0, ); end_aptos_epoch(); @@ -5492,7 +5545,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 214962865320, 20199999998, - 0 + 0, ); } @@ -5518,7 +5571,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); @@ -5535,21 +5588,21 @@ module supra_framework::pbo_delegation_pool { pool_address, 300 * ONE_SUPRA - fee, 0, - 0 + 0, ); assert_delegation( validator_address, pool_address, 200 * ONE_SUPRA, 0, - 0 + 0, ); stake::assert_stake_pool( pool_address, 200 * ONE_SUPRA, 0, 300 * ONE_SUPRA, - 0 + 0, ); end_aptos_epoch(); @@ -5559,14 +5612,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 300 * ONE_SUPRA, 0, - 0 + 0, ); assert_delegation( validator_address, pool_address, 20199999999, 0, - 0 + 0, ); stake::assert_stake_pool(pool_address, 502 * ONE_SUPRA, 0, 0, 0); @@ -5577,14 +5630,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 303 * ONE_SUPRA, 0, - 0 + 0, ); assert_delegation( validator_address, pool_address, 20401999999, 0, - 0 + 0, ); stake::assert_stake_pool(pool_address, 50702000000, 0, 0, 0); @@ -5595,14 +5648,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 30603000000, 0, - 0 + 0, ); assert_delegation( validator_address, pool_address, 20606019999, 0, - 0 + 0, ); stake::assert_stake_pool(pool_address, 51209020000, 0, 0, 0); @@ -5612,14 +5665,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 30909030000, 0, - 0 + 0, ); assert_delegation( validator_address, pool_address, 20812080199, 0, - 0 + 0, ); stake::assert_stake_pool(pool_address, 51721110200, 0, 0, 0); @@ -5633,14 +5686,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 130909030000 - fee, 0, - 0 + 0, ); assert_delegation( validator_address, pool_address, 20812080199, 0, - 0 + 0, ); end_aptos_epoch(); @@ -5650,14 +5703,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 131218120300, 0, - 0 + 0, ); assert_delegation( validator_address, pool_address, 21020201001, 0, - 0 + 0, ); stake::assert_stake_pool(pool_address, 152238321302, 0, 0, 0); } @@ -5684,7 +5737,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); @@ -5696,7 +5749,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1010 * ONE_SUPRA, 0, - 0 + 0, ); // unlock 200 coins from delegator `validator` @@ -5706,7 +5759,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 81000000001, 0, - 19999999999 + 19999999999, ); end_aptos_epoch(); // 81000000001 active stake * 1.01 + 19999999999 pending_inactive stake * 1.01 @@ -5720,7 +5773,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 84288924811, 20606019996, - 0 + 0, ); // unlock 200 coins from delegator `validator` which implicitly executes its pending withdrawal @@ -5731,7 +5784,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 64288924812, 0, - 19999999999 + 19999999999, ); // lockup cycle is not ended, pending_inactive stake is still earning @@ -5744,7 +5797,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 66899312957, 0, - 20812080195 + 20812080195, ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); @@ -5756,18 +5809,11 @@ module supra_framework::pbo_delegation_pool { pool_address, 68926429037, 21020200996, - 0 + 0, ); } - #[ - test( - supra_framework = @supra_framework, - validator = @0x123, - delegator1 = @0x010, - delegator2 = @0x020 - ) - ] + #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] public entry fun test_out_of_order_redeem( supra_framework: &signer, validator: &signer, @@ -5792,7 +5838,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); @@ -5820,7 +5866,7 @@ module supra_framework::pbo_delegation_pool { true, 0, false, - 14999999999 + 14999999999, ); // move to lockup cycle 1 @@ -5835,7 +5881,7 @@ module supra_framework::pbo_delegation_pool { true, 1, false, - 14999999999 + 14999999999, ); // 14999999999 pending_inactive stake * 1.01 assert_pending_withdrawal( @@ -5844,7 +5890,7 @@ module supra_framework::pbo_delegation_pool { true, 0, true, - 15149999998 + 15149999998, ); // move to lockup cycle 2 @@ -5857,7 +5903,7 @@ module supra_framework::pbo_delegation_pool { true, 1, true, - 15149999998 + 15149999998, ); assert_pending_withdrawal( delegator1_address, @@ -5865,7 +5911,7 @@ module supra_framework::pbo_delegation_pool { true, 0, true, - 15149999998 + 15149999998, ); // both delegators who unlocked at different lockup cycles should be able to withdraw their stakes @@ -5878,7 +5924,7 @@ module supra_framework::pbo_delegation_pool { true, 1, true, - 10000000001 + 10000000001, ); assert_pending_withdrawal( delegator1_address, @@ -5886,7 +5932,7 @@ module supra_framework::pbo_delegation_pool { false, 0, false, - 0 + 0, ); assert!(coin::balance(delegator1_address) == 15149999998, 0); assert!(coin::balance(delegator2_address) == 5149999997, 0); @@ -5904,7 +5950,7 @@ module supra_framework::pbo_delegation_pool { true, 1, true, - 10000000001 + 10000000001, ); // 9999999999 pending_inactive stake * 1.01 assert_pending_withdrawal( @@ -5913,7 +5959,7 @@ module supra_framework::pbo_delegation_pool { true, 2, true, - 10099999998 + 10099999998, ); // withdraw inactive stake of delegator 2 left from lockup cycle 1 in cycle 3 @@ -5925,14 +5971,14 @@ module supra_framework::pbo_delegation_pool { false, 0, false, - 0 + 0, ); // withdraw inactive stake of delegator 1 left from previous lockup cycle withdraw(delegator1, pool_address, 10099999998); assert!( coin::balance(delegator1_address) == 15149999998 + 10099999998, - 0 + 0, ); assert_pending_withdrawal( delegator1_address, @@ -5940,18 +5986,11 @@ module supra_framework::pbo_delegation_pool { false, 0, false, - 0 + 0, ); } - #[ - test( - supra_framework = @supra_framework, - validator = @0x123, - delegator1 = @0x010, - delegator2 = @0x020 - ) - ] + #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] public entry fun test_operator_fee( supra_framework: &signer, validator: &signer, @@ -5978,7 +6017,7 @@ module supra_framework::pbo_delegation_pool { vector[1], 1, principle_lockup_time, - 60 + 60, ); let pool_address = get_owned_pool_address(validator_address); assert!(stake::get_operator(pool_address) == validator_address, 0); @@ -6000,7 +6039,11 @@ module supra_framework::pbo_delegation_pool { assert_delegation(validator_address, pool_address, 0, 0, 0); // activate validator - stake::rotate_consensus_key(validator, pool_address, CONSENSUS_KEY_1); + stake::rotate_consensus_key( + validator, + pool_address, + stake::generate_unique_consensus_pubkey_bytes() + ); stake::join_validator_set(validator, pool_address); end_aptos_epoch(); @@ -6016,7 +6059,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 10087350000, 0, - 0 + 0, ); // 20000000000 active stake * 1.008735 assert_delegation( @@ -6024,7 +6067,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 20174700000, 0, - 0 + 0, ); end_aptos_epoch(); @@ -6040,7 +6083,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 10175573500, 0, - 0 + 0, ); // 20174700000 active stake * 1.008735 + some of the rewards of previous commission if restaked assert_delegation( @@ -6048,7 +6091,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 20351147000, 0, - 0 + 0, ); // restake operator commission rewards @@ -6063,7 +6106,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 115658596, 0, - 0 + 0, ); // 10175573500 active stake * 1.008735 assert_delegation( @@ -6071,7 +6114,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 10264457134, 0, - 0 + 0, ); // 20351147000 active stake * 1.008735 assert_delegation( @@ -6079,7 +6122,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 20528914269, 0, - 0 + 0, ); // check operator is rewarded by pending_inactive stake too @@ -6095,7 +6138,7 @@ module supra_framework::pbo_delegation_pool { false, 0, false, - 0 + 0, ); // distribute operator pending_inactive commission rewards synchronize_delegation_pool(pool_address); @@ -6106,7 +6149,7 @@ module supra_framework::pbo_delegation_pool { true, 0, false, - 12649998 + 12649998, ); // 209090300 active rewards * 0.1265 + 115658596 active stake * 1.008735 @@ -6116,7 +6159,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 143118796, 0, - 12649998 + 12649998, ); // 10264457134 active stake * 1.008735 assert_delegation( @@ -6124,7 +6167,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 10354117168, 0, - 0 + 0, ); // 10528914270 active stake * 1.008735 // 9999999999 pending_inactive stake * 1.008735 @@ -6133,7 +6176,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 10620884336, 0, - 10087349999 + 10087349999, ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); @@ -6148,7 +6191,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 171083360, 25536995, - 0 + 0, ); // distribute operator pending_inactive commission rewards synchronize_delegation_pool(pool_address); @@ -6158,14 +6201,14 @@ module supra_framework::pbo_delegation_pool { true, 0, true, - 25536995 + 25536995, ); // check operator is not rewarded by `add_stake` fees stake::mint(delegator1, 100 * ONE_SUPRA); assert!( get_add_stake_fee(pool_address, 100 * ONE_SUPRA) > 0, - 0 + 0, ); add_stake(delegator1, pool_address, 100 * ONE_SUPRA); @@ -6178,7 +6221,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 199559340, 25536995, - 0 + 0, ); // unlock some more stake to produce pending_inactive commission @@ -6189,7 +6232,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 10807241561, 10175463001, - 0 + 0, ); unlock(delegator2, pool_address, 100 * ONE_SUPRA); // 10807241561 - 100 SUPRA < `MIN_COINS_ON_SHARES_POOL` thus active stake is entirely unlocked @@ -6198,7 +6241,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 807241561, 0, - 9999999999 + 9999999999, ); end_aptos_epoch(); @@ -6208,7 +6251,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 228553872, 25536996, - 12649999 + 12649999, ); assert_pending_withdrawal( validator_address, @@ -6216,7 +6259,7 @@ module supra_framework::pbo_delegation_pool { true, 0, true, - 25536996 + 25536996, ); // distribute in-flight pending_inactive commission, implicitly executing the inactive withdrawal of operator @@ -6231,7 +6274,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 228553872, 0, - 12649998 + 12649998, ); assert_pending_withdrawal( validator_address, @@ -6239,18 +6282,11 @@ module supra_framework::pbo_delegation_pool { true, 1, false, - 12649998 + 12649998, ); } - #[ - test( - supra_framework = @supra_framework, - old_operator = @0x123, - delegator = @0x010, - new_operator = @0x020 - ) - ] + #[test(supra_framework = @supra_framework, old_operator = @0x123, delegator = @0x010, new_operator = @0x020)] public entry fun test_change_operator( supra_framework: &signer, old_operator: &signer, @@ -6281,7 +6317,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let pool_address = get_owned_pool_address(old_operator_address); assert!(stake::get_operator(pool_address) == old_operator_address, 0); @@ -6294,7 +6330,11 @@ module supra_framework::pbo_delegation_pool { unlock(delegator, pool_address, 100 * ONE_SUPRA); // activate validator - stake::rotate_consensus_key(old_operator, pool_address, CONSENSUS_KEY_1); + stake::rotate_consensus_key( + old_operator, + pool_address, + stake::generate_unique_consensus_pubkey_bytes() + ); stake::join_validator_set(old_operator, pool_address); end_aptos_epoch(); @@ -6306,7 +6346,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 12650000, 0, - 12650000 + 12650000, ); end_aptos_epoch(); stake::assert_stake_pool(pool_address, 10201000000, 0, 0, 10201000000); @@ -6315,7 +6355,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 25426500, 0, - 25426500 + 25426500, ); // change operator @@ -6329,7 +6369,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 25648600, 0, - 25648600 + 25648600, ); // 102010000 active rewards * 0.1265 and 102010000 pending_inactive rewards * 0.1265 assert_delegation( @@ -6337,7 +6377,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 12904265, 0, - 12904265 + 12904265, ); // restake `new_operator` commission rewards @@ -6351,7 +6391,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 25872641, 0, - 25872641 + 25872641, ); // 103030100 active rewards * 0.1265 and 12904265 active stake * 1.008735 // 103030100 pending_inactive rewards * 0.1265 and 12904265 pending_inactive stake * 1.008735 @@ -6360,19 +6400,11 @@ module supra_framework::pbo_delegation_pool { pool_address, 26050290, 0, - 26050290 + 26050290, ); } - #[ - test( - supra_framework = @supra_framework, - operator1 = @0x123, - delegator = @0x010, - beneficiary = @0x020, - operator2 = @0x030 - ) - ] + #[test(supra_framework = @supra_framework, operator1 = @0x123, delegator = @0x010, beneficiary = @0x020, operator2 = @0x030)] public entry fun test_set_beneficiary_for_operator( supra_framework: &signer, operator1: &signer, @@ -6406,7 +6438,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let pool_address = get_owned_pool_address(operator1_address); assert!(stake::get_operator(pool_address) == operator1_address, 0); @@ -6419,7 +6451,11 @@ module supra_framework::pbo_delegation_pool { unlock(delegator, pool_address, 1000000 * ONE_SUPRA); // activate validator - stake::rotate_consensus_key(operator1, pool_address, CONSENSUS_KEY_1); + stake::rotate_consensus_key( + operator1, + pool_address, + stake::generate_unique_consensus_pubkey_bytes() + ); stake::join_validator_set(operator1, pool_address); end_aptos_epoch(); @@ -6430,14 +6466,14 @@ module supra_framework::pbo_delegation_pool { 101000000000000, 0, 0, - 101000000000000 + 101000000000000, ); assert_delegation( operator1_address, pool_address, 126500000000, 0, - 126500000000 + 126500000000, ); end_aptos_epoch(); stake::assert_stake_pool( @@ -6445,14 +6481,14 @@ module supra_framework::pbo_delegation_pool { 102010000000000, 0, 0, - 102010000000000 + 102010000000000, ); assert_delegation( operator1_address, pool_address, 254265000000, 0, - 254265000000 + 254265000000, ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); @@ -6460,7 +6496,7 @@ module supra_framework::pbo_delegation_pool { withdraw(operator1, pool_address, ONE_SUPRA); assert!( coin::balance(operator1_address) == ONE_SUPRA - 1, - 0 + 0, ); set_beneficiary_for_operator(operator1, beneficiary_address); @@ -6474,11 +6510,11 @@ module supra_framework::pbo_delegation_pool { withdraw(beneficiary, pool_address, ONE_SUPRA); assert!( coin::balance(beneficiary_address) == ONE_SUPRA - 1, - 0 + 0, ); assert!( coin::balance(operator1_address) == ONE_SUPRA - 1, - 0 + 0, ); // switch operator to operator2. The rewards should go to operator2 not to the beneficiay of operator1. @@ -6491,11 +6527,11 @@ module supra_framework::pbo_delegation_pool { withdraw(operator2, pool_address, ONE_SUPRA); assert!( coin::balance(beneficiary_address) == ONE_SUPRA - 1, - 0 + 0, ); assert!( coin::balance(operator2_address) == ONE_SUPRA - 1, - 0 + 0, ); } @@ -6523,7 +6559,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let pool_address = get_owned_pool_address(operator_address); assert!(stake::get_operator(pool_address) == operator_address, 0); @@ -6536,7 +6572,11 @@ module supra_framework::pbo_delegation_pool { unlock(delegator, pool_address, 100 * ONE_SUPRA); // activate validator - stake::rotate_consensus_key(operator, pool_address, CONSENSUS_KEY_1); + stake::rotate_consensus_key( + operator, + pool_address, + stake::generate_unique_consensus_pubkey_bytes() + ); stake::join_validator_set(operator, pool_address); end_aptos_epoch(); @@ -6548,7 +6588,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 12650000, 0, - 12650000 + 12650000, ); end_aptos_epoch(); stake::assert_stake_pool(pool_address, 10201000000, 0, 0, 10201000000); @@ -6557,7 +6597,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 25426500, 0, - 25426500 + 25426500, ); // change the commission percentage @@ -6572,7 +6612,7 @@ module supra_framework::pbo_delegation_pool { // fee amount 76756290 in the following case, not 86593604 (calculated with the old commission rate). assert!( get_add_stake_fee(pool_address, 100 * ONE_SUPRA) == 76756290, - 0 + 0, ); synchronize_delegation_pool(pool_address); @@ -6586,7 +6626,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 62187388, 38552865, - 0 + 0, ); end_aptos_epoch(); @@ -6596,7 +6636,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 86058258, 38552865, - 0 + 0, ); } @@ -6624,7 +6664,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let pool_address = get_owned_pool_address(operator_address); assert!(stake::get_operator(pool_address) == operator_address, 0); @@ -6637,7 +6677,11 @@ module supra_framework::pbo_delegation_pool { unlock(delegator, pool_address, 100 * ONE_SUPRA); // activate validator - stake::rotate_consensus_key(operator, pool_address, CONSENSUS_KEY_1); + stake::rotate_consensus_key( + operator, + pool_address, + stake::generate_unique_consensus_pubkey_bytes() + ); stake::join_validator_set(operator, pool_address); end_aptos_epoch(); @@ -6665,14 +6709,7 @@ module supra_framework::pbo_delegation_pool { update_commission_percentage(operator, 2255); } - #[ - test( - supra_framework = @supra_framework, - validator = @0x123, - delegator1 = @0x010, - delegator2 = @0x020 - ) - ] + #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] public entry fun test_min_stake_is_preserved( supra_framework: &signer, validator: &signer, @@ -6697,7 +6734,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); @@ -6723,7 +6760,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 5000000000, 0, - 0 + 0, ); // pending_inactive balance would be under threshold => move MIN_COINS_ON_SHARES_POOL coins unlock(delegator1, pool_address, MIN_COINS_ON_SHARES_POOL); @@ -6732,7 +6769,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 4900000000, 0, - 100000000 + 100000000, ); // pending_inactive balance is over threshold @@ -6742,7 +6779,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 5000000000, 0, - 0 + 0, ); // pending_inactive balance would be under threshold => move entire balance @@ -6752,21 +6789,21 @@ module supra_framework::pbo_delegation_pool { pool_address, 5000000000, 0, - 0 + 0, ); // active balance would be under threshold => move entire balance unlock( delegator1, pool_address, - 5000000000 - (MIN_COINS_ON_SHARES_POOL - 1) + 5000000000 - (MIN_COINS_ON_SHARES_POOL - 1), ); assert_delegation( delegator1_address, pool_address, 0, 0, - 5000000000 + 5000000000, ); // active balance would be under threshold => move MIN_COINS_ON_SHARES_POOL coins @@ -6776,7 +6813,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 100000000, 0, - 4900000000 + 4900000000, ); // active balance is over threshold @@ -6786,21 +6823,21 @@ module supra_framework::pbo_delegation_pool { pool_address, 0, 0, - 5000000000 + 5000000000, ); // pending_inactive balance would be under threshold => move entire balance reactivate_stake( delegator1, pool_address, - 4000000000 - (MIN_COINS_ON_SHARES_POOL - 1) + 4000000000 - (MIN_COINS_ON_SHARES_POOL - 1), ); assert_delegation( delegator1_address, pool_address, 3900000001, 0, - 1099999999 + 1099999999, ); // active + pending_inactive balance < 2 * MIN_COINS_ON_SHARES_POOL @@ -6810,7 +6847,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 16 * ONE_SUPRA, 0, - 0 + 0, ); unlock(delegator2, pool_address, MIN_COINS_ON_SHARES_POOL); assert_delegation( @@ -6818,7 +6855,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1500000000, 0, - 100000000 + 100000000, ); reactivate_stake(delegator2, pool_address, MIN_COINS_ON_SHARES_POOL); assert_delegation( @@ -6826,7 +6863,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1600000000, 0, - 0 + 0, ); unlock(delegator2, pool_address, ONE_SUPRA); @@ -6835,7 +6872,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 1500000000, 0, - 100000000 + 100000000, ); reactivate_stake(delegator2, pool_address, 2 * ONE_SUPRA); assert_delegation( @@ -6843,7 +6880,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 16 * ONE_SUPRA, 0, - 0 + 0, ); // share price becomes 1.01 on both pools @@ -6853,7 +6890,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 3800000001, 0, - 1199999999 + 1199999999, ); end_aptos_epoch(); assert_delegation( @@ -6861,7 +6898,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 3838000001, 0, - 1211999998 + 1211999998, ); // pending_inactive balance is over threshold @@ -6871,7 +6908,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 3938000000, 0, - 1111999999 + 1111999999, ); // 1 coin < 1.01 so no shares are redeemed @@ -6881,7 +6918,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 4037999999, 0, - 1012000000 + 1012000000, ); // pending_inactive balance is over threshold @@ -6892,7 +6929,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 4137999998, 0, - 912000001 + 912000001, ); // 1 coin < 1.01 so no shares are redeemed @@ -6902,7 +6939,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 4237999997, 0, - 812000002 + 812000002, ); // pending_inactive balance would be under threshold => move entire balance @@ -6912,7 +6949,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 4337999996, 0, - 712000003 + 712000003, ); // pending_inactive balance would be under threshold => move MIN_COINS_ON_SHARES_POOL coins @@ -6922,7 +6959,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 4237999996, 0, - 812000002 + 812000002, ); // pending_inactive balance would be under threshold => move entire balance @@ -6932,7 +6969,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 4337999995, 0, - 712000003 + 712000003, ); } @@ -6940,9 +6977,9 @@ module supra_framework::pbo_delegation_pool { public entry fun test_get_expected_stake_pool_address(staker: address) { let pool_address = get_expected_stake_pool_address(staker, vector[0x42, 0x42]); assert!( - pool_address - == @0xcb5678be9ec64067c2c3f9f8de78e19509411b053d723d2788ebf1f7ba02f04b, - 0 + pool_address == + @0xcb5678be9ec64067c2c3f9f8de78e19509411b053d723d2788ebf1f7ba02f04b, + 0, ); } @@ -6954,8 +6991,9 @@ module supra_framework::pbo_delegation_pool { inactive_stake: u64, pending_inactive_stake: u64 ) acquires DelegationPool, BeneficiaryForOperator { - let (actual_active, actual_inactive, actual_pending_inactive) = - get_stake(pool_address, delegator_address); + let (actual_active, actual_inactive, actual_pending_inactive) = get_stake( + pool_address, delegator_address + ); assert!(actual_active == active_stake, actual_active); assert!(actual_inactive == inactive_stake, actual_inactive); assert!( @@ -6974,12 +7012,14 @@ module supra_framework::pbo_delegation_pool { ) acquires DelegationPool { assert_delegation_pool_exists(pool_address); let pool = borrow_global(pool_address); - let (withdrawal_exists, withdrawal_olc) = - pending_withdrawal_exists(pool, delegator_address); + let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists( + pool, delegator_address + ); assert!(withdrawal_exists == exists, 0); assert!(withdrawal_olc.index == olc, withdrawal_olc.index); - let (withdrawal_inactive, withdrawal_stake) = - get_pending_withdrawal(pool_address, delegator_address); + let (withdrawal_inactive, withdrawal_stake) = get_pending_withdrawal( + pool_address, delegator_address + ); assert!(withdrawal_inactive == inactive, 0); assert!(withdrawal_stake == stake, withdrawal_stake); } @@ -6995,8 +7035,9 @@ module supra_framework::pbo_delegation_pool { let pool = borrow_global(pool_address); assert!(table::contains(&pool.inactive_shares, olc_with_index(olc)) == exists, 0); if (exists) { - let actual_stake = - total_coins(table::borrow(&pool.inactive_shares, olc_with_index(olc))); + let actual_stake = total_coins( + table::borrow(&pool.inactive_shares, olc_with_index(olc)) + ); assert!(actual_stake == stake, actual_stake); } else { assert!(0 == stake, 0); @@ -7031,7 +7072,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); @@ -7064,7 +7105,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); @@ -7074,14 +7115,7 @@ module supra_framework::pbo_delegation_pool { unlock(delegator, pool_address, 100 * ONE_SUPRA); } - #[ - test( - supra_framework = @supra_framework, - validator = @0x123, - delegator1 = @0x010, - delegator2 = @0x020 - ) - ] + #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] public entry fun test_unlock_mutiple_delegators( supra_framework: &signer, validator: &signer, @@ -7106,7 +7140,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -7138,7 +7172,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -7149,14 +7183,7 @@ module supra_framework::pbo_delegation_pool { unlock(delegator1, pool_address, 600 * ONE_SUPRA); } - #[ - test( - supra_framework = @supra_framework, - validator = @0x123, - delegator1 = @0x010, - delegator2 = @0x020 - ) - ] + #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] #[expected_failure(abort_code = 65561, location = Self)] public entry fun test_multiple_users( supra_framework: &signer, @@ -7186,7 +7213,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -7200,14 +7227,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 1000 * ONE_SUPRA, 0, - 0 + 0, ); assert_delegation( delegator1_address, pool_address, 200999999999, 0, - 0 + 0, ); unlock(delegator2, pool_address, 1000 * ONE_SUPRA); assert_delegation( @@ -7215,7 +7242,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 0, 0, - 1000 * ONE_SUPRA + 1000 * ONE_SUPRA, ); unlock(delegator1, pool_address, 1000 * ONE_SUPRA); assert_delegation( @@ -7223,7 +7250,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 101000000001, 0, - 99999999999 + 99999999999, ); unlock(delegator1, pool_address, 1000 * ONE_SUPRA); } @@ -7233,15 +7260,16 @@ module supra_framework::pbo_delegation_pool { owner: &signer, addition_owner: vector
, threshold: u64 ): address { let owner_addr = aptos_std::signer::address_of(owner); - let multisig_addr = - multisig_account::get_next_multisig_account_address(owner_addr); + let multisig_addr = multisig_account::get_next_multisig_account_address( + owner_addr + ); multisig_account::create_with_owners( owner, addition_owner, threshold, vector[], vector[], - 300 + 300, ); multisig_addr } @@ -7273,7 +7301,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -7281,7 +7309,7 @@ module supra_framework::pbo_delegation_pool { &account::create_signer_for_test(multisig), pool_address, @0x010, - @0x0101 + @0x0101, ); } @@ -7309,7 +7337,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); } @@ -7340,12 +7368,11 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); - let new_multisig = generate_multisig_account( - supra_framework, vector[@0x12234], 2 - ); + let new_multisig = + generate_multisig_account(supra_framework, vector[@0x12234], 2); let multisig_signer = account::create_signer_for_test(new_multisig); let validator_address = signer::address_of(validator); @@ -7354,18 +7381,11 @@ module supra_framework::pbo_delegation_pool { &multisig_signer, pool_address, @0x010, - @0x0101 + @0x0101, ); } - #[ - test( - supra_framework = @supra_framework, - validator = @0x123, - delegator1 = @0x010, - delegator2 = @0x020 - ) - ] + #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] public entry fun test_lose_shares_small( supra_framework: &signer, validator: &signer, @@ -7390,7 +7410,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -7404,7 +7424,7 @@ module supra_framework::pbo_delegation_pool { fixed_point64::create_from_rational(1, 100), one_year_in_secs, reward_period_start_time_in_sec, - fixed_point64::create_from_rational(0, 100) + fixed_point64::create_from_rational(0, 100), ); let index = 0; while (index < 1828) { @@ -7418,7 +7438,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 7933617798152065, 0, - 0 + 0, ); stake::assert_stake_pool(pool_address, 9913173264836398460, 0, 0, 0); unlock(delegator1, pool_address, 1 * ONE_SUPRA); @@ -7427,14 +7447,14 @@ module supra_framework::pbo_delegation_pool { pool_address, 7933617698152064, 0, - 100000000 + 100000000, ); stake::assert_stake_pool( pool_address, 9913173264736398460, 0, 0, - 100000000 + 100000000, ); unlock(delegator1, pool_address, 1 * ONE_SUPRA); stake::assert_stake_pool( @@ -7442,21 +7462,21 @@ module supra_framework::pbo_delegation_pool { 9913173264636398461, 0, 0, - 199999999 + 199999999, ); assert_delegation( delegator1_address, pool_address, 7933617598152064, 0, - 199999999 + 199999999, ); assert_delegation( delegator2_address, pool_address, 7933617798152065133, 0, - 0 + 0, ); unlock(delegator2, pool_address, 1000 * ONE_SUPRA); assert_delegation( @@ -7464,18 +7484,11 @@ module supra_framework::pbo_delegation_pool { pool_address, 7933617698152065134, 0, - 99999999999 + 99999999999, ); } - #[ - test( - supra_framework = @supra_framework, - validator = @0x123, - delegator1 = @0x010, - delegator2 = @0x020 - ) - ] + #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] public entry fun test_lose_shares_large( supra_framework: &signer, validator: &signer, @@ -7500,7 +7513,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -7514,7 +7527,7 @@ module supra_framework::pbo_delegation_pool { fixed_point64::create_from_rational(1, 100), one_year_in_secs, reward_period_start_time_in_sec, - fixed_point64::create_from_rational(0, 100) + fixed_point64::create_from_rational(0, 100), ); let index = 0; while (index < 10) { @@ -7528,7 +7541,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 110462212, 0, - 0 + 0, ); stake::assert_stake_pool(pool_address, 9941599156262803145, 0, 0, 0); unlock(delegator1, pool_address, 1 * ONE_SUPRA); @@ -7537,35 +7550,35 @@ module supra_framework::pbo_delegation_pool { pool_address, 0, 0, - 110462212 + 110462212, ); stake::assert_stake_pool( pool_address, 9941599156152340933, 0, 0, - 110462212 + 110462212, ); stake::assert_stake_pool( pool_address, 9941599156152340933, 0, 0, - 110462212 + 110462212, ); assert_delegation( delegator1_address, pool_address, 0, 0, - 110462212 + 110462212, ); assert_delegation( delegator2_address, pool_address, 9941599128700840588, 0, - 0 + 0, ); unlock(delegator2, pool_address, 1 * ONE_SUPRA); assert_delegation( @@ -7573,7 +7586,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 9941599128600840588, 0, - 100000000 + 100000000, ); } @@ -7604,7 +7617,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let multisig_signer = account::create_signer_for_test(multisig); @@ -7616,21 +7629,21 @@ module supra_framework::pbo_delegation_pool { pool_address, 100 * ONE_SUPRA, 0, - 0 + 0, ); replace_delegator( &multisig_signer, pool_address, @0x010, - new_delegator + new_delegator, ); assert_delegation( new_delegator, pool_address, 100 * ONE_SUPRA, 0, - 0 + 0, ); } @@ -7661,7 +7674,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); @@ -7673,7 +7686,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 200 * ONE_SUPRA, 0, - 100 * ONE_SUPRA + 100 * ONE_SUPRA, ); let multisig_signer = account::create_signer_for_test(multisig); @@ -7682,7 +7695,7 @@ module supra_framework::pbo_delegation_pool { &multisig_signer, pool_address, delegator_address, - new_delegator_address + new_delegator_address, ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); @@ -7691,11 +7704,11 @@ module supra_framework::pbo_delegation_pool { withdraw( &account::create_signer_for_test(new_delegator_address), pool_address, - 100 * ONE_SUPRA + 100 * ONE_SUPRA, ); assert!( coin::balance(new_delegator_address) == (100 * ONE_SUPRA) - 1, - 0 + 0, ); } @@ -7727,7 +7740,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); @@ -7739,7 +7752,7 @@ module supra_framework::pbo_delegation_pool { &multisig_signer, pool_address, delegator_address, - new_delegator_address + new_delegator_address, ); unlock(delegator, pool_address, 100 * ONE_SUPRA); @@ -7777,20 +7790,21 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); let multisig_signer = account::create_signer_for_test(multisig); let new_delegator_address = @0x0101; - let new_delegator_address_signer = - &account::create_signer_for_test(new_delegator_address); + let new_delegator_address_signer = &account::create_signer_for_test( + new_delegator_address + ); replace_delegator( &multisig_signer, pool_address, delegator_address, - new_delegator_address + new_delegator_address, ); unlock(new_delegator_address_signer, pool_address, 100 * ONE_SUPRA); @@ -7799,7 +7813,7 @@ module supra_framework::pbo_delegation_pool { pool_address, 200 * ONE_SUPRA, 0, - 100 * ONE_SUPRA + 100 * ONE_SUPRA, ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); @@ -7808,18 +7822,11 @@ module supra_framework::pbo_delegation_pool { withdraw(new_delegator_address_signer, pool_address, 100 * ONE_SUPRA); assert!( coin::balance(new_delegator_address) == (100 * ONE_SUPRA) - 1, - 0 + 0, ); } - #[ - test( - supra_framework = @supra_framework, - validator = @0x123, - delegator = @0x010, - funder = @0x999 - ) - ] + #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010, funder = @0x999)] /// if delegator is not part of one of the principle stake holder, and not funded with locked stake, /// they can unlock/withdraw without restriction public entry fun test_unlock_withdraw_multiple_funded_delegator_not_part_of_principle_stake_success( @@ -7850,30 +7857,32 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); let new_delegator_address = @0x0215; - let new_delegator_address_signer = - account::create_account_for_test(new_delegator_address); + let new_delegator_address_signer = account::create_account_for_test( + new_delegator_address + ); let new_delegator_address2 = @0x0216; - let new_delegator_address_signer2 = - account::create_account_for_test(new_delegator_address2); + let new_delegator_address_signer2 = account::create_account_for_test( + new_delegator_address2 + ); let funder_signer = account::create_account_for_test(funder); stake::mint(&funder_signer, 100 * ONE_SUPRA); assert!( coin::balance(funder) == (100 * ONE_SUPRA), - 0 + 0, ); fund_delegators_with_stake( &funder_signer, pool_address, vector[new_delegator_address, new_delegator_address2], - vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA], ); assert!(coin::balance(funder) == 0, 0); @@ -7889,13 +7898,13 @@ module supra_framework::pbo_delegation_pool { let new_delegator_balance = coin::balance(new_delegator_address); assert!( new_delegator_balance == (30 * ONE_SUPRA) - 1, - new_delegator_balance + new_delegator_balance, ); withdraw(&new_delegator_address_signer2, pool_address, (70 * ONE_SUPRA)); let new_delegator_balance2 = coin::balance(new_delegator_address2); assert!( new_delegator_balance2 == (70 * ONE_SUPRA) - 1, - new_delegator_balance2 + new_delegator_balance2, ); } @@ -7928,27 +7937,28 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS + LOCKUP_CYCLE_SECONDS, ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); let new_delegator_address = @0x0215; - let new_delegator_address_signer = - account::create_account_for_test(new_delegator_address); + let new_delegator_address_signer = account::create_account_for_test( + new_delegator_address + ); let funder_signer = account::create_signer_for_test(multisig); let funder = signer::address_of(&funder_signer); stake::mint(&funder_signer, 100 * ONE_SUPRA); stake::mint(&new_delegator_address_signer, 100 * ONE_SUPRA); assert!( coin::balance(funder) == (100 * ONE_SUPRA), - 0 + 0, ); assert!( coin::balance(new_delegator_address) == (100 * ONE_SUPRA), - 0 + 0, ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); @@ -7958,7 +7968,7 @@ module supra_framework::pbo_delegation_pool { validator, pool_address, vector[new_delegator_address], - vector[1 * ONE_SUPRA] + vector[1 * ONE_SUPRA], ); } @@ -7990,27 +8000,28 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS + LOCKUP_CYCLE_SECONDS, ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); let new_delegator_address = @0x0215; - let new_delegator_address_signer = - account::create_account_for_test(new_delegator_address); + let new_delegator_address_signer = account::create_account_for_test( + new_delegator_address + ); let funder_signer = account::create_signer_for_test(multisig); let funder = signer::address_of(&funder_signer); stake::mint(&funder_signer, 100 * ONE_SUPRA); stake::mint(&new_delegator_address_signer, 100 * ONE_SUPRA); assert!( coin::balance(funder) == (100 * ONE_SUPRA), - 0 + 0, ); assert!( coin::balance(new_delegator_address) == (100 * ONE_SUPRA), - 0 + 0, ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); @@ -8020,7 +8031,7 @@ module supra_framework::pbo_delegation_pool { &funder_signer, pool_address, vector[new_delegator_address], - vector[0] + vector[0], ); { // if the locked stake is zero, assert that it does not get added to `principle_stake` table @@ -8039,18 +8050,11 @@ module supra_framework::pbo_delegation_pool { let new_delegator_balance = coin::balance(new_delegator_address); assert!( new_delegator_balance == (100 * ONE_SUPRA) - 1, - new_delegator_balance + new_delegator_balance, ); } - #[ - test( - supra_framework = @supra_framework, - validator = @0x123, - delegator = @0x010, - funder = @0x999 - ) - ] + #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010, funder = @0x999)] /// if a single delegator was not part of one of the principle stake holder, and not funded with locked stake, /// they can unlock/withdraw without restriction public entry fun test_unlock_withdraw_funded_delegator_not_part_of_principle_stake_success( @@ -8081,27 +8085,28 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); let new_delegator_address = @0x0215; - let new_delegator_address_signer = - account::create_account_for_test(new_delegator_address); + let new_delegator_address_signer = account::create_account_for_test( + new_delegator_address + ); let funder_signer = account::create_account_for_test(funder); stake::mint(&funder_signer, 100 * ONE_SUPRA); assert!( coin::balance(funder) == (100 * ONE_SUPRA), - 0 + 0, ); fund_delegator_stake( &funder_signer, pool_address, new_delegator_address, - 100 * ONE_SUPRA + 100 * ONE_SUPRA, ); assert!(coin::balance(funder) == 0, 0); @@ -8116,7 +8121,7 @@ module supra_framework::pbo_delegation_pool { let new_delegator_balance = coin::balance(new_delegator_address); assert!( new_delegator_balance == (100 * ONE_SUPRA) - 1, - new_delegator_balance + new_delegator_balance, ); } @@ -8147,20 +8152,21 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12 + 12, ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); let new_delegator_address = @0x0215; - let new_delegator_address_signer = - account::create_account_for_test(new_delegator_address); + let new_delegator_address_signer = account::create_account_for_test( + new_delegator_address + ); stake::mint(&new_delegator_address_signer, 100 * ONE_SUPRA); assert!( coin::balance(new_delegator_address) == (100 * ONE_SUPRA), - 0 + 0, ); add_stake(&new_delegator_address_signer, pool_address, 100 * ONE_SUPRA); @@ -8174,7 +8180,7 @@ module supra_framework::pbo_delegation_pool { withdraw(&new_delegator_address_signer, pool_address, (100 * ONE_SUPRA)); assert!( coin::balance(new_delegator_address) == (100 * ONE_SUPRA) - 1, - 0 + 0, ); } @@ -8207,7 +8213,7 @@ module supra_framework::pbo_delegation_pool { vector[1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let funder_signer = account::create_signer_for_test(multisig); let funder = signer::address_of(&funder_signer); @@ -8221,7 +8227,7 @@ module supra_framework::pbo_delegation_pool { fixed_point64::create_from_rational(1, 100), one_year_in_secs, reward_period_start_time_in_sec, - fixed_point64::create_from_rational(0, 100) + fixed_point64::create_from_rational(0, 100), ); let new_delegator_address = @0x0215; @@ -8231,23 +8237,23 @@ module supra_framework::pbo_delegation_pool { stake::mint(&funder_signer, 100 * ONE_SUPRA); assert!( coin::balance(funder) == (100 * ONE_SUPRA), - 0 + 0, ); fund_delegators_with_locked_stake( &funder_signer, pool_address, vector[new_delegator_address, new_delegator_address2], - vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA], ); assert!(coin::balance(funder) == 0, 0); assert!( get_principle_stake(new_delegator_address, pool_address) == 30 * ONE_SUPRA, - 9 + 9, ); assert!( get_principle_stake(new_delegator_address2, pool_address) == 70 * ONE_SUPRA, - 9 + 9, ); // 3 month @@ -8287,7 +8293,7 @@ module supra_framework::pbo_delegation_pool { vector[1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let funder_signer = account::create_signer_for_test(multisig); let funder = signer::address_of(&funder_signer); @@ -8301,7 +8307,7 @@ module supra_framework::pbo_delegation_pool { fixed_point64::create_from_rational(1, 100), one_year_in_secs, reward_period_start_time_in_sec, - fixed_point64::create_from_rational(0, 100) + fixed_point64::create_from_rational(0, 100), ); let new_delegator_address = @0x0215; @@ -8310,30 +8316,30 @@ module supra_framework::pbo_delegation_pool { stake::mint(&funder_signer, 200 * ONE_SUPRA); assert!( coin::balance(funder) == (200 * ONE_SUPRA), - 0 + 0, ); fund_delegators_with_stake( &funder_signer, pool_address, vector[new_delegator_address, new_delegator_address2], - vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA], ); fund_delegators_with_locked_stake( &funder_signer, pool_address, vector[new_delegator_address, new_delegator_address2], - vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA], ); assert!(coin::balance(funder) == 0, 0); assert!( get_principle_stake(new_delegator_address, pool_address) == 30 * ONE_SUPRA, - 99 + 99, ); assert!( get_principle_stake(new_delegator_address2, pool_address) == 70 * ONE_SUPRA, - 99 + 99, ); let (amount1, _, _) = get_stake(pool_address, new_delegator_address); let (amount2, _, _) = get_stake(pool_address, new_delegator_address2); @@ -8348,8 +8354,9 @@ module supra_framework::pbo_delegation_pool { timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let new_delegator_address_signer = - account::create_signer_for_test(new_delegator_address); + let new_delegator_address_signer = account::create_signer_for_test( + new_delegator_address + ); unlock(&new_delegator_address_signer, pool_address, 30 * ONE_SUPRA); unlock(&new_delegator_address_signer, pool_address, 1 * ONE_SUPRA); } @@ -8381,7 +8388,7 @@ module supra_framework::pbo_delegation_pool { vector[1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let funder_signer = account::create_signer_for_test(multisig); let funder = signer::address_of(&funder_signer); @@ -8395,7 +8402,7 @@ module supra_framework::pbo_delegation_pool { fixed_point64::create_from_rational(1, 100), one_year_in_secs, reward_period_start_time_in_sec, - fixed_point64::create_from_rational(0, 100) + fixed_point64::create_from_rational(0, 100), ); let new_delegator_address = @0x0215; @@ -8404,21 +8411,21 @@ module supra_framework::pbo_delegation_pool { stake::mint(&funder_signer, 200 * ONE_SUPRA); assert!( coin::balance(funder) == (200 * ONE_SUPRA), - 0 + 0, ); fund_delegators_with_stake( &funder_signer, pool_address, vector[new_delegator_address, new_delegator_address2], - vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA], ); fund_delegators_with_locked_stake( &funder_signer, pool_address, vector[new_delegator_address, new_delegator_address2], - vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA], ); assert!(coin::balance(funder) == 0, 0); @@ -8430,8 +8437,9 @@ module supra_framework::pbo_delegation_pool { timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let new_delegator_address_signer = - account::create_signer_for_test(new_delegator_address); + let new_delegator_address_signer = account::create_signer_for_test( + new_delegator_address + ); unlock(&new_delegator_address_signer, pool_address, 30 * ONE_SUPRA); unlock(&new_delegator_address_signer, pool_address, 2 * ONE_SUPRA); } @@ -8464,7 +8472,7 @@ module supra_framework::pbo_delegation_pool { vector[1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -8476,7 +8484,7 @@ module supra_framework::pbo_delegation_pool { fixed_point64::create_from_rational(1, 100), one_year_in_secs, reward_period_start_time_in_sec, - fixed_point64::create_from_rational(0, 100) + fixed_point64::create_from_rational(0, 100), ); let new_delegator_address2 = @0x0216; @@ -8485,14 +8493,14 @@ module supra_framework::pbo_delegation_pool { stake::mint(&funder_signer, 100 * ONE_SUPRA); assert!( coin::balance(funder) == (100 * ONE_SUPRA), - 0 + 0, ); //fund existing delegator_address with locked state, this should still work fund_delegators_with_locked_stake( &funder_signer, pool_address, vector[delegator_address, new_delegator_address2], - vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA], ); assert!(coin::balance(funder) == 0, 0); @@ -8537,7 +8545,7 @@ module supra_framework::pbo_delegation_pool { vector[1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -8549,7 +8557,7 @@ module supra_framework::pbo_delegation_pool { fixed_point64::create_from_rational(1, 100), one_year_in_secs, reward_period_start_time_in_sec, - fixed_point64::create_from_rational(0, 100) + fixed_point64::create_from_rational(0, 100), ); let new_delegator_address2 = @0x0216; @@ -8558,14 +8566,14 @@ module supra_framework::pbo_delegation_pool { stake::mint(&funder_signer, 100 * ONE_SUPRA); assert!( coin::balance(funder) == (100 * ONE_SUPRA), - 0 + 0, ); //fund existing delegator_address with locked state, this should still work fund_delegators_with_locked_stake( &funder_signer, pool_address, vector[delegator_address, new_delegator_address2], - vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA], ); assert!(coin::balance(funder) == 0, 0); //Check that funded delegator was indeed added as a principle stake holder @@ -8575,12 +8583,11 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); let (active_amount, _, _) = get_stake(pool_address, new_delegator_address2); assert!(active_amount == 70 * ONE_SUPRA, active_amount); - let d2_principle_stake = get_principle_stake( - new_delegator_address2, pool_address - ); + let d2_principle_stake = + get_principle_stake(new_delegator_address2, pool_address); assert!( active_amount == d2_principle_stake, - active_amount - d2_principle_stake + active_amount - d2_principle_stake, ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); @@ -8595,8 +8602,9 @@ module supra_framework::pbo_delegation_pool { timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); // 30% of 130, so 39*ONE_SUPRA should be unlockable out of which 13 were already unlocked earlier - let unlock_coin = - can_principle_unlock(delegator_address, pool_address, 26 * ONE_SUPRA); + let unlock_coin = can_principle_unlock( + delegator_address, pool_address, 26 * ONE_SUPRA + ); let amount = cached_unlockable_balance(delegator_address, pool_address); assert!(unlock_coin, amount); @@ -8630,7 +8638,7 @@ module supra_framework::pbo_delegation_pool { vector[1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -8642,7 +8650,7 @@ module supra_framework::pbo_delegation_pool { fixed_point64::create_from_rational(1, 100), one_year_in_secs, reward_period_start_time_in_sec, - fixed_point64::create_from_rational(0, 100) + fixed_point64::create_from_rational(0, 100), ); let new_delegator_address2 = @0x0216; @@ -8651,14 +8659,14 @@ module supra_framework::pbo_delegation_pool { stake::mint(&funder_signer, 100 * ONE_SUPRA); assert!( coin::balance(funder) == (100 * ONE_SUPRA), - 0 + 0, ); //fund existing delegator_address with locked state, this should still work fund_delegators_with_locked_stake( &funder_signer, pool_address, vector[delegator_address, new_delegator_address2], - vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA], ); assert!(coin::balance(funder) == 0, 0); @@ -8713,7 +8721,7 @@ module supra_framework::pbo_delegation_pool { vector[1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -8727,12 +8735,11 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (20 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 10); } @@ -8766,7 +8773,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -8786,88 +8793,285 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (20 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (50 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (60 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (70 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (70 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 14); // after 8 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (80 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (80 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 15); // after 9 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (90 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (90 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 16); // after 10 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (100 * ONE_SUPRA) - 10 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (100 * ONE_SUPRA) - 10, + ); assert!(unlock_coin, 17); // after 11 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock(delegator_address, pool_address, 100 * ONE_SUPRA); + let unlock_coin = can_principle_unlock( + delegator_address, pool_address, 100 * ONE_SUPRA + ); assert!(unlock_coin, 18); } + #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] + #[expected_failure(abort_code = 42, location = Self)] + /// say unlocking schedule is 3 month cliff, monthly unlocking of (2,3,1) tange and principle stake is 100 coins then + /// at the end of 3 months, one can't unlock there principal stacke + /// after 4 months only 90 should remain locked + /// try delaying unlock at this point, which should result in a failure + public entry fun test_increase_last_unlock_period_failure( + supra_framework: &signer, validator: &signer, delegator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + initialize_for_test(supra_framework); + account::create_account_for_test(signer::address_of(validator)); + let delegator_address = signer::address_of(delegator); + let delegator_address_vec = vector[delegator_address]; + let principle_stake = vector[100 * ONE_SUPRA]; + let coin = stake::mint_coins(100 * ONE_SUPRA); + let principle_lockup_time = 7776000; // 3 month cliff + let multisig = generate_multisig_account(validator, vector[@0x12134], 2); + + initialize_test_validator( + validator, + 0, + true, + true, + 0, + delegator_address_vec, + principle_stake, + coin, + option::some(multisig), + vector[2, 3, 1], + 10, + principle_lockup_time, + LOCKUP_CYCLE_SECONDS, // monthly unlocking + ); + let validator_address = signer::address_of(validator); + let pool_address = get_owned_pool_address(validator_address); + + // after 2 month unlock reward + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + // 3 month + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + // after 4 months + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + // Delay unlock by 3 months + let multisig_signer = account::create_signer_for_test(multisig); + admin_increase_last_unlock_period(&multisig_signer, pool_address, 3); + } + + #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] + /// say unlocking schedule is 3 month cliff, monthly unlocking of (2,3,1) tange and principle stake is 100 coins then + /// at the end of 3 months, one can't unlock there principal stacke + /// after 4 months only 90 should remain locked + /// after 5 months only 80 should remain locked and so on + /// then increase unlock period and see if unlocking works as expected + public entry fun test_increase_last_unlock_period_success( + supra_framework: &signer, validator: &signer, delegator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + initialize_for_test(supra_framework); + account::create_account_for_test(signer::address_of(validator)); + let delegator_address = signer::address_of(delegator); + let delegator_address_vec = vector[delegator_address]; + let principle_stake = vector[100 * ONE_SUPRA]; + let coin = stake::mint_coins(100 * ONE_SUPRA); + let principle_lockup_time = 7776000; // 3 month cliff + let multisig = generate_multisig_account(validator, vector[@0x12134], 2); + + initialize_test_validator( + validator, + 0, + true, + true, + 0, + delegator_address_vec, + principle_stake, + coin, + option::some(multisig), + vector[2, 3, 1], + 10, + principle_lockup_time, + LOCKUP_CYCLE_SECONDS, // monthly unlocking + ); + let validator_address = signer::address_of(validator); + let pool_address = get_owned_pool_address(validator_address); + + // after 2 month unlock reward + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + // 3 month + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + // after 4 months + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9, + ); + assert!(unlock_coin, 11); + + // after 5 months + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9, + ); + assert!(unlock_coin, 12); + + // Delay unlock by 3 months + let multisig_signer = account::create_signer_for_test(multisig); + admin_increase_last_unlock_period(&multisig_signer, pool_address, 3); + + // after 6 months + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9, + ); + assert!(unlock_coin, 13); + + // after 7 months + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9, + ); + assert!(unlock_coin, 14); + + // after 8 months + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9, + ); + assert!(unlock_coin, 15); + + // after 9 months + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) - 9, + ); + assert!(unlock_coin, 16); + + // after 10 months + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (70 * ONE_SUPRA) - 10, + ); + assert!(unlock_coin, 17); + + // after 11 months + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + let unlock_coin = can_principle_unlock( + delegator_address, pool_address, 80 * ONE_SUPRA - 9 + ); + assert!(unlock_coin, 18); + + // after 14 months + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS * 3); + end_aptos_epoch(); + let unlock_coin = can_principle_unlock( + delegator_address, pool_address, 100 * ONE_SUPRA + ); + assert!(unlock_coin, 18); + + // after 20 months + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS * 6); + end_aptos_epoch(); + let unlock_coin = can_principle_unlock( + delegator_address, pool_address, 100 * ONE_SUPRA + ); + assert!(unlock_coin, 18); + + } + #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] //Test that `last_unlock_period` increases only up to the point so as to allow //cumulative fraction to become greater or equals one and not more than that @@ -8896,7 +9100,7 @@ module supra_framework::pbo_delegation_pool { vector[1], 2, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -8930,18 +9134,18 @@ module supra_framework::pbo_delegation_pool { timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock(delegator_address, pool_address, (100 * ONE_SUPRA)); + let unlock_coin = can_principle_unlock( + delegator_address, pool_address, (100 * ONE_SUPRA) + ); assert!(unlock_coin, 11); - let unlock_schedule = - borrow_global(pool_address).principle_unlock_schedule; + let unlock_schedule = borrow_global(pool_address).principle_unlock_schedule; let cfraction_upperbound = fixed_point64::create_from_rational(3, 2); assert!( fixed_point64::less( unlock_schedule.cumulative_unlocked_fraction, cfraction_upperbound ), - unlock_schedule.last_unlock_period + unlock_schedule.last_unlock_period, ); } @@ -8972,7 +9176,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -8991,12 +9195,11 @@ module supra_framework::pbo_delegation_pool { timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (20 * ONE_SUPRA) + 1 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) + 1, + ); assert!(unlock_coin, 20); } @@ -9027,7 +9230,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -9047,23 +9250,21 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (20 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (50 * ONE_SUPRA) + 1 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) + 1, + ); assert!(unlock_coin, 20); } @@ -9094,7 +9295,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -9114,34 +9315,31 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (20 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (50 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (60 * ONE_SUPRA) + 1 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) + 1, + ); assert!(unlock_coin, 20); } @@ -9172,7 +9370,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -9192,45 +9390,41 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (20 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (50 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (60 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (70 * ONE_SUPRA) + 1 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (70 * ONE_SUPRA) + 1, + ); assert!(unlock_coin, 20); } @@ -9261,7 +9455,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -9281,56 +9475,51 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (20 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (50 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (60 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (70 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (70 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 14); // after 8 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (80 * ONE_SUPRA) + 1 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (80 * ONE_SUPRA) + 1, + ); assert!(unlock_coin, 20); } @@ -9361,7 +9550,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -9381,67 +9570,61 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (20 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (50 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (60 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (70 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (70 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 14); // after 8 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (80 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (80 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 15); // after 9 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (90 * ONE_SUPRA) + 1 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (90 * ONE_SUPRA) + 1, + ); assert!(unlock_coin, 20); } @@ -9472,7 +9655,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -9492,78 +9675,71 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (20 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (50 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (60 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (70 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (70 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 14); // after 8 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (80 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (80 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 15); // after 9 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (90 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (90 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 16); // after 10 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (100 * ONE_SUPRA) + 1 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (100 * ONE_SUPRA) + 1, + ); assert!(unlock_coin, 20); } @@ -9596,7 +9772,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -9615,8 +9791,9 @@ module supra_framework::pbo_delegation_pool { timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let (_, old_stime, _old_duration, old_last_unlock, old_cfraction) = - get_unlock_schedule(pool_address); + let (_, old_stime, _old_duration, old_last_unlock, old_cfraction) = get_unlock_schedule( + pool_address + ); // Assert that `get_unlock_schedule` is returning expected values assert!(old_stime == principle_lockup_time, old_stime); assert!(old_last_unlock == 0, old_last_unlock); @@ -9630,9 +9807,194 @@ module supra_framework::pbo_delegation_pool { vector[1], 10, principle_lockup_time / 3, - LOCKUP_CYCLE_SECONDS + LOCKUP_CYCLE_SECONDS, + ); + + } + + // Test that after unlock schedule change, one is able to unlock as per + // new schedule but NOT as per old schedule final failure when + // someone other than admin tries to change the schedule + #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] + #[expected_failure(abort_code = 327716, location = Self)] + public entry fun test_change_unlock_schedule_unchecked( + supra_framework: &signer, validator: &signer, delegator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + initialize_for_test(supra_framework); + account::create_account_for_test(signer::address_of(validator)); + let delegator_address = signer::address_of(delegator); + let delegator_address_vec = vector[delegator_address]; + let principle_stake = vector[100 * ONE_SUPRA]; + let coin = stake::mint_coins(100 * ONE_SUPRA); + let principle_lockup_time = 7776000; // 3 month cliff + let multisig = generate_multisig_account(validator, vector[@0x12134], 2); + + initialize_test_validator( + validator, + 0, + true, + true, + 0, + delegator_address_vec, + principle_stake, + coin, + option::some(multisig), + vector[5], + 100, + principle_lockup_time, + LOCKUP_CYCLE_SECONDS, // monthly unlocking + ); + let validator_address = signer::address_of(validator); + let pool_address = get_owned_pool_address(validator_address); + + // after 2 month unlock reward + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + // 3 month + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + // after 12 months + timestamp::fast_forward_seconds(9 * LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + let unlock_coin = can_principle_unlock( + delegator_address, pool_address, (45 * ONE_SUPRA) - 9 + ); + let (_, old_stime, _old_duration, old_last_unlock, old_cfraction) = get_unlock_schedule( + pool_address + ); + assert!(unlock_coin, 11); + // Assert that `get_unlock_schedule` is returning expected values + assert!(old_stime == principle_lockup_time, old_stime); + // 9 monthly unlocks have passed total 12 months including 3 month cliff + assert!(old_last_unlock == 9, old_last_unlock); + let precision_tolerance = fixed_point64::create_from_rational(1, 1000000000); + let tmp_fraction = fixed_point64::create_from_rational(9 * 5, 100); + let old_cfraction_raw = fixed_point64::get_raw_value(old_cfraction); + let tmp_cfraction_raw = fixed_point64::get_raw_value(tmp_fraction); + let diff = + fixed_point64::sub( + fixed_point64::max(old_cfraction, tmp_fraction), + fixed_point64::min(old_cfraction, tmp_fraction), + ); + //assert cumulative fraction is within expected tolerance + assert!(fixed_point64::less_or_equal(diff, precision_tolerance), 91); + + // Change schedule to increase last unlock period by 2 + admin_increase_last_unlock_period( + &account::create_signer_for_test(multisig), + pool_address, + 2, + ); + + let (_, new_stime, _new_duration, new_last_unlock, new_cfraction) = get_unlock_schedule( + pool_address + ); + // assert start time unchanged + assert!( + new_stime == principle_lockup_time, new_stime + ); + // assert last unlock period increased + assert!(new_last_unlock == 11, new_last_unlock); + // assert cumulative fraction unchanged + assert!( + fixed_point64::get_raw_value(new_cfraction) == fixed_point64::get_raw_value( + old_cfraction + ), + 99, + ); + + //Must not be able to unlock next month since unlock period was increased + // total 13 months including 3 month cliff, 10th unlock must not happen since last unlock period increased to 11 + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + let unlock_coin = can_principle_unlock( + delegator_address, pool_address, (46 * ONE_SUPRA) - 9 + ); + assert!(!unlock_coin, 13); + + // total 14 months including 3 month cliff + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + // update schedule to 3 months and 15% unlock instead of 5% + // update last unlock period to 3, to indicate 3 quarters of unlock have passed. + update_unlocking_schedule_unchecked( + &account::create_signer_for_test(multisig), + pool_address, + vector[15], + 100, + principle_lockup_time, + LOCKUP_CYCLE_SECONDS * 3, + 3, + ); + + //assert cumulative fraction unchanged and last unlock updated + let (_, new_stime2, _new_duration2, new_last_unlock2, new_cfraction2) = get_unlock_schedule( + pool_address + ); + assert!( + fixed_point64::get_raw_value(new_cfraction2) == fixed_point64::get_raw_value( + new_cfraction + ), + 99, + ); + assert!(new_last_unlock2 == 3, new_last_unlock2); + + // total 15 months including 3 month cliff, 4 quarters for unlock has passed + // assert this time 15% additional unlock possible + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) - 9, + ); + assert!(unlock_coin, 15); + + // assert that next month unlock would not happen since unlock changed to quarterly schedule + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (61 * ONE_SUPRA) - 9, + ); + assert!(!unlock_coin, 15); + + timestamp::fast_forward_seconds(2 * LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + // total 18 months including 3 month cliff, 5 quarters for unlock has passed but last + // unlock period should be 4 until can_principle_unlock is called + let (_, new_stime3, _new_duration3, new_last_unlock3, new_cfraction3) = get_unlock_schedule( + pool_address ); + assert!(new_last_unlock3 == 4, new_last_unlock3); + // additional 15% unlock should be possible now + unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (75 * ONE_SUPRA) - 9, + ); + assert!(unlock_coin, 16); + // assert that last unlock period is now 5 + let (_, new_stime4, _new_duration4, new_last_unlock4, new_cfraction4) = get_unlock_schedule( + pool_address + ); + assert!(new_last_unlock4 == 5, new_last_unlock4); + update_unlocking_schedule_unchecked( + delegator, + pool_address, + vector[20], + 100, + principle_lockup_time, + LOCKUP_CYCLE_SECONDS * 3, + 9, + ); } // Test that after unlock schedule change, one is able to unlock as per @@ -9664,7 +10026,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -9683,8 +10045,9 @@ module supra_framework::pbo_delegation_pool { timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let (_, old_stime, _old_duration, old_last_unlock, old_cfraction) = - get_unlock_schedule(pool_address); + let (_, old_stime, _old_duration, old_last_unlock, old_cfraction) = get_unlock_schedule( + pool_address + ); // Assert that `get_unlock_schedule` is returning expected values assert!(old_stime == principle_lockup_time, old_stime); assert!(old_last_unlock == 0, old_last_unlock); @@ -9696,24 +10059,24 @@ module supra_framework::pbo_delegation_pool { vector[1], 10, principle_lockup_time / 3, - LOCKUP_CYCLE_SECONDS + LOCKUP_CYCLE_SECONDS, ); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let (_, new_stime, _new_duration, new_last_unlock, new_cfraction) = - get_unlock_schedule(pool_address); + let (_, new_stime, _new_duration, new_last_unlock, new_cfraction) = get_unlock_schedule( + pool_address + ); // Assert that `get_unlock_schedule` is returning expected values assert!( new_stime == principle_lockup_time / 3, - new_stime + new_stime, ); assert!(new_last_unlock == 0, new_last_unlock); assert!(fixed_point64::is_zero(new_cfraction), 99); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (30 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (30 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 11); // after 5 months @@ -9722,13 +10085,13 @@ module supra_framework::pbo_delegation_pool { unlock_coin = can_principle_unlock( delegator_address, pool_address, - (40 * ONE_SUPRA) - 9 + (40 * ONE_SUPRA) - 9, ); assert!(unlock_coin, 12); unlock_coin = can_principle_unlock( delegator_address, pool_address, - (50 * ONE_SUPRA) - 9 + (50 * ONE_SUPRA) - 9, ); assert!(unlock_coin, 13); @@ -9761,7 +10124,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -9781,89 +10144,81 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (20 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (50 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (60 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (70 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (70 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 14); // after 8 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (80 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (80 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 15); // after 9 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (90 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (90 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 16); // after 10 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (100 * ONE_SUPRA) - 10 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (100 * ONE_SUPRA) - 10, + ); assert!(unlock_coin, 17); // after 11 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (100 * ONE_SUPRA) + 1 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (100 * ONE_SUPRA) + 1, + ); assert!(unlock_coin, 20); } @@ -9894,7 +10249,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -9914,23 +10269,21 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (20 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (50 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 12); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); @@ -9941,8 +10294,9 @@ module supra_framework::pbo_delegation_pool { // after 11 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock(delegator_address, pool_address, 100 * ONE_SUPRA); + let unlock_coin = can_principle_unlock( + delegator_address, pool_address, 100 * ONE_SUPRA + ); assert!(unlock_coin, 18); } @@ -9973,7 +10327,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -9993,23 +10347,21 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // After three mounth cliff and one extra mouth, 2/10 of the principle stake (113) = 22.6 can be unlocked. minus 9 for rounding off. - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (22 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (22 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 11); // after 5 months, 5/10 of the principle stake (113) = 56.5 can be unlocked. minus 9 for rounding off. timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (55 * ONE_SUPRA) - 9 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (55 * ONE_SUPRA) - 9, + ); assert!(unlock_coin, 12); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); @@ -10020,8 +10372,9 @@ module supra_framework::pbo_delegation_pool { // after 11 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = - can_principle_unlock(delegator_address, pool_address, 113 * ONE_SUPRA); + let unlock_coin = can_principle_unlock( + delegator_address, pool_address, 113 * ONE_SUPRA + ); assert!(unlock_coin, 18); } @@ -10052,7 +10405,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -10064,12 +10417,11 @@ module supra_framework::pbo_delegation_pool { // After cliff, 5/10 of the principle stake (1000) = 500 can be unlocked. timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS * 2); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (500 * ONE_SUPRA) - 1 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (500 * ONE_SUPRA) - 1, + ); assert!(unlock_coin, 11); } @@ -10100,7 +10452,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -10112,12 +10464,11 @@ module supra_framework::pbo_delegation_pool { // After cliff, 7/10 of the principle stake (1000) = 700 can be unlocked. timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS * 4); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (700 * ONE_SUPRA) - 1 - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (700 * ONE_SUPRA) - 1, + ); assert!(unlock_coin, 11); } @@ -10148,7 +10499,7 @@ module supra_framework::pbo_delegation_pool { vector[2, 3, 1], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS // monthly unlocking + LOCKUP_CYCLE_SECONDS, // monthly unlocking ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -10160,12 +10511,11 @@ module supra_framework::pbo_delegation_pool { // After cliff, all of the principle stake (1000) can be unlocked. timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS * 8); - let unlock_coin = - can_principle_unlock( - delegator_address, - pool_address, - (1000 * ONE_SUPRA) - ); + let unlock_coin = can_principle_unlock( + delegator_address, + pool_address, + (1000 * ONE_SUPRA), + ); assert!(unlock_coin, 11); } @@ -10195,27 +10545,28 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - LOCKUP_CYCLE_SECONDS + LOCKUP_CYCLE_SECONDS, ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); let new_delegator_address = @0x0215; - let new_delegator_address_signer = - account::create_account_for_test(new_delegator_address); + let new_delegator_address_signer = account::create_account_for_test( + new_delegator_address + ); let funder_signer = account::create_signer_for_test(multisig); let funder = signer::address_of(&funder_signer); stake::mint(&funder_signer, 100 * ONE_SUPRA); stake::mint(&new_delegator_address_signer, 100 * ONE_SUPRA); assert!( coin::balance(funder) == (100 * ONE_SUPRA), - 0 + 0, ); assert!( coin::balance(new_delegator_address) == (100 * ONE_SUPRA), - 0 + 0, ); add_stake(&new_delegator_address_signer, pool_address, 100 * ONE_SUPRA); @@ -10229,7 +10580,7 @@ module supra_framework::pbo_delegation_pool { &funder_signer, pool_address, vector[new_delegator_address], - vector[1 * ONE_SUPRA] + vector[1 * ONE_SUPRA], ); // Ensure that its stake is not subject to the pool vesting schedule. assert!(!is_principle_stakeholder(new_delegator_address, pool_address), 1); @@ -10239,7 +10590,7 @@ module supra_framework::pbo_delegation_pool { &funder_signer, pool_address, vector[new_delegator_address], - vector[1 * ONE_SUPRA] + vector[1 * ONE_SUPRA], ); // Ensure that its stake is now subject to the pool vesting schedule. assert!(is_principle_stakeholder(new_delegator_address, pool_address), 0); @@ -10253,17 +10604,15 @@ module supra_framework::pbo_delegation_pool { let delegator_allocation = 10 * ONE_SUPRA; let half_delegator_allocation = delegator_allocation / 2; // A rounding error of 1 Quant is introduced by `unlock`. - let half_delegator_allocation_with_rounding_error = half_delegator_allocation - - 1; - let delegator_allocation_after_rounding_error = - half_delegator_allocation + half_delegator_allocation_with_rounding_error; + let half_delegator_allocation_with_rounding_error = half_delegator_allocation - 1; + let delegator_allocation_after_rounding_error = half_delegator_allocation + half_delegator_allocation_with_rounding_error; // Fund another delegator. fund_delegators_with_stake( &funder_signer, pool_address, vector[delegator], - vector[delegator_allocation] + vector[delegator_allocation], ); // End the current lockup cycle to ensure that the stake fee that is deducted when the stake @@ -10285,7 +10634,7 @@ module supra_framework::pbo_delegation_pool { assert!(inactive == 0, inactive); assert!( pending_inactive == half_delegator_allocation_with_rounding_error, - pending_inactive + pending_inactive, ); // Attempt to lock the full allocation, which should cause the `pending_inactive` allocation @@ -10294,7 +10643,7 @@ module supra_framework::pbo_delegation_pool { &funder_signer, pool_address, vector[delegator], - vector[delegator_allocation_after_rounding_error] + vector[delegator_allocation_after_rounding_error], ); // Ensure that the entire allocation is marked as active again. @@ -10318,17 +10667,16 @@ module supra_framework::pbo_delegation_pool { let delegator_stake = delegator_allocation_after_rounding_error + epoch_reward; // The amount of stake withheld due to the withdrawal and restaking process used to // recover `inactive` stake. - let add_stake_fee = - get_add_stake_fee( - pool_address, half_delegator_allocation + half_epoch_reward - ); + let add_stake_fee = get_add_stake_fee( + pool_address, half_delegator_allocation + half_epoch_reward + ); // Fund another delegator. fund_delegators_with_stake( &funder_signer, pool_address, vector[delegator], - vector[delegator_allocation] + vector[delegator_allocation], ); // End the current lockup cycle to ensure that the stake fee that is deducted when the stake @@ -10352,14 +10700,13 @@ module supra_framework::pbo_delegation_pool { let (active, inactive, pending_inactive) = get_stake(pool_address, delegator); assert!( active == half_delegator_allocation + half_epoch_reward, - active + active, ); // Another rounding error is introduced by the second `unlock`. assert!( - inactive - == half_delegator_allocation_with_rounding_error + half_epoch_reward - - 1, - inactive + inactive == half_delegator_allocation_with_rounding_error + half_epoch_reward + - 1, + inactive, ); assert!(pending_inactive == 0, pending_inactive); @@ -10369,7 +10716,7 @@ module supra_framework::pbo_delegation_pool { &funder_signer, pool_address, vector[delegator], - vector[delegator_stake] + vector[delegator_stake], ); // Ensure that the entire allocation is marked as active again. The fee for adding stake @@ -10397,13 +10744,12 @@ module supra_framework::pbo_delegation_pool { &funder_signer, pool_address, vector[delegator], - vector[delegator_allocation] + vector[delegator_allocation], ); // Calculate the fee for the newly added amount. let add_stake_fee = get_add_stake_fee(pool_address, delegator_allocation); - let expected_total_stake = - expected_active_stake + delegator_allocation - add_stake_fee; + let expected_total_stake = expected_active_stake + delegator_allocation - add_stake_fee; // Ensure that the entire allocation is marked as active. let (active, inactive, pending_inactive) = get_stake(pool_address, delegator); @@ -10417,7 +10763,7 @@ module supra_framework::pbo_delegation_pool { &funder_signer, pool_address, vector[delegator], - vector[more_than_allocated_stake] + vector[more_than_allocated_stake], ); // Ensure that the delegator's `principle_stake` has been updated. @@ -10425,7 +10771,8 @@ module supra_framework::pbo_delegation_pool { let delegator_principle_stake = *table::borrow(&pool.principle_stake, delegator); assert!( delegator_principle_stake == more_than_allocated_stake, - delegator_principle_stake + delegator_principle_stake, ); } } + diff --git a/aptos-move/framework/supra-framework/sources/randomness.move b/aptos-move/framework/supra-framework/sources/randomness.move index 4aa26724473..6cfa6e01e73 100644 --- a/aptos-move/framework/supra-framework/sources/randomness.move +++ b/aptos-move/framework/supra-framework/sources/randomness.move @@ -26,42 +26,46 @@ module supra_framework::randomness { /// `#[randomness]` annotation. Otherwise, malicious users can bias randomness result. const E_API_USE_IS_BIASIBLE: u64 = 1; - const MAX_U256: u256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935; + const MAX_U256: u256 = + 115792089237316195423570985008687907853269984665640564039457584007913129639935; /// 32-byte randomness seed unique to every block. /// This resource is updated in every block prologue. struct PerBlockRandomness has drop, key { epoch: u64, round: u64, - seed: Option>, + seed: Option> } #[event] /// Event emitted every time a public randomness API in this module is called. - struct RandomnessGeneratedEvent has store, drop { - } + struct RandomnessGeneratedEvent has store, drop {} /// Called in genesis.move. /// Must be called in tests to initialize the `PerBlockRandomness` resource. public fun initialize(framework: &signer) { system_addresses::assert_supra_framework(framework); if (!exists(@supra_framework)) { - move_to(framework, PerBlockRandomness { - epoch: 0, - round: 0, - seed: option::none(), - }); + move_to( + framework, + PerBlockRandomness { epoch: 0, round: 0, seed: option::none() } + ); } } #[test_only] - public fun initialize_for_testing(framework: &signer) acquires PerBlockRandomness { + public fun initialize_for_testing(framework: &signer) acquires PerBlockRandomness { initialize(framework); set_seed(x"0000000000000000000000000000000000000000000000000000000000000000"); } /// Invoked in block prologues to update the block-level randomness seed. - public(friend) fun on_new_block(vm: &signer, epoch: u64, round: u64, seed_for_new_block: Option>) acquires PerBlockRandomness { + public(friend) fun on_new_block( + vm: &signer, + epoch: u64, + round: u64, + seed_for_new_block: Option> + ) acquires PerBlockRandomness { system_addresses::assert_vm(vm); if (exists(@supra_framework)) { let randomness = borrow_global_mut(@supra_framework); @@ -303,7 +307,7 @@ module supra_framework::randomness { let values = vector[]; - if(n == 0) { + if (n == 0) { return vector[] }; @@ -354,17 +358,26 @@ module supra_framework::randomness { let a_clone = a; let neg_b = m - b; let a_less = a < neg_b; - take_first(if (a_less) { a + b } else { a_clone - neg_b }, if (!a_less) { a_clone - neg_b } else { a + b }) + take_first( + if (a_less) { a + b } + else { + a_clone - neg_b + }, + if (!a_less) { + a_clone - neg_b + } else { a + b } + ) } - fun take_first(x: u256, _y: u256 ): u256 { x } + fun take_first(x: u256, _y: u256): u256 { + x + } #[verify_only] fun safe_add_mod_for_verification(a: u256, b: u256, m: u256): u256 { let neg_b = m - b; - if (a < neg_b) { - a + b - } else { + if (a < neg_b) { a + b } + else { a - neg_b } } @@ -385,13 +398,69 @@ module supra_framework::randomness { assert!(2 == safe_add_mod(4, 3, 5), 1); assert!(7 == safe_add_mod(3, 4, 9), 1); assert!(7 == safe_add_mod(4, 3, 9), 1); - assert!(0xfffffffffffffffffffffffffffffffffffffffffffffffe == safe_add_mod(0xfffffffffffffffffffffffffffffffffffffffffffffffd, 0x000000000000000000000000000000000000000000000001, 0xffffffffffffffffffffffffffffffffffffffffffffffff), 1); - assert!(0xfffffffffffffffffffffffffffffffffffffffffffffffe == safe_add_mod(0x000000000000000000000000000000000000000000000001, 0xfffffffffffffffffffffffffffffffffffffffffffffffd, 0xffffffffffffffffffffffffffffffffffffffffffffffff), 1); - assert!(0x000000000000000000000000000000000000000000000000 == safe_add_mod(0xfffffffffffffffffffffffffffffffffffffffffffffffd, 0x000000000000000000000000000000000000000000000002, 0xffffffffffffffffffffffffffffffffffffffffffffffff), 1); - assert!(0x000000000000000000000000000000000000000000000000 == safe_add_mod(0x000000000000000000000000000000000000000000000002, 0xfffffffffffffffffffffffffffffffffffffffffffffffd, 0xffffffffffffffffffffffffffffffffffffffffffffffff), 1); - assert!(0x000000000000000000000000000000000000000000000001 == safe_add_mod(0xfffffffffffffffffffffffffffffffffffffffffffffffd, 0x000000000000000000000000000000000000000000000003, 0xffffffffffffffffffffffffffffffffffffffffffffffff), 1); - assert!(0x000000000000000000000000000000000000000000000001 == safe_add_mod(0x000000000000000000000000000000000000000000000003, 0xfffffffffffffffffffffffffffffffffffffffffffffffd, 0xffffffffffffffffffffffffffffffffffffffffffffffff), 1); - assert!(0xfffffffffffffffffffffffffffffffffffffffffffffffd == safe_add_mod(0xfffffffffffffffffffffffffffffffffffffffffffffffe, 0xfffffffffffffffffffffffffffffffffffffffffffffffe, 0xffffffffffffffffffffffffffffffffffffffffffffffff), 1); + assert!( + 0xfffffffffffffffffffffffffffffffffffffffffffffffe + == safe_add_mod( + 0xfffffffffffffffffffffffffffffffffffffffffffffffd, + 0x000000000000000000000000000000000000000000000001, + 0xffffffffffffffffffffffffffffffffffffffffffffffff + ), + 1 + ); + assert!( + 0xfffffffffffffffffffffffffffffffffffffffffffffffe + == safe_add_mod( + 0x000000000000000000000000000000000000000000000001, + 0xfffffffffffffffffffffffffffffffffffffffffffffffd, + 0xffffffffffffffffffffffffffffffffffffffffffffffff + ), + 1 + ); + assert!( + 0x000000000000000000000000000000000000000000000000 + == safe_add_mod( + 0xfffffffffffffffffffffffffffffffffffffffffffffffd, + 0x000000000000000000000000000000000000000000000002, + 0xffffffffffffffffffffffffffffffffffffffffffffffff + ), + 1 + ); + assert!( + 0x000000000000000000000000000000000000000000000000 + == safe_add_mod( + 0x000000000000000000000000000000000000000000000002, + 0xfffffffffffffffffffffffffffffffffffffffffffffffd, + 0xffffffffffffffffffffffffffffffffffffffffffffffff + ), + 1 + ); + assert!( + 0x000000000000000000000000000000000000000000000001 + == safe_add_mod( + 0xfffffffffffffffffffffffffffffffffffffffffffffffd, + 0x000000000000000000000000000000000000000000000003, + 0xffffffffffffffffffffffffffffffffffffffffffffffff + ), + 1 + ); + assert!( + 0x000000000000000000000000000000000000000000000001 + == safe_add_mod( + 0x000000000000000000000000000000000000000000000003, + 0xfffffffffffffffffffffffffffffffffffffffffffffffd, + 0xffffffffffffffffffffffffffffffffffffffffffffffff + ), + 1 + ); + assert!( + 0xfffffffffffffffffffffffffffffffffffffffffffffffd + == safe_add_mod( + 0xfffffffffffffffffffffffffffffffffffffffffffffffe, + 0xfffffffffffffffffffffffffffffffffffffffffffffffe, + 0xffffffffffffffffffffffffffffffffffffffffffffffff + ), + 1 + ); } #[test(fx = @supra_framework)] @@ -524,7 +593,7 @@ module supra_framework::randomness { for (i in 0..n) { let bit = vector::borrow(&present, i); - if(*bit == false) { + if (*bit == false) { return false }; }; @@ -559,12 +628,12 @@ module supra_framework::randomness { let permutations = table_with_length::new, bool>(); // This loop will not exit until all permutations are created - while(table_with_length::length(&permutations) < num_permutations) { + while (table_with_length::length(&permutations) < num_permutations) { let v = permutation(size); assert!(vector::length(&v) == size, 0); assert!(is_permutation(&v), 0); - if(table_with_length::contains(&permutations, v) == false) { + if (table_with_length::contains(&permutations, v) == false) { table_with_length::add(&mut permutations, v, true); } }; diff --git a/aptos-move/framework/supra-framework/sources/reconfiguration.move b/aptos-move/framework/supra-framework/sources/reconfiguration.move index 56b80f9a614..6de6656d852 100644 --- a/aptos-move/framework/supra-framework/sources/reconfiguration.move +++ b/aptos-move/framework/supra-framework/sources/reconfiguration.move @@ -4,6 +4,7 @@ module supra_framework::reconfiguration { use std::error; use std::features; use std::signer; + use supra_framework::leader_ban_registry; use supra_framework::account; use supra_framework::event; @@ -136,6 +137,7 @@ module supra_framework::reconfiguration { // Call stake to compute the new validator set and distribute rewards and transaction fees. stake::on_new_epoch(); + leader_ban_registry::on_new_epoch(); storage_gas::on_reconfig(); assert!(current_time > config_ref.last_reconfiguration_time, error::invalid_state(EINVALID_BLOCK_TIME)); diff --git a/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.move b/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.move index 08b0792ce85..598aecdfaf1 100644 --- a/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.move +++ b/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.move @@ -1,15 +1,24 @@ /// Reconfiguration with DKG helper functions. module supra_framework::reconfiguration_with_dkg { + use std::dkg_committee::{ + new_dkg_committee_from_validator_consensus_info, + new_receiver_committee + }; use std::features; use std::option; + use std::vector; + use supra_framework::evm_config; use supra_framework::automation_registry; + use supra_framework::randomness; use supra_framework::consensus_config; - use supra_framework::dkg; + use supra_framework::supra_dkg; + use supra_framework::dkg_config; use supra_framework::execution_config; use supra_framework::gas_schedule; use supra_framework::jwk_consensus_config; use supra_framework::jwks; use supra_framework::keyless_account; + use supra_framework::leader_ban_registry_config; use supra_framework::randomness_api_v0_config; use supra_framework::randomness_config; use supra_framework::randomness_config_seqnum; @@ -26,30 +35,63 @@ module supra_framework::reconfiguration_with_dkg { /// Trigger a reconfiguration with DKG. /// Do nothing if one is already in progress. public(friend) fun try_start() { - let incomplete_dkg_session = dkg::incomplete_session(); + let incomplete_dkg_session = supra_dkg::incomplete_session(); if (option::is_some(&incomplete_dkg_session)) { let session = option::borrow(&incomplete_dkg_session); - if (dkg::session_dealer_epoch(session) == reconfiguration::current_epoch()) { - return - } + if (supra_dkg::session_dealer_epoch(session) + == reconfiguration::current_epoch()) { return } }; reconfiguration_state::on_reconfig_start(); let cur_epoch = reconfiguration::current_epoch(); - dkg::start( + let randomness_seed = randomness::bytes(32); + + // Get DKG configuration (dealer threshold type and receiver committee configs) + let config = dkg_config::current(); + let receiver_configs = dkg_config::get_receiver_committee_configs(&config); + + // Build receiver committees from config + let receiver_committees = vector[]; + let i = 0; + let len = vector::length(&receiver_configs); + while (i < len) { + let rc = vector::borrow(&receiver_configs, i); + vector::push_back( + &mut receiver_committees, + new_receiver_committee( + dkg_config::get_is_resharing(rc), + dkg_config::get_dkg_threshold_type(rc), + new_dkg_committee_from_validator_consensus_info( + stake::next_epoch_validator_consensus_infos_for_dkg(), + dkg_config::get_committee_threshold_type(rc) + ) + ) + ); + i = i + 1; + }; + + // DKG for configured receiver committees + supra_dkg::start( cur_epoch, - randomness_config::current(), - stake::cur_validator_consensus_infos(), - stake::next_validator_consensus_infos() + randomness_seed, + new_dkg_committee_from_validator_consensus_info( + stake::cur_validator_consensus_infos(), + dkg_config::get_dealer_committee_threshold_type(&config) + ), + receiver_committees ); } + fun set_dkg_meta(dkg_meta: vector) { + supra_dkg::set_dkg_meta(dkg_meta); + } + /// Clear incomplete DKG session, if it exists. /// Apply buffered on-chain configs (except for ValidatorSet, which is done inside `reconfiguration::reconfigure()`). /// Re-enable validator set changes. /// Run the default reconfiguration to enter the new epoch. public(friend) fun finish(framework: &signer) { system_addresses::assert_supra_framework(framework); - dkg::try_clear_incomplete_session(framework); + supra_dkg::try_clear_incomplete_session(framework); consensus_config::on_new_epoch(framework); execution_config::on_new_epoch(framework); supra_config::on_new_epoch(framework); @@ -60,17 +102,20 @@ module supra_framework::reconfiguration_with_dkg { jwk_consensus_config::on_new_epoch(framework); jwks::on_new_epoch(framework); keyless_account::on_new_epoch(framework); + leader_ban_registry_config::on_new_epoch(framework); randomness_config_seqnum::on_new_epoch(framework); randomness_config::on_new_epoch(framework); randomness_api_v0_config::on_new_epoch(framework); evm_genesis_config::on_new_epoch(framework); + dkg_config::on_new_epoch(framework); + evm_config::on_new_epoch(framework); reconfiguration::reconfigure(); } /// Complete the current reconfiguration with DKG. /// Abort if no DKG is in progress. fun finish_with_dkg_result(account: &signer, dkg_result: vector) { - dkg::finish(dkg_result); + supra_dkg::finish(dkg_result); finish(account); } } diff --git a/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.spec.move b/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.spec.move index a739f701806..df407384b74 100644 --- a/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.spec.move +++ b/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.spec.move @@ -12,8 +12,8 @@ spec supra_framework::reconfiguration_with_dkg { requires chain_status::is_operating(); include stake::ResourceRequirement; include stake::GetReconfigStartTimeRequirement; - include features::spec_periodical_reward_rate_decrease_enabled( - ) ==> staking_config::StakingRewardsConfigEnabledRequirement; + include features::spec_periodical_reward_rate_decrease_enabled() ==> + staking_config::StakingRewardsConfigEnabledRequirement; aborts_if false; pragma verify_duration_estimate = 600; // TODO: set because of timeout (property proved). } @@ -62,12 +62,10 @@ spec supra_framework::reconfiguration_with_dkg { } spec finish_with_dkg_result(account: &signer, dkg_result: vector) { - use supra_framework::dkg; + use supra_framework::supra_dkg; pragma verify_duration_estimate = 1500; - include FinishRequirement { - framework: account - }; - requires dkg::has_incomplete_session(); + include FinishRequirement { framework: account }; + requires supra_dkg::has_incomplete_session(); aborts_if false; } } diff --git a/aptos-move/framework/supra-framework/sources/stake.move b/aptos-move/framework/supra-framework/sources/stake.move index a276bc8f51b..0d6c05f6df1 100644 --- a/aptos-move/framework/supra-framework/sources/stake.move +++ b/aptos-move/framework/supra-framework/sources/stake.move @@ -28,6 +28,7 @@ module supra_framework::stake { use aptos_std::big_ordered_map::{Self, BigOrderedMap}; use aptos_std::table::Table; use supra_framework::aggregator_v2::{Self, Aggregator}; + use supra_std::validator_public_keys; use supra_framework::supra_coin::SupraCoin; use supra_framework::account; use supra_framework::coin::{Self, Coin, MintCapability}; @@ -36,6 +37,7 @@ module supra_framework::stake { use supra_framework::system_addresses; use supra_framework::staking_config::{Self, StakingConfig, StakingRewardsConfig}; use supra_framework::chain_status; + use std::dkg_committee; use supra_framework::permissioned_signer; friend supra_framework::block; @@ -43,6 +45,12 @@ module supra_framework::stake { friend supra_framework::reconfiguration; friend supra_framework::reconfiguration_with_dkg; friend supra_framework::transaction_fee; + friend supra_framework::dkg; + friend supra_framework::leader_ban_registry; + friend supra_framework::supra_dkg; + + #[test_only] + friend supra_framework::test_leader_ban_registry; /// Validator Config not published. const EVALIDATOR_CONFIG: u64 = 1; @@ -84,10 +92,18 @@ module supra_framework::stake { const EFEES_TABLE_ALREADY_EXISTS: u64 = 19; /// Validator set change temporarily disabled because of in-progress reconfiguration. Please retry after 1 minute. const ERECONFIGURATION_IN_PROGRESS: u64 = 20; + /// Invalid DKG public key shares. + const EDKG_INVALID_PK_SHARES: u64 = 21; + /// Another validator in the next validator set already uses this consensus public key. + const EDUPLICATE_CONSENSUS_PUBKEY: u64 = 22; + /// Another validator in the next validator set already uses these network addresses. + const EDUPLICATE_NETWORK_ADDRESSES: u64 = 23; + /// The submitted BLS multisig proof-of-possession does not verify against the multisig key. + const EINVALID_PROOF_OF_POSSESSION: u64 = 24; /// Signer does not have permission to perform stake logic. - const ENO_STAKE_PERMISSION: u64 = 28; + const ENO_STAKE_PERMISSION: u64 = 25; /// Transaction fee is not fully distributed at epoch ending. - const ETRANSACTION_FEE_NOT_FULLY_DISTRIBUTED: u64 = 29; + const ETRANSACTION_FEE_NOT_FULLY_DISTRIBUTED: u64 = 26; /// Validator status enum. We can switch to proper enum later once Move supports it. const VALIDATOR_STATUS_PENDING_ACTIVE: u64 = 1; @@ -108,7 +124,7 @@ module supra_framework::stake { /// Having this be separate from the signer for the account that the validator resources are hosted at allows /// modules to have control over a validator. struct OwnerCapability has key, store { - pool_address: address, + pool_address: address } /// Each validator has a separate StakePool resource and can provide a stake. @@ -148,13 +164,14 @@ module supra_framework::stake { add_stake_events: EventHandle, reactivate_stake_events: EventHandle, rotate_consensus_key_events: EventHandle, - update_network_and_fullnode_addresses_events: EventHandle, + update_network_and_fullnode_addresses_events: EventHandle< + UpdateNetworkAndFullnodeAddressesEvent>, increase_lockup_events: EventHandle, join_validator_set_events: EventHandle, distribute_rewards_events: EventHandle, unlock_stake_events: EventHandle, withdraw_stake_events: EventHandle, - leave_validator_set_events: EventHandle, + leave_validator_set_events: EventHandle } /// Validator info stored in validator address. @@ -164,14 +181,14 @@ module supra_framework::stake { // to make it compatible with previous definition, remove later fullnode_addresses: vector, // Index in the active set if the validator corresponding to this stake pool is active. - validator_index: u64, + validator_index: u64 } /// Consensus information per validator, stored in ValidatorSet. struct ValidatorInfo has copy, store, drop { addr: address, voting_power: u64, - config: ValidatorConfig, + config: ValidatorConfig } /// Full ValidatorSet, stored in @supra_framework. @@ -206,75 +223,75 @@ module supra_framework::stake { /// SupraCoin capabilities, set during genesis and stored in @CoreResource account. /// This allows the Stake module to mint rewards to stakers. struct SupraCoinCapabilities has key { - mint_cap: MintCapability, + mint_cap: MintCapability } struct IndividualValidatorPerformance has store, drop { successful_proposals: u64, - failed_proposals: u64, + failed_proposals: u64 } struct ValidatorPerformance has key { - validators: vector, + validators: vector } struct RegisterValidatorCandidateEvent has drop, store { - pool_address: address, + pool_address: address } struct StakeManagementPermission has copy, drop, store {} #[event] struct RegisterValidatorCandidate has drop, store { - pool_address: address, + pool_address: address } struct SetOperatorEvent has drop, store { pool_address: address, old_operator: address, - new_operator: address, + new_operator: address } #[event] struct SetOperator has drop, store { pool_address: address, old_operator: address, - new_operator: address, + new_operator: address } struct AddStakeEvent has drop, store { pool_address: address, - amount_added: u64, + amount_added: u64 } #[event] struct AddStake has drop, store { pool_address: address, - amount_added: u64, + amount_added: u64 } struct ReactivateStakeEvent has drop, store { pool_address: address, - amount: u64, + amount: u64 } #[event] struct ReactivateStake has drop, store { pool_address: address, - amount: u64, + amount: u64 } struct RotateConsensusKeyEvent has drop, store { pool_address: address, old_consensus_pubkey: vector, - new_consensus_pubkey: vector, + new_consensus_pubkey: vector } #[event] struct RotateConsensusKey has drop, store { pool_address: address, old_consensus_pubkey: vector, - new_consensus_pubkey: vector, + new_consensus_pubkey: vector } struct UpdateNetworkAndFullnodeAddressesEvent has drop, store { @@ -282,7 +299,7 @@ module supra_framework::stake { old_network_addresses: vector, new_network_addresses: vector, old_fullnode_addresses: vector, - new_fullnode_addresses: vector, + new_fullnode_addresses: vector } #[event] @@ -291,78 +308,78 @@ module supra_framework::stake { old_network_addresses: vector, new_network_addresses: vector, old_fullnode_addresses: vector, - new_fullnode_addresses: vector, + new_fullnode_addresses: vector } struct IncreaseLockupEvent has drop, store { pool_address: address, old_locked_until_secs: u64, - new_locked_until_secs: u64, + new_locked_until_secs: u64 } #[event] struct IncreaseLockup has drop, store { pool_address: address, old_locked_until_secs: u64, - new_locked_until_secs: u64, + new_locked_until_secs: u64 } struct JoinValidatorSetEvent has drop, store { - pool_address: address, + pool_address: address } #[event] struct JoinValidatorSet has drop, store { - pool_address: address, + pool_address: address } struct DistributeRewardsEvent has drop, store { pool_address: address, - rewards_amount: u64, + rewards_amount: u64 } #[event] /// The amount includes transaction fee and staking rewards. struct DistributeRewards has drop, store { pool_address: address, - rewards_amount: u64, + rewards_amount: u64 } struct UnlockStakeEvent has drop, store { pool_address: address, - amount_unlocked: u64, + amount_unlocked: u64 } #[event] struct UnlockStake has drop, store { pool_address: address, - amount_unlocked: u64, + amount_unlocked: u64 } struct WithdrawStakeEvent has drop, store { pool_address: address, - amount_withdrawn: u64, + amount_withdrawn: u64 } #[event] struct WithdrawStake has drop, store { pool_address: address, - amount_withdrawn: u64, + amount_withdrawn: u64 } struct LeaveValidatorSetEvent has drop, store { - pool_address: address, + pool_address: address } #[event] struct LeaveValidatorSet has drop, store { - pool_address: address, + pool_address: address } #[deprecated] /// DEPRECATED struct ValidatorFees has key { - fees_table: Table>, + fees_table: Table> } /// Permissions @@ -392,9 +409,8 @@ module supra_framework::stake { public fun get_remaining_lockup_secs(pool_address: address): u64 acquires StakePool { assert_stake_pool_exists(pool_address); let lockup_time = borrow_global(pool_address).locked_until_secs; - if (lockup_time <= timestamp::now_seconds()) { - 0 - } else { + if (lockup_time <= timestamp::now_seconds()) { 0 } + else { lockup_time - timestamp::now_seconds() } } @@ -409,7 +425,7 @@ module supra_framework::stake { coin::value(&stake_pool.active), coin::value(&stake_pool.inactive), coin::value(&stake_pool.pending_active), - coin::value(&stake_pool.pending_inactive), + coin::value(&stake_pool.pending_inactive) ) } @@ -417,11 +433,17 @@ module supra_framework::stake { /// Returns the validator's state. public fun get_validator_state(pool_address: address): u64 acquires ValidatorSet { let validator_set = borrow_global(@supra_framework); - if (option::is_some(&find_validator(&validator_set.pending_active, pool_address))) { + if (option::is_some( + &find_validator(&validator_set.pending_active, pool_address) + )) { VALIDATOR_STATUS_PENDING_ACTIVE - } else if (option::is_some(&find_validator(&validator_set.active_validators, pool_address))) { + } else if (option::is_some( + &find_validator(&validator_set.active_validators, pool_address) + )) { VALIDATOR_STATUS_ACTIVE - } else if (option::is_some(&find_validator(&validator_set.pending_inactive, pool_address))) { + } else if (option::is_some( + &find_validator(&validator_set.pending_inactive, pool_address) + )) { VALIDATOR_STATUS_PENDING_INACTIVE } else { VALIDATOR_STATUS_INACTIVE @@ -431,17 +453,20 @@ module supra_framework::stake { #[view] /// Return the voting power of the validator in the current epoch. /// This is the same as the validator's total active and pending_inactive stake. - public fun get_current_epoch_voting_power(pool_address: address): u64 acquires StakePool, ValidatorSet { + public fun get_current_epoch_voting_power( + pool_address: address + ): u64 acquires StakePool, ValidatorSet { assert_stake_pool_exists(pool_address); let validator_state = get_validator_state(pool_address); // Both active and pending inactive validators can still vote in the current epoch. - if (validator_state == VALIDATOR_STATUS_ACTIVE || validator_state == VALIDATOR_STATUS_PENDING_INACTIVE) { - let active_stake = coin::value(&borrow_global(pool_address).active); - let pending_inactive_stake = coin::value(&borrow_global(pool_address).pending_inactive); + if (validator_state == VALIDATOR_STATUS_ACTIVE + || validator_state == VALIDATOR_STATUS_PENDING_INACTIVE) { + let active_stake = + coin::value(&borrow_global(pool_address).active); + let pending_inactive_stake = + coin::value(&borrow_global(pool_address).pending_inactive); active_stake + pending_inactive_stake - } else { - 0 - } + } else { 0 } } #[view] @@ -472,10 +497,18 @@ module supra_framework::stake { #[view] /// Return the number of successful and failed proposals for the proposal at the given validator index. - public fun get_current_epoch_proposal_counts(validator_index: u64): (u64, u64) acquires ValidatorPerformance { - let validator_performances = &borrow_global(@supra_framework).validators; - let validator_performance = vector::borrow(validator_performances, validator_index); - (validator_performance.successful_proposals, validator_performance.failed_proposals) + public fun get_current_epoch_proposal_counts( + validator_index: u64 + ): (u64, u64) acquires ValidatorPerformance { + let validator_performances = + &borrow_global(@supra_framework).validators; + let validator_performance = vector::borrow( + validator_performances, validator_index + ); + ( + validator_performance.successful_proposals, + validator_performance.failed_proposals + ) } #[view] @@ -485,7 +518,11 @@ module supra_framework::stake { ): (vector, vector, vector) acquires ValidatorConfig { assert_stake_pool_exists(pool_address); let validator_config = borrow_global(pool_address); - (validator_config.consensus_pubkey, validator_config.network_addresses, validator_config.fullnode_addresses) + ( + validator_config.consensus_pubkey, + validator_config.network_addresses, + validator_config.fullnode_addresses + ) } #[view] @@ -512,31 +549,102 @@ module supra_framework::stake { public(friend) fun initialize(supra_framework: &signer) { system_addresses::assert_supra_framework(supra_framework); - move_to(supra_framework, ValidatorSet { - consensus_scheme: 0, - active_validators: vector::empty(), - pending_active: vector::empty(), - pending_inactive: vector::empty(), - total_voting_power: 0, - total_joining_power: 0, - }); + move_to( + supra_framework, + ValidatorSet { + consensus_scheme: 0, + active_validators: vector::empty(), + pending_active: vector::empty(), + pending_inactive: vector::empty(), + total_voting_power: 0, + total_joining_power: 0 + } + ); - move_to(supra_framework, ValidatorPerformance { - validators: vector::empty(), - }); + move_to(supra_framework, ValidatorPerformance { validators: vector::empty() }); } /// This is only called during Genesis, which is where MintCapability can be created. /// Beyond genesis, no one can create SupraCoin mint/burn capabilities. - public(friend) fun store_supra_coin_mint_cap(supra_framework: &signer, mint_cap: MintCapability) { + public(friend) fun store_supra_coin_mint_cap( + supra_framework: &signer, mint_cap: MintCapability + ) { system_addresses::assert_supra_framework(supra_framework); move_to(supra_framework, SupraCoinCapabilities { mint_cap }) } + /// To get validator pool address from validator index + public(friend) fun get_pool_address_from_index( + index: u64 + ): Option
acquires ValidatorSet { + if (exists(@supra_framework)) { + let validator_set = borrow_global(@supra_framework); + // it can happen that some validator may added a leave request in between + // this can change the order of indexes in active validator + // so need to iterate through all until find pool address in active and pending_active + let (is_index_exist, i) = vector::find( + &validator_set.active_validators, + |v| { + let v: &ValidatorInfo = v; + v.config.validator_index == index + } + ); + if (is_index_exist) { + let v_info = vector::borrow(&validator_set.active_validators, i); + return option::some(v_info.addr) + }; + let (is_index_exist, i) = vector::find( + &validator_set.pending_inactive, + |v| { + let v: &ValidatorInfo = v; + v.config.validator_index == index + } + ); + if (is_index_exist) { + let v_info = vector::borrow(&validator_set.pending_inactive, i); + return option::some(v_info.addr) + }; + }; + option::none() + } + + /// Returns committee size + public(friend) fun get_committee_size(): u64 acquires ValidatorSet { + let commitee_size = 0; + if (exists(@supra_framework)) { + let validator_set = borrow_global(@supra_framework); + commitee_size = vector::length(&validator_set.active_validators) + + vector::length(&validator_set.pending_inactive); + }; + commitee_size + } + + /// Returns pool addresses of current committee including pending inactive + public(friend) fun get_committee_pool_addresses(): vector
acquires ValidatorSet { + let pool_addresses = vector::empty(); + if (exists(@supra_framework)) { + let validator_set = borrow_global(@supra_framework); + vector::for_each_ref( + &validator_set.active_validators, + |validator_info| { + let validator_info: &ValidatorInfo = validator_info; + vector::push_back(&mut pool_addresses, validator_info.addr); + } + ); + vector::for_each_ref( + &validator_set.pending_inactive, + |validator_info| { + let validator_info: &ValidatorInfo = validator_info; + vector::push_back(&mut pool_addresses, validator_info.addr); + } + ); + }; + pool_addresses + } + /// Allow on chain governance to remove validators from the validator set. public fun remove_validators( - supra_framework: &signer, - validators: &vector
, + supra_framework: &signer, validators: &vector
) acquires ValidatorSet { assert_reconfig_not_in_progress(); system_addresses::assert_supra_framework(supra_framework); @@ -557,14 +665,17 @@ module supra_framework::stake { invariant spec_validator_indices_are_valid(active_validators); invariant spec_validators_are_initialized(pending_inactive); invariant spec_validator_indices_are_valid(pending_inactive); - invariant ghost_active_num + ghost_pending_inactive_num == len(active_validators) + len(pending_inactive); + invariant ghost_active_num + ghost_pending_inactive_num + == len(active_validators) + len(pending_inactive); }; i < len_validators }) { let validator = *vector::borrow(validators, i); let validator_index = find_validator(active_validators, validator); if (option::is_some(&validator_index)) { - let validator_info = vector::swap_remove(active_validators, *option::borrow(&validator_index)); + let validator_info = vector::swap_remove( + active_validators, *option::borrow(&validator_index) + ); vector::push_back(pending_inactive, validator_info); spec { update ghost_active_num = ghost_active_num - 1; @@ -616,16 +727,19 @@ module supra_framework::stake { owner: &signer, initial_stake_amount: u64, operator: address, - voter: address, + voter: address ) acquires AllowedValidators, OwnerCapability, StakePool, ValidatorSet { check_stake_permission(owner); initialize_owner(owner); - move_to(owner, ValidatorConfig { - consensus_pubkey: vector::empty(), - network_addresses: vector::empty(), - fullnode_addresses: vector::empty(), - validator_index: 0, - }); + move_to( + owner, + ValidatorConfig { + consensus_pubkey: vector::empty(), + network_addresses: vector::empty(), + fullnode_addresses: vector::empty(), + validator_index: 0 + } + ); if (initial_stake_amount != 0) { add_stake(owner, initial_stake_amount); @@ -645,52 +759,245 @@ module supra_framework::stake { account: &signer, consensus_pubkey: vector, network_addresses: vector, - fullnode_addresses: vector, - ) acquires AllowedValidators { + fullnode_addresses: vector + ) acquires AllowedValidators, ValidatorSet, ValidatorConfig { check_stake_permission(account); - // Checks the public key is valid to prevent rogue-key attacks. - let valid_public_key = ed25519::new_validated_public_key_from_bytes(consensus_pubkey); - assert!(option::is_some(&valid_public_key), error::invalid_argument(EINVALID_PUBLIC_KEY)); + initialize_validator_internal( + account, + consensus_pubkey, + network_addresses, + fullnode_addresses, + false + ); + } - initialize_owner(account); - move_to(account, ValidatorConfig { + /// Initialize a validator during genesis. Identical to `initialize_validator` except that the + /// consensus key blob is trusted genesis output and therefore carries no operator + /// proof-of-possession (mirrors `rotate_consensus_key` / `rotate_consensus_key_genesis`). + public(friend) fun initialize_validator_genesis( + account: &signer, + consensus_pubkey: vector, + network_addresses: vector, + fullnode_addresses: vector + ) acquires AllowedValidators, ValidatorSet, ValidatorConfig { + initialize_validator_internal( + account, consensus_pubkey, network_addresses, fullnode_addresses, - validator_index: 0, - }); + true + ); + } + + fun initialize_validator_internal( + account: &signer, + consensus_pubkey: vector, + network_addresses: vector, + fullnode_addresses: vector, + genesis: bool + ) acquires AllowedValidators, ValidatorSet, ValidatorConfig { + // Verify the keys (and, for operator submissions, the appended BLS multisig PoP) and keep + // only the canonical key bytes (any appended PoP is stripped before storage). + let consensus_pubkey = validate_consensus_public_key(consensus_pubkey, genesis); + let account_addr = signer::address_of(account); + assert_consensus_pubkey_unique_in_next_validator_set( + account_addr, &consensus_pubkey + ); + assert_network_addresses_unique_in_next_validator_set( + account_addr, &network_addresses + ); + initialize_owner(account); + move_to( + account, + ValidatorConfig { + consensus_pubkey, + network_addresses, + fullnode_addresses, + validator_index: 0 + } + ); + } + + // Verifies a submitted consensus key blob and returns the canonical key bytes to store. + // + // A legacy consensus key (a bare ed25519 public key) is only accepted before the v2 identity + // feature flag is activated; it has no aggregatable BLS key and so carries no proof-of-possession. + // + // Every other (new-format `ValidatorPublicKeys`) submission -- whether under v2 or via the + // pre-v2 early-migration path -- must carry an appended BLS12-381 proof-of-possession for the + // BLS multisig key (operator / non-genesis submissions only; genesis output is trusted and + // carries no PoP). The multisig key is the only operator-submitted key exposed to rogue-key + // attacks (the class-group key carries its own ZK PoP verified by its native, the ed25519 keys + // are non-aggregated, and the BLS threshold shares are DKG-produced). We split off and verify + // that PoP (see `validator_public_keys::split_consensus_key_and_pop`) and return the key bytes + // with the PoP stripped, so the stored key keeps its canonical format. PoP enforcement is tied + // to the key format, not the v2 flag, so a key registered during the pre-v2 migration window + // cannot skip it. + // + // Deserialization (`validator_public_keys_from_bytes`) only reconstructs each key's bytes + // without running the per-key validation natives, so we also re-validate every static key via + // `validate_static_keys` (on-curve / subgroup / valid-encoding checks). + fun validate_consensus_public_key( + consensus_pubkey: vector, genesis: bool + ): vector { + // Legacy format (only acceptable before v2): a bare ed25519 key with no aggregatable BLS + // key, hence no PoP. Accept and store it unchanged. + if (!std::features::supra_validator_identity_v2_enabled()) { + let maybe_legacy = + ed25519::new_validated_public_key_from_bytes(consensus_pubkey); + if (option::is_some(&maybe_legacy)) { + return consensus_pubkey + }; + }; + + // New identity format (v2, or a pre-v2 early-migration submission). Operator (non-genesis) + // submissions carry an appended BLS multisig PoP; verify and strip it. Genesis is exempt. + let (keys_bytes, maybe_pop) = + if (genesis) { + (consensus_pubkey, option::none>()) + } else { + let (keys_bytes, pop) = + validator_public_keys::split_consensus_key_and_pop(consensus_pubkey); + (keys_bytes, option::some(pop)) + }; + + let valid_public_keys = + validator_public_keys::validator_public_keys_from_bytes(keys_bytes); + + if (option::is_some(&maybe_pop)) { + assert!( + validator_public_keys::verify_bls_multisig_pop( + &valid_public_keys, option::extract(&mut maybe_pop) + ), + error::invalid_argument(EINVALID_PROOF_OF_POSSESSION) + ); + }; + + assert!( + validator_public_keys::validate_static_keys(&valid_public_keys), + error::invalid_argument(EINVALID_PUBLIC_KEY) + ); + + keys_bytes + } + + /// Aborts if any validator other than `self_addr` in the next validator set + /// (the union of `active_validators` and `pending_active`) already uses + /// `consensus_pubkey` as its latest on-chain consensus key. + fun assert_consensus_pubkey_unique_in_next_validator_set( + self_addr: address, consensus_pubkey: &vector + ) acquires ValidatorSet, ValidatorConfig { + let validator_set = borrow_global(@supra_framework); + assert_consensus_pubkey_unique_in_validator_list( + self_addr, consensus_pubkey, &validator_set.active_validators + ); + assert_consensus_pubkey_unique_in_validator_list( + self_addr, consensus_pubkey, &validator_set.pending_active + ); + } + + fun assert_consensus_pubkey_unique_in_validator_list( + self_addr: address, + consensus_pubkey: &vector, + validators: &vector + ) acquires ValidatorConfig { + let len = vector::length(validators); + let i = 0; + while (i < len) { + let other = vector::borrow(validators, i); + if (other.addr != self_addr && exists(other.addr)) { + let other_config = borrow_global(other.addr); + assert!( + other_config.consensus_pubkey != *consensus_pubkey, + error::invalid_argument(EDUPLICATE_CONSENSUS_PUBKEY) + ); + }; + i = i + 1; + }; + } + + /// Aborts if any validator other than `self_addr` in the next validator set + /// already uses `network_addresses`. Empty `network_addresses` is treated + /// as "unset" and skips the check. + fun assert_network_addresses_unique_in_next_validator_set( + self_addr: address, network_addresses: &vector + ) acquires ValidatorSet, ValidatorConfig { + if (vector::is_empty(network_addresses)) { return }; + let validator_set = borrow_global(@supra_framework); + assert_network_addresses_unique_in_validator_list( + self_addr, network_addresses, &validator_set.active_validators + ); + assert_network_addresses_unique_in_validator_list( + self_addr, network_addresses, &validator_set.pending_active + ); + } + + fun assert_network_addresses_unique_in_validator_list( + self_addr: address, + network_addresses: &vector, + validators: &vector + ) acquires ValidatorConfig { + let len = vector::length(validators); + let i = 0; + while (i < len) { + let other = vector::borrow(validators, i); + if (other.addr != self_addr && exists(other.addr)) { + let other_config = borrow_global(other.addr); + assert!( + other_config.network_addresses != *network_addresses, + error::invalid_argument(EDUPLICATE_NETWORK_ADDRESSES) + ); + }; + i = i + 1; + }; } fun initialize_owner(owner: &signer) acquires AllowedValidators { check_stake_permission(owner); let owner_address = signer::address_of(owner); assert!(is_allowed(owner_address), error::not_found(EINELIGIBLE_VALIDATOR)); - assert!(!stake_pool_exists(owner_address), error::already_exists(EALREADY_REGISTERED)); - - move_to(owner, StakePool { - active: coin::zero(), - pending_active: coin::zero(), - pending_inactive: coin::zero(), - inactive: coin::zero(), - locked_until_secs: 0, - operator_address: owner_address, - delegated_voter: owner_address, - // Events. - initialize_validator_events: account::new_event_handle(owner), - set_operator_events: account::new_event_handle(owner), - add_stake_events: account::new_event_handle(owner), - reactivate_stake_events: account::new_event_handle(owner), - rotate_consensus_key_events: account::new_event_handle(owner), - update_network_and_fullnode_addresses_events: account::new_event_handle( - owner - ), - increase_lockup_events: account::new_event_handle(owner), - join_validator_set_events: account::new_event_handle(owner), - distribute_rewards_events: account::new_event_handle(owner), - unlock_stake_events: account::new_event_handle(owner), - withdraw_stake_events: account::new_event_handle(owner), - leave_validator_set_events: account::new_event_handle(owner), - }); + assert!( + !stake_pool_exists(owner_address), + error::already_exists(EALREADY_REGISTERED) + ); + + move_to( + owner, + StakePool { + active: coin::zero(), + pending_active: coin::zero(), + pending_inactive: coin::zero(), + inactive: coin::zero(), + locked_until_secs: 0, + operator_address: owner_address, + delegated_voter: owner_address, + // Events. + initialize_validator_events: account::new_event_handle< + RegisterValidatorCandidateEvent>(owner), + set_operator_events: account::new_event_handle(owner), + add_stake_events: account::new_event_handle(owner), + reactivate_stake_events: account::new_event_handle( + owner + ), + rotate_consensus_key_events: account::new_event_handle< + RotateConsensusKeyEvent>(owner), + update_network_and_fullnode_addresses_events: account::new_event_handle< + UpdateNetworkAndFullnodeAddressesEvent>(owner), + increase_lockup_events: account::new_event_handle( + owner + ), + join_validator_set_events: account::new_event_handle( + owner + ), + distribute_rewards_events: account::new_event_handle( + owner + ), + unlock_stake_events: account::new_event_handle(owner), + withdraw_stake_events: account::new_event_handle(owner), + leave_validator_set_events: account::new_event_handle< + LeaveValidatorSetEvent>(owner) + } + ); move_to(owner, OwnerCapability { pool_address: owner_address }); } @@ -705,9 +1012,14 @@ module supra_framework::stake { /// Deposit `owner_cap` into `account`. This requires `account` to not already have ownership of another /// staking pool. - public fun deposit_owner_cap(owner: &signer, owner_cap: OwnerCapability) { + public fun deposit_owner_cap( + owner: &signer, owner_cap: OwnerCapability + ) { check_stake_permission(owner); - assert!(!exists(signer::address_of(owner)), error::not_found(EOWNER_CAP_ALREADY_EXISTS)); + assert!( + !exists(signer::address_of(owner)), + error::not_found(EOWNER_CAP_ALREADY_EXISTS) + ); move_to(owner, owner_cap); } @@ -717,7 +1029,9 @@ module supra_framework::stake { } /// Allows an owner to change the operator of the stake pool. - public entry fun set_operator(owner: &signer, new_operator: address) acquires OwnerCapability, StakePool { + public entry fun set_operator( + owner: &signer, new_operator: address + ) acquires OwnerCapability, StakePool { check_stake_permission(owner); let owner_address = signer::address_of(owner); assert_owner_cap_exists(owner_address); @@ -726,7 +1040,9 @@ module supra_framework::stake { } /// Allows an account with ownership capability to change the operator of the stake pool. - public fun set_operator_with_cap(owner_cap: &OwnerCapability, new_operator: address) acquires StakePool { + public fun set_operator_with_cap( + owner_cap: &OwnerCapability, new_operator: address + ) acquires StakePool { let pool_address = owner_cap.pool_address; assert_stake_pool_exists(pool_address); let stake_pool = borrow_global_mut(pool_address); @@ -754,7 +1070,9 @@ module supra_framework::stake { } /// Allows an owner to change the delegated voter of the stake pool. - public entry fun set_delegated_voter(owner: &signer, new_voter: address) acquires OwnerCapability, StakePool { + public entry fun set_delegated_voter( + owner: &signer, new_voter: address + ) acquires OwnerCapability, StakePool { check_stake_permission(owner); let owner_address = signer::address_of(owner); assert_owner_cap_exists(owner_address); @@ -763,7 +1081,9 @@ module supra_framework::stake { } /// Allows an owner to change the delegated voter of the stake pool. - public fun set_delegated_voter_with_cap(owner_cap: &OwnerCapability, new_voter: address) acquires StakePool { + public fun set_delegated_voter_with_cap( + owner_cap: &OwnerCapability, new_voter: address + ) acquires StakePool { let pool_address = owner_cap.pool_address; assert_stake_pool_exists(pool_address); let stake_pool = borrow_global_mut(pool_address); @@ -771,7 +1091,9 @@ module supra_framework::stake { } /// Add `amount` of coins from the `account` owning the StakePool. - public entry fun add_stake(owner: &signer, amount: u64) acquires OwnerCapability, StakePool, ValidatorSet { + public entry fun add_stake( + owner: &signer, amount: u64 + ) acquires OwnerCapability, StakePool, ValidatorSet { check_stake_permission(owner); let owner_address = signer::address_of(owner); assert_owner_cap_exists(owner_address); @@ -780,7 +1102,9 @@ module supra_framework::stake { } /// Add `coins` into `pool_address`. this requires the corresponding `owner_cap` to be passed in. - public fun add_stake_with_cap(owner_cap: &OwnerCapability, coins: Coin) acquires StakePool, ValidatorSet { + public fun add_stake_with_cap( + owner_cap: &OwnerCapability, coins: Coin + ) acquires StakePool, ValidatorSet { assert_reconfig_not_in_progress(); let pool_address = owner_cap.pool_address; assert_stake_pool_exists(pool_address); @@ -796,8 +1120,11 @@ module supra_framework::stake { // Inactive validator's total stake will be tracked when they join the validator set. let validator_set = borrow_global(@supra_framework); // Search directly rather using get_validator_state to save on unnecessary loops. - if (option::is_some(&find_validator(&validator_set.active_validators, pool_address)) || - option::is_some(&find_validator(&validator_set.pending_active, pool_address))) { + if (option::is_some( + &find_validator(&validator_set.active_validators, pool_address) + ) || option::is_some( + &find_validator(&validator_set.pending_active, pool_address) + )) { update_voting_power_increase(amount); }; @@ -810,9 +1137,12 @@ module supra_framework::stake { coin::merge(&mut stake_pool.active, coins); }; - let (_, maximum_stake) = staking_config::get_required_stake(&staking_config::get()); + let (_, maximum_stake) = + staking_config::get_required_stake(&staking_config::get()); let voting_power = get_next_epoch_voting_power(stake_pool); - assert!(voting_power <= maximum_stake, error::invalid_argument(ESTAKE_EXCEEDS_MAX)); + assert!( + voting_power <= maximum_stake, error::invalid_argument(ESTAKE_EXCEEDS_MAX) + ); if (std::features::module_event_migration_enabled()) { event::emit( @@ -842,7 +1172,9 @@ module supra_framework::stake { reactivate_stake_with_cap(ownership_cap, amount); } - public fun reactivate_stake_with_cap(owner_cap: &OwnerCapability, amount: u64) acquires StakePool { + public fun reactivate_stake_with_cap( + owner_cap: &OwnerCapability, amount: u64 + ) acquires StakePool { assert_reconfig_not_in_progress(); let pool_address = owner_cap.pool_address; assert_stake_pool_exists(pool_address); @@ -880,26 +1212,66 @@ module supra_framework::stake { operator: &signer, pool_address: address, new_consensus_pubkey: vector, - genesis: bool, - ) acquires StakePool, ValidatorConfig { + genesis: bool + ) acquires StakePool, ValidatorConfig, ValidatorSet { check_stake_permission(operator); assert_reconfig_not_in_progress(); assert_stake_pool_exists(pool_address); let stake_pool = borrow_global_mut(pool_address); - assert!(signer::address_of(operator) == stake_pool.operator_address, error::unauthenticated(ENOT_OPERATOR)); + assert!( + signer::address_of(operator) == stake_pool.operator_address, + error::unauthenticated(ENOT_OPERATOR) + ); - assert!(exists(pool_address), error::not_found(EVALIDATOR_CONFIG)); + assert!( + exists(pool_address), + error::not_found(EVALIDATOR_CONFIG) + ); + // Verify the keys (and, for operator submissions, the appended BLS multisig PoP) and keep + // only the canonical key bytes (any appended PoP is stripped before storage/merge). + let new_consensus_pubkey = + validate_consensus_public_key(new_consensus_pubkey, genesis); + assert_consensus_pubkey_unique_in_next_validator_set( + pool_address, &new_consensus_pubkey + ); let validator_info = borrow_global_mut(pool_address); let old_consensus_pubkey = validator_info.consensus_pubkey; - // Checks the public key is valid to prevent rogue-key attacks. - if (!genesis) { - let validated_public_key = ed25519::new_validated_public_key_from_bytes(new_consensus_pubkey); - assert!(option::is_some(&validated_public_key), error::invalid_argument(EINVALID_PUBLIC_KEY)); - } else { - let validated_public_key = ed25519::new_validated_public_key_from_bytes(new_consensus_pubkey); - assert!(option::is_some(&validated_public_key), error::invalid_argument(EINVALID_PUBLIC_KEY)); - }; + + // Preserve the DKG-managed BLS threshold keys: an operator rotation must only change the + // static keys. We load the current on-chain keys and copy in only the operator-supplied + // static keys, leaving the threshold keys (written by `set_dkg_output_keys`) intact. + // + // The merge is skipped (and the incoming blob stored verbatim, preserving the original + // behavior) when there is nothing to preserve or the stored blob cannot be parsed: + // - before v2: the stored blob may be a legacy ed25519 key with no threshold keys; + // - genesis: no DKG threshold keys exist yet; + // - an empty stored key: a validator initialized via `initialize_stake_owner` sets its key + // for the first time here, so there is no prior `ValidatorPublicKeys` to merge into + // (parsing the empty blob would abort). + // Under v2 a non-empty stored blob is guaranteed to be a valid `ValidatorPublicKeys` (the + // feature is only enabled once all validators have migrated to the new format), and + // `validate_consensus_public_key` has already verified the incoming blob, so both + // deserializations are safe. + let new_consensus_pubkey = + if (!genesis + && std::features::supra_validator_identity_v2_enabled() + && !vector::is_empty(&old_consensus_pubkey)) { + let current_keys = + validator_public_keys::validator_public_keys_from_bytes( + old_consensus_pubkey + ); + let incoming_keys = + validator_public_keys::validator_public_keys_from_bytes( + new_consensus_pubkey + ); + validator_public_keys::replace_static_keys( + &mut current_keys, &incoming_keys + ); + validator_public_keys::public_key_to_bytes(current_keys) + } else { + new_consensus_pubkey + }; validator_info.consensus_pubkey = new_consensus_pubkey; if (std::features::module_event_migration_enabled()) { @@ -907,8 +1279,8 @@ module supra_framework::stake { RotateConsensusKey { pool_address, old_consensus_pubkey, - new_consensus_pubkey, - }, + new_consensus_pubkey + } ); } else { event::emit_event( @@ -916,9 +1288,102 @@ module supra_framework::stake { RotateConsensusKeyEvent { pool_address, old_consensus_pubkey, - new_consensus_pubkey, - }, + new_consensus_pubkey + } + ); + } + } + + /// Set DKG output keys for all provided threshold types. + /// Each DkgCommitteeOutput contains a threshold_type and corresponding keys for all validators. + public(friend) fun set_dkg_output_keys( + committee_outputs: vector + ) acquires ValidatorConfig, ValidatorPerformance, ValidatorSet, StakePool { + if (vector::is_empty(&committee_outputs)) { return }; + + let next_validator_infos = next_validator_consensus_infos(); + let num_validators = vector::length(&next_validator_infos); + + // Validate all committee outputs have correct number of keys + let num_outputs = vector::length(&committee_outputs); + let j = 0; + while (j < num_outputs) { + let output = vector::borrow(&committee_outputs, j); + assert!( + num_validators + == vector::length( + &dkg_committee::get_dkg_committee_output_keys(output) + ), + error::invalid_argument(EDKG_INVALID_PK_SHARES) ); + j = j + 1; + }; + + // Iterate over each validator + let i = 0; + while (i < num_validators) { + let val_info = vector::borrow(&next_validator_infos, i); + let addr = validator_consensus_info::get_addr(val_info); + let validator_config = borrow_global_mut(addr); + let old_consensus_pubkey = validator_config.consensus_pubkey; + + // Load current public keys + let pub_keys = + validator_public_keys::validator_public_keys_from_bytes( + old_consensus_pubkey + ); + + // Apply all threshold key updates for this validator + let k = 0; + while (k < num_outputs) { + let output = vector::borrow(&committee_outputs, k); + let output_keys = dkg_committee::get_dkg_committee_output_keys(output); + let key_bytes = vector::borrow(&output_keys, i); + + // Deserialize the key + let key_opt = aptos_std::bls12381::public_key_from_bytes(*key_bytes); + assert!( + option::is_some(&key_opt), + error::invalid_argument(EINVALID_PUBLIC_KEY) + ); + let new_key = option::extract(&mut key_opt); + + // Rotate the key based on threshold type + validator_public_keys::rotate_supra_bls_threshold_key_by_type( + &mut pub_keys, + dkg_committee::get_dkg_committee_output_threshold_type(output), + new_key + ); + k = k + 1; + }; + + // Serialize and save updated keys + let new_consensus_pubkey = + validator_public_keys::public_key_to_bytes(pub_keys); + validator_config.consensus_pubkey = new_consensus_pubkey; + + // Emit events + let stake_pool = borrow_global_mut(addr); + if (std::features::module_event_migration_enabled()) { + event::emit( + RotateConsensusKey { + pool_address: addr, + old_consensus_pubkey, + new_consensus_pubkey + } + ); + } else { + event::emit_event( + &mut stake_pool.rotate_consensus_key_events, + RotateConsensusKeyEvent { + pool_address: addr, + old_consensus_pubkey, + new_consensus_pubkey + } + ); + }; + + i = i + 1; }; } @@ -926,20 +1391,26 @@ module supra_framework::stake { /// does not verify proof of possession /// only for genesis public(friend) fun rotate_consensus_key_genesis( - operator: &signer, - pool_address: address, - new_consensus_pubkey: vector, - ) acquires StakePool, ValidatorConfig { - rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, true); + operator: &signer, pool_address: address, new_consensus_pubkey: vector + ) acquires StakePool, ValidatorConfig, ValidatorSet { + rotate_consensus_key_internal( + operator, + pool_address, + new_consensus_pubkey, + true + ); } /// Rotate the consensus key of the validator, it'll take effect in next epoch. public entry fun rotate_consensus_key( - operator: &signer, - pool_address: address, - new_consensus_pubkey: vector, - ) acquires StakePool, ValidatorConfig { - rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, false); + operator: &signer, pool_address: address, new_consensus_pubkey: vector + ) acquires StakePool, ValidatorConfig, ValidatorSet { + rotate_consensus_key_internal( + operator, + pool_address, + new_consensus_pubkey, + false + ); } /// Update the network and full node addresses of the validator. This only takes effect in the next epoch. @@ -947,14 +1418,23 @@ module supra_framework::stake { operator: &signer, pool_address: address, new_network_addresses: vector, - new_fullnode_addresses: vector, - ) acquires StakePool, ValidatorConfig { + new_fullnode_addresses: vector + ) acquires StakePool, ValidatorConfig, ValidatorSet { check_stake_permission(operator); assert_reconfig_not_in_progress(); assert_stake_pool_exists(pool_address); let stake_pool = borrow_global_mut(pool_address); - assert!(signer::address_of(operator) == stake_pool.operator_address, error::unauthenticated(ENOT_OPERATOR)); - assert!(exists(pool_address), error::not_found(EVALIDATOR_CONFIG)); + assert!( + signer::address_of(operator) == stake_pool.operator_address, + error::unauthenticated(ENOT_OPERATOR) + ); + assert!( + exists(pool_address), + error::not_found(EVALIDATOR_CONFIG) + ); + assert_network_addresses_unique_in_next_validator_set( + pool_address, &new_network_addresses + ); let validator_info = borrow_global_mut(pool_address); let old_network_addresses = validator_info.network_addresses; validator_info.network_addresses = new_network_addresses; @@ -968,8 +1448,8 @@ module supra_framework::stake { old_network_addresses, new_network_addresses, old_fullnode_addresses, - new_fullnode_addresses, - }, + new_fullnode_addresses + } ); } else { event::emit_event( @@ -979,8 +1459,8 @@ module supra_framework::stake { old_network_addresses, new_network_addresses, old_fullnode_addresses, - new_fullnode_addresses, - }, + new_fullnode_addresses + } ); }; } @@ -1003,8 +1483,13 @@ module supra_framework::stake { let stake_pool = borrow_global_mut(pool_address); let old_locked_until_secs = stake_pool.locked_until_secs; - let new_locked_until_secs = timestamp::now_seconds() + staking_config::get_recurring_lockup_duration(&config); - assert!(old_locked_until_secs < new_locked_until_secs, error::invalid_argument(EINVALID_LOCKUP)); + let new_locked_until_secs = + timestamp::now_seconds() + + staking_config::get_recurring_lockup_duration(&config); + assert!( + old_locked_until_secs < new_locked_until_secs, + error::invalid_argument(EINVALID_LOCKUP) + ); stake_pool.locked_until_secs = new_locked_until_secs; if (std::features::module_event_migration_enabled()) { @@ -1012,8 +1497,8 @@ module supra_framework::stake { IncreaseLockup { pool_address, old_locked_until_secs, - new_locked_until_secs, - }, + new_locked_until_secs + } ); } else { event::emit_event( @@ -1021,21 +1506,20 @@ module supra_framework::stake { IncreaseLockupEvent { pool_address, old_locked_until_secs, - new_locked_until_secs, - }, + new_locked_until_secs + } ); } } /// This can only called by the operator of the validator/staking pool. public entry fun join_validator_set( - operator: &signer, - pool_address: address + operator: &signer, pool_address: address ) acquires StakePool, ValidatorConfig, ValidatorSet { check_stake_permission(operator); assert!( staking_config::get_allow_validator_set_change(&staking_config::get()), - error::invalid_argument(ENO_POST_GENESIS_VALIDATOR_SET_CHANGE_ALLOWED), + error::invalid_argument(ENO_POST_GENESIS_VALIDATOR_SET_CHANGE_ALLOWED) ); join_validator_set_internal(operator, pool_address); @@ -1048,16 +1532,18 @@ module supra_framework::stake { /// /// This internal version can only be called by the Genesis module during Genesis. public(friend) fun join_validator_set_internal( - operator: &signer, - pool_address: address + operator: &signer, pool_address: address ) acquires StakePool, ValidatorConfig, ValidatorSet { assert_reconfig_not_in_progress(); assert_stake_pool_exists(pool_address); let stake_pool = borrow_global_mut(pool_address); - assert!(signer::address_of(operator) == stake_pool.operator_address, error::unauthenticated(ENOT_OPERATOR)); + assert!( + signer::address_of(operator) == stake_pool.operator_address, + error::unauthenticated(ENOT_OPERATOR) + ); assert!( get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE, - error::invalid_state(EALREADY_ACTIVE_VALIDATOR), + error::invalid_state(EALREADY_ACTIVE_VALIDATOR) ); let config = staking_config::get(); @@ -1071,7 +1557,10 @@ module supra_framework::stake { // Add validator to pending_active, to be activated in the next epoch. let validator_config = borrow_global(pool_address); - assert!(!vector::is_empty(&validator_config.consensus_pubkey), error::invalid_argument(EINVALID_PUBLIC_KEY)); + assert!( + !vector::is_empty(&validator_config.consensus_pubkey), + error::invalid_argument(EINVALID_PUBLIC_KEY) + ); // Validate the current validator set size has not exceeded the limit. let validator_set = borrow_global_mut(@supra_framework); @@ -1079,17 +1568,19 @@ module supra_framework::stake { &mut validator_set.pending_active, generate_validator_info(pool_address, stake_pool, *validator_config) ); - let validator_set_size = vector::length(&validator_set.active_validators) + vector::length( - &validator_set.pending_active + let validator_set_size = vector::length(&validator_set.active_validators) + + vector::length(&validator_set.pending_active); + assert!( + validator_set_size <= MAX_VALIDATOR_SET_SIZE, + error::invalid_argument(EVALIDATOR_SET_TOO_LARGE) ); - assert!(validator_set_size <= MAX_VALIDATOR_SET_SIZE, error::invalid_argument(EVALIDATOR_SET_TOO_LARGE)); if (std::features::module_event_migration_enabled()) { event::emit(JoinValidatorSet { pool_address }); } else { event::emit_event( &mut stake_pool.join_validator_set_events, - JoinValidatorSetEvent { pool_address }, + JoinValidatorSetEvent { pool_address } ); } } @@ -1108,9 +1599,7 @@ module supra_framework::stake { public fun unlock_with_cap(amount: u64, owner_cap: &OwnerCapability) acquires StakePool { assert_reconfig_not_in_progress(); // Short-circuit if amount to unlock is 0 so we don't emit events. - if (amount == 0) { - return - }; + if (amount == 0) { return }; // Unlocked coins are moved to pending_inactive. When the current lockup cycle expires, they will be moved into // inactive in the earliest possible epoch transition. @@ -1142,8 +1631,7 @@ module supra_framework::stake { /// Withdraw from `account`'s inactive stake. public entry fun withdraw( - owner: &signer, - withdraw_amount: u64 + owner: &signer, withdraw_amount: u64 ) acquires OwnerCapability, StakePool, ValidatorSet { check_stake_permission(owner); let owner_address = signer::address_of(owner); @@ -1155,8 +1643,7 @@ module supra_framework::stake { /// Withdraw from `pool_address`'s inactive stake with the corresponding `owner_cap`. public fun withdraw_with_cap( - owner_cap: &OwnerCapability, - withdraw_amount: u64 + owner_cap: &OwnerCapability, withdraw_amount: u64 ): Coin acquires StakePool, ValidatorSet { assert_reconfig_not_in_progress(); let pool_address = owner_cap.pool_address; @@ -1165,9 +1652,10 @@ module supra_framework::stake { // There's an edge case where a validator unlocks their stake and leaves the validator set before // the stake is fully unlocked (the current lockup cycle has not expired yet). // This can leave their stake stuck in pending_inactive even after the current lockup cycle expires. - if (get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE && - timestamp::now_seconds() >= stake_pool.locked_until_secs) { - let pending_inactive_stake = coin::extract_all(&mut stake_pool.pending_inactive); + if (get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE + && timestamp::now_seconds() >= stake_pool.locked_until_secs) { + let pending_inactive_stake = + coin::extract_all(&mut stake_pool.pending_inactive); coin::merge(&mut stake_pool.inactive, pending_inactive_stake); }; @@ -1202,28 +1690,33 @@ module supra_framework::stake { /// /// Can only be called by the operator of the validator/staking pool. public entry fun leave_validator_set( - operator: &signer, - pool_address: address + operator: &signer, pool_address: address ) acquires StakePool, ValidatorSet { check_stake_permission(operator); assert_reconfig_not_in_progress(); let config = staking_config::get(); assert!( staking_config::get_allow_validator_set_change(&config), - error::invalid_argument(ENO_POST_GENESIS_VALIDATOR_SET_CHANGE_ALLOWED), + error::invalid_argument(ENO_POST_GENESIS_VALIDATOR_SET_CHANGE_ALLOWED) ); assert_stake_pool_exists(pool_address); let stake_pool = borrow_global_mut(pool_address); // Account has to be the operator. - assert!(signer::address_of(operator) == stake_pool.operator_address, error::unauthenticated(ENOT_OPERATOR)); + assert!( + signer::address_of(operator) == stake_pool.operator_address, + error::unauthenticated(ENOT_OPERATOR) + ); let validator_set = borrow_global_mut(@supra_framework); // If the validator is still pending_active, directly kick the validator out. - let maybe_pending_active_index = find_validator(&validator_set.pending_active, pool_address); + let maybe_pending_active_index = + find_validator(&validator_set.pending_active, pool_address); if (option::is_some(&maybe_pending_active_index)) { vector::swap_remove( - &mut validator_set.pending_active, option::extract(&mut maybe_pending_active_index)); + &mut validator_set.pending_active, + option::extract(&mut maybe_pending_active_index) + ); // Decrease the voting power increase as the pending validator's voting power was added when they requested // to join. Now that they changed their mind, their voting power should not affect the joining limit of this @@ -1233,17 +1726,27 @@ module supra_framework::stake { // rounding error somewhere that can lead to an underflow, we still want to allow this transaction to // succeed. if (validator_set.total_joining_power > validator_stake) { - validator_set.total_joining_power = validator_set.total_joining_power - validator_stake; + validator_set.total_joining_power = + validator_set.total_joining_power - validator_stake; } else { validator_set.total_joining_power = 0; }; } else { // Validate that the validator is already part of the validator set. - let maybe_active_index = find_validator(&validator_set.active_validators, pool_address); - assert!(option::is_some(&maybe_active_index), error::invalid_state(ENOT_VALIDATOR)); + let maybe_active_index = + find_validator(&validator_set.active_validators, pool_address); + assert!( + option::is_some(&maybe_active_index), + error::invalid_state(ENOT_VALIDATOR) + ); let validator_info = vector::swap_remove( - &mut validator_set.active_validators, option::extract(&mut maybe_active_index)); - assert!(vector::length(&validator_set.active_validators) != 0, error::invalid_state(ELAST_VALIDATOR)); + &mut validator_set.active_validators, + option::extract(&mut maybe_active_index) + ); + assert!( + vector::length(&validator_set.active_validators) != 0, + error::invalid_state(ELAST_VALIDATOR) + ); vector::push_back(&mut validator_set.pending_inactive, validator_info); if (std::features::module_event_migration_enabled()) { @@ -1265,14 +1768,14 @@ module supra_framework::stake { public fun is_current_epoch_validator(pool_address: address): bool acquires ValidatorSet { assert_stake_pool_exists(pool_address); let validator_state = get_validator_state(pool_address); - validator_state == VALIDATOR_STATUS_ACTIVE || validator_state == VALIDATOR_STATUS_PENDING_INACTIVE + validator_state == VALIDATOR_STATUS_ACTIVE + || validator_state == VALIDATOR_STATUS_PENDING_INACTIVE } /// Update the validator performance (proposal statistics). This is only called by block::prologue(). /// This function cannot abort. public(friend) fun update_performance_statistics( - proposer_index: Option, - failed_proposer_indices: vector + proposer_index: Option, failed_proposer_indices: vector ) acquires ValidatorPerformance { // Validator set cannot change until the end of the epoch, so the validator index in arguments should // match with those of the validators in ValidatorPerformance resource. @@ -1289,7 +1792,9 @@ module supra_framework::stake { // Here, and in all other vector::borrow, skip any validator indices that are out of bounds, // this ensures that this function doesn't abort if there are out of bounds errors. if (cur_proposer_index < validator_len) { - let validator = vector::borrow_mut(&mut validator_perf.validators, cur_proposer_index); + let validator = vector::borrow_mut( + &mut validator_perf.validators, cur_proposer_index + ); spec { assume validator.successful_proposals + 1 <= MAX_U64; }; @@ -1302,17 +1807,25 @@ module supra_framework::stake { while ({ spec { invariant len(validator_perf.validators) == validator_len; - invariant (option::spec_is_some(ghost_proposer_idx) && option::spec_borrow( - ghost_proposer_idx - ) < validator_len) ==> - (validator_perf.validators[option::spec_borrow(ghost_proposer_idx)].successful_proposals == - ghost_valid_perf.validators[option::spec_borrow(ghost_proposer_idx)].successful_proposals + 1); + invariant ( + option::spec_is_some(ghost_proposer_idx) + && option::spec_borrow(ghost_proposer_idx) < validator_len + ) ==> + ( + validator_perf.validators[option::spec_borrow(ghost_proposer_idx)] + .successful_proposals + == ghost_valid_perf.validators[option::spec_borrow( + ghost_proposer_idx + )].successful_proposals + 1 + ); }; f < f_len }) { let validator_index = *vector::borrow(&failed_proposer_indices, f); if (validator_index < validator_len) { - let validator = vector::borrow_mut(&mut validator_perf.validators, validator_index); + let validator = vector::borrow_mut( + &mut validator_perf.validators, validator_index + ); spec { assume validator.failed_proposals + 1 <= MAX_U64; }; @@ -1332,24 +1845,29 @@ module supra_framework::stake { /// pending inactive validators so they no longer can vote. /// 4. The validator's voting power in the validator set is updated to be the corresponding staking pool's voting /// power. - public(friend) fun on_new_epoch( - ) acquires SupraCoinCapabilities, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { + public(friend) fun on_new_epoch() acquires SupraCoinCapabilities, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { let validator_set = borrow_global_mut(@supra_framework); let config = staking_config::get(); let validator_perf = borrow_global_mut(@supra_framework); // Process pending stake and distribute transaction fees and rewards for each currently active validator. - vector::for_each_ref(&validator_set.active_validators, |validator| { - let validator: &ValidatorInfo = validator; - update_stake_pool(validator_perf, validator.addr, &config); - }); + vector::for_each_ref( + &validator_set.active_validators, + |validator| { + let validator: &ValidatorInfo = validator; + update_stake_pool(validator_perf, validator.addr, &config); + } + ); // Process pending stake and distribute transaction fees and rewards for each currently pending_inactive validator // (requested to leave but not removed yet). - vector::for_each_ref(&validator_set.pending_inactive, |validator| { - let validator: &ValidatorInfo = validator; - update_stake_pool(validator_perf, validator.addr, &config); - }); + vector::for_each_ref( + &validator_set.pending_inactive, + |validator| { + let validator: &ValidatorInfo = validator; + update_stake_pool(validator_perf, validator.addr, &config); + } + ); // Activate currently pending_active validators. append(&mut validator_set.active_validators, &mut validator_set.pending_active); @@ -1372,18 +1890,23 @@ module supra_framework::stake { }; i < vlen }) { - let old_validator_info = vector::borrow_mut(&mut validator_set.active_validators, i); + let old_validator_info = vector::borrow_mut( + &mut validator_set.active_validators, i + ); let pool_address = old_validator_info.addr; let validator_config = borrow_global(pool_address); let stake_pool = borrow_global(pool_address); - let new_validator_info = generate_validator_info(pool_address, stake_pool, *validator_config); + let new_validator_info = + generate_validator_info(pool_address, stake_pool, *validator_config); // A validator needs at least the min stake required to join the validator set. if (new_validator_info.voting_power >= minimum_stake) { spec { - assume total_voting_power + new_validator_info.voting_power <= MAX_U128; + assume total_voting_power + new_validator_info.voting_power + <= MAX_U128; }; - total_voting_power = total_voting_power + (new_validator_info.voting_power as u128); + total_voting_power = + total_voting_power + (new_validator_info.voting_power as u128); vector::push_back(&mut next_epoch_validators, new_validator_info); }; i = i + 1; @@ -1395,7 +1918,8 @@ module supra_framework::stake { // Update validator indices, reset performance scores, and renew lockups. validator_perf.validators = vector::empty(); - let recurring_lockup_duration_secs = staking_config::get_recurring_lockup_duration(&config); + let recurring_lockup_duration_secs = + staking_config::get_recurring_lockup_duration(&config); let vlen = vector::length(&validator_set.active_validators); let validator_index = 0; while ({ @@ -1406,37 +1930,47 @@ module supra_framework::stake { invariant 0 <= validator_index && validator_index <= vlen; invariant vlen == len(validator_set.active_validators); invariant forall i in 0..validator_index: - global(validator_set.active_validators[i].addr).validator_index < validator_index; + global(validator_set.active_validators[i].addr).validator_index + < validator_index; invariant forall i in 0..validator_index: - validator_set.active_validators[i].config.validator_index < validator_index; + validator_set.active_validators[i].config.validator_index + < validator_index; invariant len(validator_perf.validators) == validator_index; }; validator_index < vlen }) { - let validator_info = vector::borrow_mut(&mut validator_set.active_validators, validator_index); + let validator_info = vector::borrow_mut( + &mut validator_set.active_validators, validator_index + ); validator_info.config.validator_index = validator_index; - let validator_config = borrow_global_mut(validator_info.addr); + let validator_config = + borrow_global_mut(validator_info.addr); validator_config.validator_index = validator_index; - vector::push_back(&mut validator_perf.validators, IndividualValidatorPerformance { - successful_proposals: 0, - failed_proposals: 0, - }); + vector::push_back( + &mut validator_perf.validators, + IndividualValidatorPerformance { + successful_proposals: 0, + failed_proposals: 0 + } + ); // Automatically renew a validator's lockup for validators that will still be in the validator set in the // next epoch. let stake_pool = borrow_global_mut(validator_info.addr); let now_secs = timestamp::now_seconds(); - let reconfig_start_secs = if (chain_status::is_operating()) { - get_reconfig_start_time_secs() - } else { - now_secs - }; + let reconfig_start_secs = + if (chain_status::is_operating()) { + get_reconfig_start_time_secs() + } else { + now_secs + }; if (stake_pool.locked_until_secs <= reconfig_start_secs) { spec { assume now_secs + recurring_lockup_duration_secs <= MAX_U64; }; - stake_pool.locked_until_secs = now_secs + recurring_lockup_duration_secs; + stake_pool.locked_until_secs = now_secs + + recurring_lockup_duration_secs; }; validator_index = validator_index + 1; @@ -1460,15 +1994,42 @@ module supra_framework::stake { validator_consensus_infos_from_validator_set(validator_set) } - public fun next_validator_consensus_infos(): vector acquires ValidatorSet, ValidatorPerformance, StakePool, ValidatorConfig { - // Init. - let cur_validator_set = borrow_global(@supra_framework); - let staking_config = staking_config::get(); - let validator_perf = borrow_global(@supra_framework); - let (minimum_stake, _) = staking_config::get_required_stake(&staking_config); - let (rewards_rate, rewards_rate_denominator) = staking_config::get_reward_rate(&staking_config); - + let new_validator_set = compute_next_validator_set_internal(false); + validator_consensus_infos_from_validator_set(&new_validator_set) + } + + /// Same as `next_validator_consensus_infos` but uses the current-epoch config data for + /// validators that are already active. This is used when starting DKG: the committee + /// membership (active + pending_active) must reflect the next epoch, but node config + /// should reflect current-epoch for the active validators to ensure that validators that update + /// their configuration do not need to run two copies of themselves to participate in DKG. + public fun next_epoch_validator_consensus_infos_for_dkg(): vector acquires ValidatorSet, ValidatorPerformance, StakePool, ValidatorConfig { + // Use the current-epoch config snapshot for active validators so mid-epoch config changes + // do not take effect during DKG (use_current_config_for_actives=true). + let new_validator_set = compute_next_validator_set_internal(true); + validator_consensus_infos_from_validator_set(&new_validator_set) + } + + /// Computes the validator set for the next epoch. + /// + /// `use_current_config_for_actives`: when `true`, currently-active validators retain their + /// current-epoch `ValidatorConfig` snapshot instead of reading the latest on-chain value. + /// New joiners (`pending_active`) always read from `ValidatorConfig` regardless of this flag. + /// + /// `pending_active` is iterated in reverse to match the order produced by `on_new_epoch` + /// (which appends via `pop_back`). + fun compute_next_validator_set_internal( + use_current_config_for_actives: bool + ): ValidatorSet acquires ValidatorSet, ValidatorPerformance, StakePool, ValidatorConfig { + // Init. + let cur_validator_set = borrow_global(@supra_framework); + let staking_config = staking_config::get(); + let validator_perf = borrow_global(@supra_framework); + let (minimum_stake, _) = staking_config::get_required_stake(&staking_config); + let (rewards_rate, rewards_rate_denominator) = + staking_config::get_reward_rate(&staking_config); + // Compute new validator set. let new_active_validators = vector[]; let num_new_actives = 0; @@ -1493,11 +2054,14 @@ module supra_framework::stake { candidate_idx < num_candidates }) { let candidate_in_current_validator_set = candidate_idx < num_cur_actives; - let candidate = if (candidate_idx < num_cur_actives) { - vector::borrow(&cur_validator_set.active_validators, candidate_idx) - } else { - vector::borrow(&cur_validator_set.pending_active, candidate_idx - num_cur_actives) - }; + let candidate = + if (candidate_idx < num_cur_actives) { + vector::borrow(&cur_validator_set.active_validators, candidate_idx) + } else { + let pending_idx = + num_cur_pending_actives - 1 - (candidate_idx - num_cur_actives); + vector::borrow(&cur_validator_set.pending_active, pending_idx) + }; let stake_pool = borrow_global(candidate.addr); let cur_active = coin::value(&stake_pool.active); let cur_pending_active = coin::value(&stake_pool.pending_active); @@ -1528,12 +2092,21 @@ module supra_framework::stake { + cur_reward; if (new_voting_power >= minimum_stake) { - let config = *borrow_global(candidate.addr); + let config = + if (use_current_config_for_actives + && candidate_in_current_validator_set) { + // Use the current-epoch config snapshot so that any mid-epoch changes + // (consensus key, network addresses, etc.) only take effect after the + // epoch transition, not during DKG. + candidate.config + } else { + *borrow_global(candidate.addr) + }; config.validator_index = num_new_actives; let new_validator_info = ValidatorInfo { addr: candidate.addr, voting_power: new_voting_power, - config, + config }; // Update ValidatorSet. @@ -1543,24 +2116,56 @@ module supra_framework::stake { new_total_power = new_total_power + (new_voting_power as u128); vector::push_back(&mut new_active_validators, new_validator_info); num_new_actives = num_new_actives + 1; - }; candidate_idx = candidate_idx + 1; }; - let new_validator_set = ValidatorSet { + ValidatorSet { consensus_scheme: cur_validator_set.consensus_scheme, active_validators: new_active_validators, pending_inactive: vector[], pending_active: vector[], total_voting_power: new_total_power, - total_joining_power: 0, - }; + total_joining_power: 0 + } + } - validator_consensus_infos_from_validator_set(&new_validator_set) + /// Computes the reward earned by a candidate validator for the current epoch. + /// Returns 0 for pending-active validators (not yet in the active set) or validators + /// with no active stake. + fun calculate_candidate_reward( + candidate: &ValidatorInfo, + candidate_in_current_validator_set: bool, + cur_active: u64, + validator_perf: &ValidatorPerformance, + rewards_rate: u64, + rewards_rate_denominator: u64 + ): u64 { + if (candidate_in_current_validator_set && cur_active != 0) { + spec { + assert candidate.config.validator_index + < len(validator_perf.validators); + }; + let cur_perf = vector::borrow( + &validator_perf.validators, candidate.config.validator_index + ); + spec { + assume cur_perf.successful_proposals + cur_perf.failed_proposals + <= MAX_U64; + }; + calculate_rewards_amount( + cur_active, + cur_perf.successful_proposals, + cur_perf.successful_proposals + cur_perf.failed_proposals, + rewards_rate, + rewards_rate_denominator + ) + } else { 0 } } - fun validator_consensus_infos_from_validator_set(validator_set: &ValidatorSet): vector { + fun validator_consensus_infos_from_validator_set( + validator_set: &ValidatorSet + ): vector { let validator_consensus_infos = vector[]; let num_active = vector::length(&validator_set.active_validators); @@ -1574,63 +2179,95 @@ module supra_framework::stake { let idx = 0; while ({ spec { - invariant idx <= len(validator_set.active_validators) + len(validator_set.pending_inactive); + invariant idx + <= len(validator_set.active_validators) + + len(validator_set.pending_inactive); invariant len(validator_consensus_infos) == idx; - invariant len(validator_consensus_infos) <= len(validator_set.active_validators) + len(validator_set.pending_inactive); + invariant len(validator_consensus_infos) + <= len(validator_set.active_validators) + + len(validator_set.pending_inactive); }; idx < total }) { - vector::push_back(&mut validator_consensus_infos, validator_consensus_info::default()); + vector::push_back( + &mut validator_consensus_infos, validator_consensus_info::default() + ); idx = idx + 1; }; spec { - assert len(validator_consensus_infos) == len(validator_set.active_validators) + len(validator_set.pending_inactive); - assert spec_validator_indices_are_valid_config(validator_set.active_validators, - len(validator_set.active_validators) + len(validator_set.pending_inactive)); + assert len(validator_consensus_infos) + == len(validator_set.active_validators) + + len(validator_set.pending_inactive); + assert spec_validator_indices_are_valid_config( + validator_set.active_validators, + len(validator_set.active_validators) + + len(validator_set.pending_inactive) + ); }; - vector::for_each_ref(&validator_set.active_validators, |obj| { - let vi: &ValidatorInfo = obj; - spec { - assume len(validator_consensus_infos) == len(validator_set.active_validators) + len(validator_set.pending_inactive); - assert vi.config.validator_index < len(validator_consensus_infos); - }; - let vci = vector::borrow_mut(&mut validator_consensus_infos, vi.config.validator_index); - *vci = validator_consensus_info::new( - vi.addr, - vi.config.consensus_pubkey, - vi.voting_power - ); - spec { - assert len(validator_consensus_infos) == len(validator_set.active_validators) + len(validator_set.pending_inactive); - }; - }); + vector::for_each_ref( + &validator_set.active_validators, + |obj| { + let vi: &ValidatorInfo = obj; + spec { + assume len(validator_consensus_infos) + == len(validator_set.active_validators) + + len(validator_set.pending_inactive); + assert vi.config.validator_index < len(validator_consensus_infos); + }; + let vci = vector::borrow_mut( + &mut validator_consensus_infos, vi.config.validator_index + ); + *vci = validator_consensus_info::new( + vi.addr, + vi.config.consensus_pubkey, + vi.voting_power + ); + spec { + assert len(validator_consensus_infos) + == len(validator_set.active_validators) + + len(validator_set.pending_inactive); + }; + } + ); - vector::for_each_ref(&validator_set.pending_inactive, |obj| { - let vi: &ValidatorInfo = obj; - spec { - assume len(validator_consensus_infos) == len(validator_set.active_validators) + len(validator_set.pending_inactive); - assert vi.config.validator_index < len(validator_consensus_infos); - }; - let vci = vector::borrow_mut(&mut validator_consensus_infos, vi.config.validator_index); - *vci = validator_consensus_info::new( - vi.addr, - vi.config.consensus_pubkey, - vi.voting_power - ); - spec { - assert len(validator_consensus_infos) == len(validator_set.active_validators) + len(validator_set.pending_inactive); - }; - }); + vector::for_each_ref( + &validator_set.pending_inactive, + |obj| { + let vi: &ValidatorInfo = obj; + spec { + assume len(validator_consensus_infos) + == len(validator_set.active_validators) + + len(validator_set.pending_inactive); + assert vi.config.validator_index < len(validator_consensus_infos); + }; + let vci = vector::borrow_mut( + &mut validator_consensus_infos, vi.config.validator_index + ); + *vci = validator_consensus_info::new( + vi.addr, + vi.config.consensus_pubkey, + vi.voting_power + ); + spec { + assert len(validator_consensus_infos) + == len(validator_set.active_validators) + + len(validator_set.pending_inactive); + }; + } + ); validator_consensus_infos } fun addresses_from_validator_infos(infos: &vector): vector
{ - vector::map_ref(infos, |obj| { - let info: &ValidatorInfo = obj; - info.addr - }) + vector::map_ref( + infos, + |obj| { + let info: &ValidatorInfo = obj; + info.addr + } + ) } /// Calculate the stake amount of a stake pool for the next epoch. @@ -1643,12 +2280,14 @@ module supra_framework::stake { fun update_stake_pool( validator_perf: &ValidatorPerformance, pool_address: address, - staking_config: &StakingConfig, + staking_config: &StakingConfig ) acquires SupraCoinCapabilities, PendingTransactionFee, StakePool, ValidatorConfig { let stake_pool = borrow_global_mut(pool_address); let validator_config = borrow_global(pool_address); let validator_index = validator_config.validator_index; - let cur_validator_perf = vector::borrow(&validator_perf.validators, validator_index); + let cur_validator_perf = vector::borrow( + &validator_perf.validators, validator_index + ); let num_successful_proposals = cur_validator_perf.successful_proposals; let fee_pending_inactive = 0; @@ -1672,24 +2311,30 @@ module supra_framework::stake { spec { // The following addition should not overflow because `num_total_proposals` cannot be larger than 86400, // the maximum number of proposals in a day (1 proposal per second). - assume cur_validator_perf.successful_proposals + cur_validator_perf.failed_proposals <= MAX_U64; + assume cur_validator_perf.successful_proposals + + cur_validator_perf.failed_proposals <= MAX_U64; }; - let num_total_proposals = cur_validator_perf.successful_proposals + cur_validator_perf.failed_proposals; - let (rewards_rate, rewards_rate_denominator) = staking_config::get_reward_rate(staking_config); - let rewards_active = distribute_rewards( - &mut stake_pool.active, - num_successful_proposals, - num_total_proposals, - rewards_rate, - rewards_rate_denominator - ); - let rewards_pending_inactive = distribute_rewards( - &mut stake_pool.pending_inactive, - num_successful_proposals, - num_total_proposals, - rewards_rate, - rewards_rate_denominator - ); + let num_total_proposals = + cur_validator_perf.successful_proposals + + cur_validator_perf.failed_proposals; + let (rewards_rate, rewards_rate_denominator) = + staking_config::get_reward_rate(staking_config); + let rewards_active = + distribute_rewards( + &mut stake_pool.active, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ); + let rewards_pending_inactive = + distribute_rewards( + &mut stake_pool.pending_inactive, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ); spec { assume rewards_active + rewards_pending_inactive <= MAX_U64; }; @@ -1717,7 +2362,7 @@ module supra_framework::stake { if (get_reconfig_start_time_secs() >= current_lockup_expiration) { coin::merge( &mut stake_pool.inactive, - coin::extract_all(&mut stake_pool.pending_inactive), + coin::extract_all(&mut stake_pool.pending_inactive) ); }; @@ -1749,7 +2394,7 @@ module supra_framework::stake { num_successful_proposals: u64, num_total_proposals: u64, rewards_rate: u64, - rewards_rate_denominator: u64, + rewards_rate_denominator: u64 ): u64 { spec { // The following condition must hold because @@ -1760,13 +2405,14 @@ module supra_framework::stake { }; // The rewards amount is equal to (stake amount * rewards rate * performance multiplier). // We do multiplication in u128 before division to avoid the overflow and minimize the rounding error. - let rewards_numerator = (stake_amount as u128) * (rewards_rate as u128) * (num_successful_proposals as u128); - let rewards_denominator = (rewards_rate_denominator as u128) * (num_total_proposals as u128); + let rewards_numerator = + (stake_amount as u128) * (rewards_rate as u128) + * (num_successful_proposals as u128); + let rewards_denominator = + (rewards_rate_denominator as u128) * (num_total_proposals as u128); if (rewards_denominator != 0) { ((rewards_numerator / rewards_denominator) as u64) - } else { - 0 - } + } else { 0 } } /// Mint rewards corresponding to current epoch's `stake` and `num_successful_votes`. @@ -1775,22 +2421,22 @@ module supra_framework::stake { num_successful_proposals: u64, num_total_proposals: u64, rewards_rate: u64, - rewards_rate_denominator: u64, + rewards_rate_denominator: u64 ): u64 acquires SupraCoinCapabilities { let stake_amount = coin::value(stake); - let rewards_amount = if (stake_amount != 0) { - calculate_rewards_amount( - stake_amount, - num_successful_proposals, - num_total_proposals, - rewards_rate, - rewards_rate_denominator - ) - } else { - 0 - }; + let rewards_amount = + if (stake_amount != 0) { + calculate_rewards_amount( + stake_amount, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ) + } else { 0 }; if (rewards_amount != 0) { - let mint_cap = &borrow_global(@supra_framework).mint_cap; + let mint_cap = + &borrow_global(@supra_framework).mint_cap; let rewards = coin::mint(rewards_amount, mint_cap); coin::merge(stake, rewards); }; @@ -1820,13 +2466,11 @@ module supra_framework::stake { option::none() } - fun generate_validator_info(addr: address, stake_pool: &StakePool, config: ValidatorConfig): ValidatorInfo { + fun generate_validator_info( + addr: address, stake_pool: &StakePool, config: ValidatorConfig + ): ValidatorInfo { let voting_power = get_next_epoch_voting_power(stake_pool); - ValidatorInfo { - addr, - voting_power, - config, - } + ValidatorInfo { addr, voting_power, config } } /// Returns validator's next epoch voting power, including pending_active, active, and pending_inactive stake. @@ -1835,7 +2479,8 @@ module supra_framework::stake { let value_active = coin::value(&stake_pool.active); let value_pending_inactive = coin::value(&stake_pool.pending_inactive); spec { - assume value_pending_active + value_active + value_pending_inactive <= MAX_U64; + assume value_pending_active + value_active + value_pending_inactive + <= MAX_U64; }; value_pending_active + value_active + value_pending_inactive } @@ -1843,32 +2488,39 @@ module supra_framework::stake { fun update_voting_power_increase(increase_amount: u64) acquires ValidatorSet { let validator_set = borrow_global_mut(@supra_framework); let voting_power_increase_limit = - (staking_config::get_voting_power_increase_limit(&staking_config::get()) as u128); - validator_set.total_joining_power = validator_set.total_joining_power + (increase_amount as u128); + ( + staking_config::get_voting_power_increase_limit(&staking_config::get()) as u128 + ); + validator_set.total_joining_power = + validator_set.total_joining_power + (increase_amount as u128); // Only validator voting power increase if the current validator set's voting power > 0. if (validator_set.total_voting_power != 0) { assert!( - validator_set.total_joining_power <= validator_set.total_voting_power * voting_power_increase_limit / 100, - error::invalid_argument(EVOTING_POWER_INCREASE_EXCEEDS_LIMIT), + validator_set.total_joining_power + <= validator_set.total_voting_power * voting_power_increase_limit + / 100, + error::invalid_argument(EVOTING_POWER_INCREASE_EXCEEDS_LIMIT) ); } } fun assert_stake_pool_exists(pool_address: address) { - assert!(stake_pool_exists(pool_address), error::invalid_argument(ESTAKE_POOL_DOES_NOT_EXIST)); + assert!( + stake_pool_exists(pool_address), + error::invalid_argument(ESTAKE_POOL_DOES_NOT_EXIST) + ); } /// This provides an ACL for Testnet purposes. In testnet, everyone is a whale, a whale can be a validator. /// This allows a testnet to bring additional entities into the validator set without compromising the /// security of the testnet. This will NOT be enabled in Mainnet. struct AllowedValidators has key { - accounts: vector
, + accounts: vector
} public fun configure_allowed_validators( - supra_framework: &signer, - accounts: vector
+ supra_framework: &signer, accounts: vector
) acquires AllowedValidators { let supra_framework_address = signer::address_of(supra_framework); system_addresses::assert_supra_framework(supra_framework); @@ -1881,20 +2533,25 @@ module supra_framework::stake { } fun is_allowed(account: address): bool acquires AllowedValidators { - if (!exists(@supra_framework)) { - true - } else { + if (!exists(@supra_framework)) { true } + else { let allowed = borrow_global(@supra_framework); vector::contains(&allowed.accounts, &account) } } fun assert_owner_cap_exists(owner: address) { - assert!(exists(owner), error::not_found(EOWNER_CAP_NOT_FOUND)); + assert!( + exists(owner), + error::not_found(EOWNER_CAP_NOT_FOUND) + ); } fun assert_reconfig_not_in_progress() { - assert!(!reconfiguration_state::is_in_progress(), error::invalid_state(ERECONFIGURATION_IN_PROGRESS)); + assert!( + !reconfiguration_state::is_in_progress(), + error::invalid_state(ERECONFIGURATION_IN_PROGRESS) + ); } #[test_only] @@ -1914,20 +2571,30 @@ module supra_framework::stake { #[test_only] public fun initialize_for_test(supra_framework: &signer) { reconfiguration_state::initialize(supra_framework); - initialize_for_test_custom(supra_framework, 100, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 100, 1000000); + initialize_for_test_custom( + supra_framework, + 100, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 100, + 1000000 + ); // In the test environment, the periodical_reward_rate_decrease feature is initially turned off. features::change_feature_flags_for_testing(supra_framework, vector[], vector[features::get_periodical_reward_rate_decrease_feature()]); } #[test_only] public fun join_validator_set_for_test( - pk: &ed25519::UnvalidatedPublicKey, + pk: &validator_public_keys::ValidatorPublicKeys, operator: &signer, pool_address: address, - should_end_epoch: bool, + should_end_epoch: bool ) acquires SupraCoinCapabilities, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { - let pk_bytes = ed25519::unvalidated_public_key_to_bytes(pk); - rotate_consensus_key(operator, pool_address, pk_bytes); + let pk_bytes = validator_public_keys::public_key_to_bytes(*pk); + // Test fixture: rotate through the genesis (PoP-exempt) path. + rotate_consensus_key_genesis(operator, pool_address, pk_bytes); join_validator_set(operator, pool_address); if (should_end_epoch) { end_epoch(); @@ -1935,8 +2602,9 @@ module supra_framework::stake { } #[test_only] - public fun fast_forward_to_unlock(pool_address: address) - acquires SupraCoinCapabilities, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { + public fun fast_forward_to_unlock( + pool_address: address + ) acquires SupraCoinCapabilities, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { let expiration_time = get_lockup_secs(pool_address); timestamp::update_global_time_for_test_secs(expiration_time); end_epoch(); @@ -1952,7 +2620,7 @@ module supra_framework::stake { allow_validator_set_change: bool, rewards_rate_numerator: u64, rewards_rate_denominator: u64, - voting_power_increase_limit: u64, + voting_power_increase_limit: u64 ) { timestamp::set_time_has_started_for_testing(supra_framework); reconfiguration_state::initialize(supra_framework); @@ -1967,7 +2635,7 @@ module supra_framework::stake { allow_validator_set_change, rewards_rate_numerator, rewards_rate_denominator, - voting_power_increase_limit, + voting_power_increase_limit ); if (!exists(@supra_framework)) { @@ -1995,24 +2663,32 @@ module supra_framework::stake { #[test_only] public fun mint_and_add_stake( - account: &signer, amount: u64) acquires SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorSet { + account: &signer, amount: u64 + ) acquires SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorSet { mint(account, amount); add_stake(account, amount); } #[test_only] public fun initialize_test_validator( - public_key: &ed25519::UnvalidatedPublicKey, + public_key: &validator_public_keys::ValidatorPublicKeys, validator: &signer, amount: u64, should_join_validator_set: bool, - should_end_epoch: bool, + should_end_epoch: bool ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { let validator_address = signer::address_of(validator); account::create_account_for_test(validator_address); - let pk_bytes = ed25519::unvalidated_public_key_to_bytes(public_key); - initialize_validator(validator, pk_bytes, vector::empty(), vector::empty()); + let pk_bytes = validator_public_keys::public_key_to_bytes(*public_key); + // Test fixtures register through the genesis (PoP-exempt) path; see + // `register_test_validator_with_addresses`. + initialize_validator_genesis( + validator, + pk_bytes, + vector::empty(), + vector::empty() + ); if (amount > 0) { mint_and_add_stake(validator, amount); @@ -2030,37 +2706,43 @@ module supra_framework::stake { public fun create_validator_set( supra_framework: &signer, active_validator_addresses: vector
, - public_keys: vector, + public_keys: vector ) { let active_validators = vector::empty(); let i = 0; while (i < vector::length(&active_validator_addresses)) { let validator_address = vector::borrow(&active_validator_addresses, i); let pk = vector::borrow(&public_keys, i); - vector::push_back(&mut active_validators, ValidatorInfo { - addr: *validator_address, - voting_power: 0, - config: ValidatorConfig { - consensus_pubkey: ed25519::unvalidated_public_key_to_bytes(pk), - network_addresses: b"", - fullnode_addresses: b"", - validator_index: 0, + vector::push_back( + &mut active_validators, + ValidatorInfo { + addr: *validator_address, + voting_power: 0, + config: ValidatorConfig { + consensus_pubkey: validator_public_keys::public_key_to_bytes(*pk), + network_addresses: b"", + fullnode_addresses: b"", + validator_index: 0 + } } - }); + ); i = i + 1; }; - move_to(supra_framework, ValidatorSet { - consensus_scheme: 0, - // active validators for the current epoch - active_validators, - // pending validators to leave in next epoch (still active) - pending_inactive: vector::empty(), - // pending validators to join in next epoch - pending_active: vector::empty(), - total_voting_power: 0, - total_joining_power: 0, - }); + move_to( + supra_framework, + ValidatorSet { + consensus_scheme: 0, + // active validators for the current epoch + active_validators, + // pending validators to leave in next epoch (still active) + pending_inactive: vector::empty(), + // pending validators to join in next epoch + pending_active: vector::empty(), + total_voting_power: 0, + total_joining_power: 0 + } + ); } #[test_only] @@ -2068,7 +2750,7 @@ module supra_framework::stake { account: &signer, active: Coin, pending_inactive: Coin, - locked_until_secs: u64, + locked_until_secs: u64 ) acquires AllowedValidators, OwnerCapability, StakePool, ValidatorSet { let account_address = signer::address_of(account); initialize_stake_owner(account, 0, account_address, account_address); @@ -2081,24 +2763,463 @@ module supra_framework::stake { // Allows unit tests to set custom validator performances. #[test_only] public fun update_validator_performances_for_test( - proposer_index: Option, - failed_proposer_indices: vector, + proposer_index: Option, failed_proposer_indices: vector ) acquires ValidatorPerformance { update_performance_statistics(proposer_index, failed_proposer_indices); } #[test_only] - public fun generate_identity(): (ed25519::SecretKey, ed25519::UnvalidatedPublicKey) { - let (sk, validated_pub_key) = ed25519::generate_keys(); - let unvalidated_pk = ed25519::public_key_to_unvalidated(&validated_pub_key); - (sk, unvalidated_pk) + public fun generate_identity(): ( + validator_public_keys::ValidatorSecretKeys, + validator_public_keys::ValidatorPublicKeys + ) { + validator_public_keys::generate_keys() + } + + /// Returns the serialized bytes of a freshly generated, unique consensus public key with a + /// valid BLS multisig proof-of-possession appended, i.e. exactly what an operator submits to + /// `rotate_consensus_key` under the v2 identity format (which is enabled in the test VM). + #[test_only] + public fun generate_unique_consensus_pubkey_bytes(): vector { + let (sk, pk) = generate_identity(); + validator_public_keys::serialized_keys_with_pop_for_test(&sk, &pk) + } + + #[test_only] + fun register_test_validator_with_addresses( + public_key: &validator_public_keys::ValidatorPublicKeys, + validator: &signer, + network_addresses: vector, + fullnode_addresses: vector + ) acquires AllowedValidators, ValidatorConfig, ValidatorSet { + let validator_address = signer::address_of(validator); + if (!account::exists_at(validator_address)) { + account::create_account_for_test(validator_address); + }; + let pk_bytes = validator_public_keys::public_key_to_bytes(*public_key); + // Test fixtures register through the genesis (PoP-exempt) path: they are trusted setup and + // do not carry an operator proof-of-possession. PoP enforcement is covered by the dedicated + // `initialize_validator` / `rotate_consensus_key` tests. + initialize_validator_genesis( + validator, + pk_bytes, + network_addresses, + fullnode_addresses + ); + } + + #[test(supra_framework = @supra_framework, validator_1 = @0x123, validator_2 = @0x234)] + #[expected_failure(abort_code = 0x10016, location = Self)] + public entry fun test_initialize_validator_rejects_duplicate_consensus_pubkey_active( + supra_framework: &signer, validator_1: &signer, validator_2: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, PendingTransactionFee { + initialize_for_test(supra_framework); + let (_sk, pk) = generate_identity(); + // validator_1 joins and becomes active in the next epoch. + initialize_test_validator(&pk, validator_1, 100, true, true); + // validator_2 tries to register with the same consensus key - should abort. + initialize_test_validator(&pk, validator_2, 100, false, false); + } + + #[test(supra_framework = @supra_framework, validator_1 = @0x123, validator_2 = @0x234)] + #[expected_failure(abort_code = 0x10016, location = Self)] + public entry fun test_initialize_validator_rejects_duplicate_consensus_pubkey_pending_active( + supra_framework: &signer, validator_1: &signer, validator_2: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, PendingTransactionFee { + initialize_for_test(supra_framework); + let (_sk, pk) = generate_identity(); + // validator_1 joins pending_active but no epoch transition. + initialize_test_validator(&pk, validator_1, 100, true, false); + // validator_2 tries to register with the same key against pending_active - should abort. + initialize_test_validator(&pk, validator_2, 100, false, false); + } + + #[test(supra_framework = @supra_framework, validator_1 = @0x123, validator_2 = @0x234)] + #[expected_failure(abort_code = 0x10017, location = Self)] + public entry fun test_initialize_validator_rejects_duplicate_network_addresses( + supra_framework: &signer, validator_1: &signer, validator_2: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorSet { + initialize_for_test(supra_framework); + let (_sk_1, pk_1) = generate_identity(); + let (_sk_2, pk_2) = generate_identity(); + let validator_1_address = signer::address_of(validator_1); + register_test_validator_with_addresses(&pk_1, validator_1, b"net-1", b"fn-1"); + mint_and_add_stake(validator_1, 100); + join_validator_set(validator_1, validator_1_address); + // validator_2 tries to reuse the same network address - should abort. + register_test_validator_with_addresses(&pk_2, validator_2, b"net-1", b"fn-2"); + } + + #[test(supra_framework = @supra_framework, validator_1 = @0x123, validator_2 = @0x234)] + public entry fun test_initialize_validator_allows_unique_credentials( + supra_framework: &signer, validator_1: &signer, validator_2: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorSet { + initialize_for_test(supra_framework); + let (_sk_1, pk_1) = generate_identity(); + let (_sk_2, pk_2) = generate_identity(); + let validator_1_address = signer::address_of(validator_1); + register_test_validator_with_addresses(&pk_1, validator_1, b"net-1", b"fn-1"); + mint_and_add_stake(validator_1, 100); + join_validator_set(validator_1, validator_1_address); + // Distinct key and address - should succeed. + register_test_validator_with_addresses(&pk_2, validator_2, b"net-2", b"fn-2"); + } + + #[test(supra_framework = @supra_framework, validator_1 = @0x123, validator_2 = @0x234)] + public entry fun test_initialize_validator_allows_two_empty_network_addresses( + supra_framework: &signer, validator_1: &signer, validator_2: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, PendingTransactionFee { + initialize_for_test(supra_framework); + let (_sk_1, pk_1) = generate_identity(); + let (_sk_2, pk_2) = generate_identity(); + // Both validators register with empty network_addresses via initialize_test_validator. + // The empty-skip rule lets this succeed; existing test helpers must keep working. + initialize_test_validator(&pk_1, validator_1, 100, true, false); + initialize_test_validator(&pk_2, validator_2, 100, false, false); + } + + #[test(supra_framework = @supra_framework, validator_1 = @0x123, validator_2 = @0x234)] + #[expected_failure(abort_code = 0x10016, location = Self)] + public entry fun test_rotate_consensus_key_rejects_duplicate( + supra_framework: &signer, validator_1: &signer, validator_2: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, PendingTransactionFee { + initialize_for_test(supra_framework); + let (sk_1, pk_1) = generate_identity(); + let (_sk_2, pk_2) = generate_identity(); + let pk_1_bytes = + validator_public_keys::serialized_keys_with_pop_for_test(&sk_1, &pk_1); + initialize_test_validator(&pk_1, validator_1, 100, true, true); + initialize_test_validator(&pk_2, validator_2, 100, true, true); + // validator_2 tries to rotate to validator_1's consensus key - should abort. + rotate_consensus_key(validator_2, signer::address_of(validator_2), pk_1_bytes); + } + + #[test(supra_framework = @supra_framework, validator = @0x123)] + public entry fun test_rotate_consensus_key_allows_fresh_key( + supra_framework: &signer, validator: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, PendingTransactionFee { + initialize_for_test(supra_framework); + let (_sk, pk) = generate_identity(); + initialize_test_validator(&pk, validator, 100, true, true); + let (sk_new, pk_new) = generate_identity(); + let pk_new_bytes = + validator_public_keys::serialized_keys_with_pop_for_test(&sk_new, &pk_new); + rotate_consensus_key(validator, signer::address_of(validator), pk_new_bytes); + } + + #[test(supra_framework = @supra_framework, validator = @0x123)] + public entry fun test_rotate_consensus_key_allows_self_rotation( + supra_framework: &signer, validator: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, PendingTransactionFee { + initialize_for_test(supra_framework); + let (sk, pk) = generate_identity(); + let pk_bytes = validator_public_keys::serialized_keys_with_pop_for_test( + &sk, &pk + ); + initialize_test_validator(&pk, validator, 100, true, true); + // Rotating to the same key the validator already holds is a no-op and must not abort. + rotate_consensus_key(validator, signer::address_of(validator), pk_bytes); + } + + #[test(supra_framework = @supra_framework, validator = @0x123)] + /// An operator rotation must preserve the DKG-managed BLS threshold keys (written by + /// `set_dkg_output_keys`) and only swap the static keys. This holds under the v2 identity format. + public entry fun test_rotate_consensus_key_preserves_threshold_keys( + supra_framework: &signer, validator: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, PendingTransactionFee { + initialize_for_test(supra_framework); + // v2 is enabled by default in the test VM; this makes the dependency explicit. + features::change_feature_flags_for_testing( + supra_framework, + vector[features::get_supra_validator_identity_v2_feature()], + vector[] + ); + + // Seed a DKG-style threshold key on the validator's initial keys. The fixture registers via + // the genesis (PoP-exempt) helper, so the seeded keys are stored as-is. Reuse the multisig + // key as a stand-in `bls12381::PublicKey` so the test needs no extra crypto imports. + let (_sk, pk) = generate_identity(); + let threshold_key = validator_public_keys::get_supra_bls_multi_sig_pub_key(&pk); + validator_public_keys::rotate_supra_bls_threshold_validity_key( + &mut pk, threshold_key + ); + initialize_test_validator(&pk, validator, 100, true, true); + + // Rotate to a fresh static identity whose threshold fields are empty (modelling an operator + // rotating from a node that has not yet received the latest DKG keys). The operator submits + // the keys with an appended BLS multisig proof-of-possession. + let (sk_new, pk_new) = generate_identity(); + let pk_new_bytes = + validator_public_keys::serialized_keys_with_pop_for_test(&sk_new, &pk_new); + rotate_consensus_key(validator, signer::address_of(validator), pk_new_bytes); + + let (stored_bytes, _net, _fn) = + get_validator_config(signer::address_of(validator)); + let stored = + validator_public_keys::validator_public_keys_from_bytes(stored_bytes); + + // The DKG threshold key survived the operator rotation (0 = validity certificate type). + let preserved = + validator_public_keys::get_supra_bls_threshold_key_by_type(&stored, 0); + assert!(option::is_some(&preserved), 3001); + assert!(option::extract(&mut preserved) == threshold_key, 3002); + + // The static keys were actually rotated to `pk_new`'s. + assert!( + validator_public_keys::get_supra_ed_key(&stored) + == validator_public_keys::get_supra_ed_key(&pk_new), + 3003 + ); + assert!( + validator_public_keys::get_network_key(&stored) + == validator_public_keys::get_network_key(&pk_new), + 3004 + ); + } + + #[test(supra_framework = @supra_framework, validator = @0x123)] + #[expected_failure(abort_code = 0x1000b, location = Self)] + /// Registration must reject a consensus public key blob that deserializes but carries a + /// malformed static key (here, an empty network key), even when its appended BLS multisig PoP + /// is valid. Validated under the v2 identity format. + public entry fun test_initialize_validator_rejects_invalid_consensus_pubkey( + supra_framework: &signer, validator: &signer + ) acquires AllowedValidators, ValidatorSet, ValidatorConfig { + initialize_for_test(supra_framework); + features::change_feature_flags_for_testing( + supra_framework, + vector[features::get_supra_validator_identity_v2_feature()], + vector[] + ); + let invalid_pubkey = + validator_public_keys::serialized_keys_with_invalid_network_key_and_pop_for_test(); + initialize_validator(validator, invalid_pubkey, b"net", b"fn"); + } + + #[test(supra_framework = @supra_framework, validator = @0x123)] + #[expected_failure(abort_code = 0x10018, location = Self)] + /// Under v2, an operator key submission whose appended BLS multisig PoP does not verify must be + /// rejected with `EINVALID_PROOF_OF_POSSESSION` (24 = 0x18). + public entry fun test_initialize_validator_rejects_invalid_pop( + supra_framework: &signer, validator: &signer + ) acquires AllowedValidators, ValidatorSet, ValidatorConfig { + initialize_for_test(supra_framework); + features::change_feature_flags_for_testing( + supra_framework, + vector[features::get_supra_validator_identity_v2_feature()], + vector[] + ); + // Well-formed keys, but the appended PoP is generated from a different (freshly generated) + // secret, so it does not match pk's multisig key. + let (_sk, pk) = generate_identity(); + let (other_sk, _other_pk) = generate_identity(); + let blob = + validator_public_keys::serialized_keys_with_pop_for_test(&other_sk, &pk); + initialize_validator(validator, blob, b"net", b"fn"); + } + + #[test(supra_framework = @supra_framework, validator = @0x123)] + /// Genesis registration is PoP-exempt: under v2, `initialize_validator_genesis` accepts a blob + /// with no appended PoP and stores it verbatim. + public entry fun test_initialize_validator_genesis_skips_pop( + supra_framework: &signer, validator: &signer + ) acquires AllowedValidators, ValidatorSet, ValidatorConfig { + initialize_for_test(supra_framework); + features::change_feature_flags_for_testing( + supra_framework, + vector[features::get_supra_validator_identity_v2_feature()], + vector[] + ); + let (_sk, pk) = generate_identity(); + let pk_bytes = validator_public_keys::public_key_to_bytes(pk); + let validator_address = signer::address_of(validator); + if (!account::exists_at(validator_address)) { + account::create_account_for_test(validator_address); + }; + initialize_validator_genesis(validator, pk_bytes, b"net", b"fn"); + let (stored_bytes, _net, _fn) = get_validator_config(validator_address); + assert!(stored_bytes == pk_bytes, 7001); + } + + #[test(supra_framework = @supra_framework, validator = @0x123)] + /// Pre-v2 migration fallback: an operator new-format submission must still carry a valid BLS + /// multisig PoP, which the contract verifies and strips, storing the canonical key. PoP + /// enforcement is tied to the key format, not the v2 flag. + public entry fun test_rotate_consensus_key_fallback_verifies_pop( + supra_framework: &signer, validator: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, PendingTransactionFee { + initialize_for_test(supra_framework); + let (_sk, pk) = generate_identity(); + initialize_test_validator(&pk, validator, 100, true, true); + + // Disable v2 to exercise the pre-v2 migration fallback. + features::change_feature_flags_for_testing( + supra_framework, + vector[], + vector[features::get_supra_validator_identity_v2_feature()] + ); + + let (sk_new, pk_new) = generate_identity(); + let blob = + validator_public_keys::serialized_keys_with_pop_for_test(&sk_new, &pk_new); + rotate_consensus_key(validator, signer::address_of(validator), blob); + + let (stored_bytes, _net, _fn) = + get_validator_config(signer::address_of(validator)); + assert!(stored_bytes == validator_public_keys::public_key_to_bytes(pk_new), 8001); + } + + #[test(supra_framework = @supra_framework, validator = @0x123)] + /// Pre-v2 migration fallback: a bare 32-byte ed25519 consensus key (legacy format) has no + /// aggregatable BLS key, so it is accepted without a PoP and stored unchanged. + public entry fun test_rotate_consensus_key_fallback_accepts_legacy_ed25519( + supra_framework: &signer, validator: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, PendingTransactionFee { + initialize_for_test(supra_framework); + let (_sk, pk) = generate_identity(); + initialize_test_validator(&pk, validator, 100, true, true); + features::change_feature_flags_for_testing( + supra_framework, + vector[], + vector[features::get_supra_validator_identity_v2_feature()] + ); + let (_legacy_sk, legacy_pk) = ed25519::generate_keys(); + let legacy_bytes = ed25519::validated_public_key_to_bytes(&legacy_pk); + rotate_consensus_key(validator, signer::address_of(validator), legacy_bytes); + let (stored_bytes, _net, _fn) = + get_validator_config(signer::address_of(validator)); + assert!(stored_bytes == legacy_bytes, 8101); + } + + #[test(supra_framework = @supra_framework, validator = @0x123)] + /// Under v2, a correctly pop-appended operator submission succeeds and the stored key is the + /// canonical `ValidatorPublicKeys` with the PoP stripped (parses with no trailing bytes). + public entry fun test_rotate_consensus_key_accepts_valid_pop_and_strips_it( + supra_framework: &signer, validator: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, PendingTransactionFee { + initialize_for_test(supra_framework); + let (_sk, pk) = generate_identity(); + initialize_test_validator(&pk, validator, 100, true, true); + + features::change_feature_flags_for_testing( + supra_framework, + vector[features::get_supra_validator_identity_v2_feature()], + vector[] + ); + + let (sk_new, pk_new) = generate_identity(); + let blob = + validator_public_keys::serialized_keys_with_pop_for_test(&sk_new, &pk_new); + rotate_consensus_key(validator, signer::address_of(validator), blob); + + // The stored key is the canonical (PoP-stripped) ValidatorPublicKeys for pk_new. + let (stored_bytes, _net, _fn) = + get_validator_config(signer::address_of(validator)); + let stored = + validator_public_keys::validator_public_keys_from_bytes(stored_bytes); + assert!( + validator_public_keys::get_supra_ed_key(&stored) + == validator_public_keys::get_supra_ed_key(&pk_new), + 6001 + ); + assert!( + stored_bytes == validator_public_keys::public_key_to_bytes(pk_new), + 6002 + ); + } + + #[test(supra_framework = @supra_framework, validator = @0x123)] + #[expected_failure(abort_code = 0x10018, location = Self)] + /// Pre-v2 migration fallback: a new-format submission with a non-matching PoP is rejected with + /// `EINVALID_PROOF_OF_POSSESSION` (24 = 0x18), exactly as under v2. + public entry fun test_rotate_consensus_key_fallback_rejects_invalid_pop( + supra_framework: &signer, validator: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, PendingTransactionFee { + initialize_for_test(supra_framework); + let (_sk, pk) = generate_identity(); + initialize_test_validator(&pk, validator, 100, true, true); + features::change_feature_flags_for_testing( + supra_framework, + vector[], + vector[features::get_supra_validator_identity_v2_feature()] + ); + // PoP generated from a different secret, so it does not match pk_new's multisig key. + let (_sk_new, pk_new) = generate_identity(); + let (other_sk, _other_pk) = generate_identity(); + let blob = + validator_public_keys::serialized_keys_with_pop_for_test(&other_sk, &pk_new); + rotate_consensus_key(validator, signer::address_of(validator), blob); + } + + #[test(supra_framework = @supra_framework, validator_1 = @0x123, validator_2 = @0x234)] + #[expected_failure(abort_code = 0x10017, location = Self)] + public entry fun test_update_network_addresses_rejects_duplicate( + supra_framework: &signer, validator_1: &signer, validator_2: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, PendingTransactionFee { + initialize_for_test(supra_framework); + let (_sk_1, pk_1) = generate_identity(); + let (_sk_2, pk_2) = generate_identity(); + let validator_1_address = signer::address_of(validator_1); + register_test_validator_with_addresses(&pk_1, validator_1, b"net-1", b"fn-1"); + mint_and_add_stake(validator_1, 100); + join_validator_set(validator_1, validator_1_address); + // validator_2 registers with empty addresses then tries to claim validator_1's net address. + initialize_test_validator(&pk_2, validator_2, 100, true, true); + update_network_and_fullnode_addresses( + validator_2, + signer::address_of(validator_2), + b"net-1", + b"fn-2" + ); + } + + #[test(supra_framework = @supra_framework, validator_1 = @0x123, validator_2 = @0x234)] + public entry fun test_update_network_addresses_allows_clear_to_empty( + supra_framework: &signer, validator_1: &signer, validator_2: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorSet { + initialize_for_test(supra_framework); + let (_sk_1, pk_1) = generate_identity(); + let (_sk_2, pk_2) = generate_identity(); + let validator_1_address = signer::address_of(validator_1); + let validator_2_address = signer::address_of(validator_2); + register_test_validator_with_addresses(&pk_1, validator_1, b"net-1", b"fn-1"); + mint_and_add_stake(validator_1, 100); + join_validator_set(validator_1, validator_1_address); + register_test_validator_with_addresses(&pk_2, validator_2, b"net-2", b"fn-2"); + mint_and_add_stake(validator_2, 100); + join_validator_set(validator_2, validator_2_address); + // Clearing to empty is always allowed (empty == "unset / non-functional"). + update_network_and_fullnode_addresses( + validator_2, + validator_2_address, + vector::empty(), + vector::empty() + ); + } + + #[test(supra_framework = @supra_framework, validator = @0x123)] + public entry fun test_update_network_addresses_allows_self( + supra_framework: &signer, validator: &signer + ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorSet { + initialize_for_test(supra_framework); + let (_sk, pk) = generate_identity(); + let validator_address = signer::address_of(validator); + register_test_validator_with_addresses(&pk, validator, b"net-self", b"fn-self"); + mint_and_add_stake(validator, 100); + join_validator_set(validator, validator_address); + // Re-setting the same address on self must be a no-op, not an abort. + update_network_and_fullnode_addresses( + validator, + validator_address, + b"net-self", + b"fn-self" + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x10007, location = Self)] public entry fun test_inactive_validator_can_add_stake_if_exceeding_max_allowed( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2111,11 +3232,18 @@ module supra_framework::stake { #[test(supra_framework = @0x1, validator_1 = @0x123, validator_2 = @0x234)] #[expected_failure(abort_code = 0x10007, location = Self)] public entry fun test_pending_active_validator_cannot_add_stake_if_exceeding_max_allowed( - supra_framework: &signer, - validator_1: &signer, - validator_2: &signer, + supra_framework: &signer, validator_1: &signer, validator_2: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 100000); + initialize_for_test_custom( + supra_framework, + 50, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 10, + 100000 + ); // Have one validator join the set to ensure the validator set is not empty when main validator joins. let (_sk_1, pk_1) = generate_identity(); initialize_test_validator(&pk_1, validator_1, 100, true, true); @@ -2131,8 +3259,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x10007, location = Self)] public entry fun test_active_validator_cannot_add_stake_if_exceeding_max_allowed( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); // Validator joins validator set and waits for epoch end so it's in the validator set. @@ -2146,8 +3273,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x10007, location = Self)] public entry fun test_active_validator_with_pending_inactive_stake_cannot_add_stake_if_exceeding_max_allowed( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); // Validator joins validator set and waits for epoch end so it's in the validator set. @@ -2165,9 +3291,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator_1 = @0x123, validator_2 = @0x234)] #[expected_failure(abort_code = 0x10007, location = Self)] public entry fun test_pending_inactive_cannot_add_stake_if_exceeding_max_allowed( - supra_framework: &signer, - validator_1: &signer, - validator_2: &signer, + supra_framework: &signer, validator_1: &signer, validator_2: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); let (_sk_1, pk_1) = generate_identity(); @@ -2184,8 +3308,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_end_to_end( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2241,8 +3364,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_inactive_validator_with_existing_lockup_join_validator_set( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2252,7 +3374,10 @@ module supra_framework::stake { increase_lockup(validator); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS / 2); let validator_address = signer::address_of(validator); - assert!(get_remaining_lockup_secs(validator_address) == LOCKUP_CYCLE_SECONDS / 2, 1); + assert!( + get_remaining_lockup_secs(validator_address) == LOCKUP_CYCLE_SECONDS / 2, + 1 + ); // Join the validator set with an existing lockup join_validator_set(validator, validator_address); @@ -2260,15 +3385,18 @@ module supra_framework::stake { // Validator is added to the set but lockup time shouldn't have changed. end_epoch(); assert!(get_validator_state(validator_address) == VALIDATOR_STATUS_ACTIVE, 2); - assert!(get_remaining_lockup_secs(validator_address) == LOCKUP_CYCLE_SECONDS / 2 - EPOCH_DURATION, 3); + assert!( + get_remaining_lockup_secs(validator_address) + == LOCKUP_CYCLE_SECONDS / 2 - EPOCH_DURATION, + 3 + ); assert_validator_state(validator_address, 100, 0, 0, 0, 0); } #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x10012, location = Self)] public entry fun test_cannot_reduce_lockup( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2285,12 +3413,19 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator_1 = @0x123, validator_2 = @0x234)] #[expected_failure(abort_code = 0x1000D, location = Self)] public entry fun test_inactive_validator_cannot_join_if_exceed_increase_limit( - supra_framework: &signer, - validator_1: &signer, - validator_2: &signer, + supra_framework: &signer, validator_1: &signer, validator_2: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { // Only 50% voting power increase is allowed in each epoch. - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 50); + initialize_for_test_custom( + supra_framework, + 50, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 10, + 50 + ); let (_sk_1, pk_1) = generate_identity(); let (_sk_2, pk_2) = generate_identity(); initialize_test_validator(&pk_1, validator_1, 100, false, false); @@ -2307,11 +3442,18 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator_1 = @0x123, validator_2 = @0x234)] public entry fun test_pending_active_validator_can_add_more_stake( - supra_framework: &signer, - validator_1: &signer, - validator_2: &signer, + supra_framework: &signer, validator_1: &signer, validator_2: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 10000); + initialize_for_test_custom( + supra_framework, + 50, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 10, + 10000 + ); // Need 1 validator to be in the active validator set so joining limit works. let (_sk_1, pk_1) = generate_identity(); let (_sk_2, pk_2) = generate_identity(); @@ -2321,7 +3463,10 @@ module supra_framework::stake { // Add more stake while still pending_active. let validator_2_address = signer::address_of(validator_2); join_validator_set(validator_2, validator_2_address); - assert!(get_validator_state(validator_2_address) == VALIDATOR_STATUS_PENDING_ACTIVE, 0); + assert!( + get_validator_state(validator_2_address) == VALIDATOR_STATUS_PENDING_ACTIVE, + 0 + ); mint_and_add_stake(validator_2, 100); assert_validator_state(validator_2_address, 200, 0, 0, 0, 0); } @@ -2329,12 +3474,19 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator_1 = @0x123, validator_2 = @0x234)] #[expected_failure(abort_code = 0x1000D, location = Self)] public entry fun test_pending_active_validator_cannot_add_more_stake_than_limit( - supra_framework: &signer, - validator_1: &signer, - validator_2: &signer, + supra_framework: &signer, validator_1: &signer, validator_2: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { // 100% voting power increase is allowed in each epoch. - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 100); + initialize_for_test_custom( + supra_framework, + 50, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 10, + 100 + ); // Need 1 validator to be in the active validator set so joining limit works. let (_sk_1, pk_1) = generate_identity(); initialize_test_validator(&pk_1, validator_1, 100, true, true); @@ -2350,35 +3502,49 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_pending_active_validator_leaves_validator_set( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); // Validator joins but epoch hasn't ended, so the validator is still pending_active. let (_sk, pk) = generate_identity(); initialize_test_validator(&pk, validator, 100, true, false); let validator_address = signer::address_of(validator); - assert!(get_validator_state(validator_address) == VALIDATOR_STATUS_PENDING_ACTIVE, 0); + assert!( + get_validator_state(validator_address) == VALIDATOR_STATUS_PENDING_ACTIVE, + 0 + ); // Check that voting power increase is tracked. - assert!(borrow_global(@supra_framework).total_joining_power == 100, 0); + assert!( + borrow_global(@supra_framework).total_joining_power == 100, 0 + ); // Leave the validator set immediately. leave_validator_set(validator, validator_address); assert!(get_validator_state(validator_address) == VALIDATOR_STATUS_INACTIVE, 1); // Check that voting power increase has been decreased when the pending active validator leaves. - assert!(borrow_global(@supra_framework).total_joining_power == 0, 1); + assert!( + borrow_global(@supra_framework).total_joining_power == 0, 1 + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x1000D, location = Self)] public entry fun test_active_validator_cannot_add_more_stake_than_limit_in_multiple_epochs( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { // Only 50% voting power increase is allowed in each epoch. - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 50); + initialize_for_test_custom( + supra_framework, + 50, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 10, + 50 + ); // Add initial stake and join the validator set. let (_sk, pk) = generate_identity(); initialize_test_validator(&pk, validator, 100, true, true); @@ -2396,11 +3562,19 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x1000D, location = Self)] public entry fun test_active_validator_cannot_add_more_stake_than_limit( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { // Only 50% voting power increase is allowed in each epoch. - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 50); + initialize_for_test_custom( + supra_framework, + 50, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 10, + 50 + ); let (_sk, pk) = generate_identity(); initialize_test_validator(&pk, validator, 100, true, true); @@ -2410,11 +3584,19 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_active_validator_unlock_partial_stake( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { // Reward rate = 10%. - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 100); + initialize_for_test_custom( + supra_framework, + 50, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 10, + 100 + ); let (_sk, pk) = generate_identity(); initialize_test_validator(&pk, validator, 100, true, true); @@ -2436,8 +3618,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_active_validator_can_withdraw_all_stake_and_rewards_at_once( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2451,7 +3632,11 @@ module supra_framework::stake { assert_validator_state(validator_address, 101, 0, 0, 0, 0); // Unlock all coins while still having a lockup. - assert!(get_remaining_lockup_secs(validator_address) == LOCKUP_CYCLE_SECONDS - EPOCH_DURATION, 2); + assert!( + get_remaining_lockup_secs(validator_address) + == LOCKUP_CYCLE_SECONDS - EPOCH_DURATION, + 2 + ); unlock(validator, 101); assert_validator_state(validator_address, 0, 0, 0, 101, 0); @@ -2473,8 +3658,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_active_validator_unlocking_more_than_available_stake_should_cap( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2487,8 +3671,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_active_validator_withdraw_should_cap_by_inactive_stake( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); // Initial balance = 900 (idle) + 100 (staked) = 1000. @@ -2512,8 +3695,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_active_validator_can_reactivate_pending_inactive_stake( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2531,8 +3713,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_active_validator_reactivate_more_than_available_pending_inactive_stake_should_cap( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2548,8 +3729,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_active_validator_having_insufficient_remaining_stake_after_withdrawal_gets_kicked( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2575,9 +3755,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123, validator_2 = @0x234)] public entry fun test_active_validator_leaves_staking_but_still_has_a_lockup( - supra_framework: &signer, - validator: &signer, - validator_2: &signer, + supra_framework: &signer, validator: &signer, validator_2: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); let (_sk_1, pk_1) = generate_identity(); @@ -2591,7 +3769,10 @@ module supra_framework::stake { assert!(get_remaining_lockup_secs(validator_address) == LOCKUP_CYCLE_SECONDS, 0); leave_validator_set(validator, validator_address); // Validator is in pending_inactive state but is technically still part of the validator set. - assert!(get_validator_state(validator_address) == VALIDATOR_STATUS_PENDING_INACTIVE, 2); + assert!( + get_validator_state(validator_address) == VALIDATOR_STATUS_PENDING_INACTIVE, + 2 + ); assert_validator_state(validator_address, 100, 0, 0, 0, 1); end_epoch(); @@ -2599,7 +3780,11 @@ module supra_framework::stake { assert!(get_validator_state(validator_address) == VALIDATOR_STATUS_INACTIVE, 3); // However, their stake, including rewards, should still subject to the existing lockup. assert_validator_state(validator_address, 101, 0, 0, 0, 1); - assert!(get_remaining_lockup_secs(validator_address) == LOCKUP_CYCLE_SECONDS - EPOCH_DURATION, 4); + assert!( + get_remaining_lockup_secs(validator_address) + == LOCKUP_CYCLE_SECONDS - EPOCH_DURATION, + 4 + ); // If they try to unlock, their stake is moved to pending_inactive and would only be withdrawable after the // lockup has expired. @@ -2619,9 +3804,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123, validator_2 = @0x234)] public entry fun test_active_validator_leaves_staking_and_rejoins_with_expired_lockup_should_be_renewed( - supra_framework: &signer, - validator: &signer, - validator_2: &signer, + supra_framework: &signer, validator: &signer, validator_2: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); let (_sk_1, pk_1) = generate_identity(); @@ -2650,12 +3833,19 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator_1 = @0x123, validator_2 = @0x234)] public entry fun test_pending_inactive_validator_does_not_count_in_increase_limit( - supra_framework: &signer, - validator_1: &signer, - validator_2: &signer, + supra_framework: &signer, validator_1: &signer, validator_2: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { // Only 50% voting power increase is allowed in each epoch. - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 50); + initialize_for_test_custom( + supra_framework, + 50, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 10, + 50 + ); let (_sk_1, pk_1) = generate_identity(); let (_sk_2, pk_2) = generate_identity(); initialize_test_validator(&pk_1, validator_1, 100, true, false); @@ -2668,7 +3858,14 @@ module supra_framework::stake { mint_and_add_stake(validator_1, 51); } - #[test(supra_framework = @0x1, validator_1 = @0x123, validator_2 = @0x234, validator_3 = @0x345)] + #[ + test( + supra_framework = @0x1, + validator_1 = @0x123, + validator_2 = @0x234, + validator_3 = @0x345 + ) + ] public entry fun test_multiple_validators_join_and_leave( supra_framework: &signer, validator_1: &signer, @@ -2679,9 +3876,18 @@ module supra_framework::stake { let validator_2_address = signer::address_of(validator_2); let validator_3_address = signer::address_of(validator_3); - initialize_for_test_custom(supra_framework, 100, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 100, 100); + initialize_for_test_custom( + supra_framework, + 100, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 100, + 100 + ); let (_sk_1, pk_1) = generate_identity(); - let pk_1_bytes = ed25519::unvalidated_public_key_to_bytes(&pk_1); + let pk_1_bytes = validator_public_keys::public_key_to_bytes(pk_1); let (_sk_2, pk_2) = generate_identity(); let (_sk_3, pk_3) = generate_identity(); initialize_test_validator(&pk_1, validator_1, 100, false, false); @@ -2707,13 +3913,23 @@ module supra_framework::stake { assert!(validator_config_2.config.validator_index == 1, 5); // Validator 1 rotates consensus key. Validator 2 leaves. Validator 3 joins. - let (_sk_1b, pk_1b) = generate_identity(); - let pk_1b_bytes = ed25519::unvalidated_public_key_to_bytes(&pk_1b); - rotate_consensus_key(validator_1, validator_1_address, pk_1b_bytes); + let (sk_1b, pk_1b) = generate_identity(); + // `pk_1b_bytes` is the canonical (PoP-stripped) form the contract stores; the submission + // carries the appended PoP. + let pk_1b_bytes = validator_public_keys::public_key_to_bytes(pk_1b); + rotate_consensus_key( + validator_1, + validator_1_address, + validator_public_keys::serialized_keys_with_pop_for_test(&sk_1b, &pk_1b) + ); leave_validator_set(validator_2, validator_2_address); join_validator_set(validator_3, validator_3_address); // Validator 2 is not effectively removed until next epoch. - assert!(get_validator_state(validator_2_address) == VALIDATOR_STATUS_PENDING_INACTIVE, 6); + assert!( + get_validator_state(validator_2_address) + == VALIDATOR_STATUS_PENDING_INACTIVE, + 6 + ); assert!( vector::borrow( &borrow_global(@supra_framework).pending_inactive, @@ -2722,7 +3938,10 @@ module supra_framework::stake { 0 ); // Validator 3 is not effectively added until next epoch. - assert!(get_validator_state(validator_3_address) == VALIDATOR_STATUS_PENDING_ACTIVE, 7); + assert!( + get_validator_state(validator_3_address) == VALIDATOR_STATUS_PENDING_ACTIVE, + 7 + ); assert!( vector::borrow( &borrow_global(@supra_framework).pending_active, @@ -2760,15 +3979,25 @@ module supra_framework::stake { unlock(validator_1, 50); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_epoch(); - assert!(get_validator_state(validator_1_address) == VALIDATOR_STATUS_INACTIVE, 11); + assert!( + get_validator_state(validator_1_address) == VALIDATOR_STATUS_INACTIVE, 11 + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_delegated_staking_with_owner_cap( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { - initialize_for_test_custom(supra_framework, 100, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 100, 100); + initialize_for_test_custom( + supra_framework, + 100, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 100, + 100 + ); let (_sk, pk) = generate_identity(); initialize_test_validator(&pk, validator, 0, false, false); let owner_cap = extract_owner_cap(validator); @@ -2796,9 +4025,15 @@ module supra_framework::stake { assert_validator_state(pool_address, 0, 0, 0, 0, 0); // Operator can separately rotate consensus key. - let (_sk_new, pk_new) = generate_identity(); - let pk_new_bytes = ed25519::unvalidated_public_key_to_bytes(&pk_new); - rotate_consensus_key(validator, pool_address, pk_new_bytes); + let (sk_new, pk_new) = generate_identity(); + // `pk_new_bytes` is the canonical (PoP-stripped) form the contract stores; the submission + // carries the appended PoP. + let pk_new_bytes = validator_public_keys::public_key_to_bytes(pk_new); + rotate_consensus_key( + validator, + pool_address, + validator_public_keys::serialized_keys_with_pop_for_test(&sk_new, &pk_new) + ); let validator_config = borrow_global(pool_address); assert!(validator_config.consensus_pubkey == pk_new_bytes, 2); @@ -2817,10 +4052,18 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x1000A, location = Self)] public entry fun test_validator_cannot_join_post_genesis( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { - initialize_for_test_custom(supra_framework, 100, 10000, LOCKUP_CYCLE_SECONDS, false, 1, 100, 100); + initialize_for_test_custom( + supra_framework, + 100, + 10000, + LOCKUP_CYCLE_SECONDS, + false, + 1, + 100, + 100 + ); // Joining the validator set should fail as post genesis validator set change is not allowed. let (_sk, pk) = generate_identity(); @@ -2830,8 +4073,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x1000E, location = Self)] public entry fun test_invalid_pool_address( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2842,10 +4084,18 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x1000A, location = Self)] public entry fun test_validator_cannot_leave_post_genesis( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { - initialize_for_test_custom(supra_framework, 100, 10000, LOCKUP_CYCLE_SECONDS, false, 1, 100, 100); + initialize_for_test_custom( + supra_framework, + 100, + 10000, + LOCKUP_CYCLE_SECONDS, + false, + 1, + 100, + 100 + ); let (_sk, pk) = generate_identity(); initialize_test_validator(&pk, validator, 100, false, false); @@ -2858,21 +4108,23 @@ module supra_framework::stake { leave_validator_set(validator, validator_address); } - #[test( - supra_framework = @supra_framework, - validator_1 = @supra_framework, - validator_2 = @0x2, - validator_3 = @0x3, - validator_4 = @0x4, - validator_5 = @0x5 - )] + #[ + test( + supra_framework = @supra_framework, + validator_1 = @supra_framework, + validator_2 = @0x2, + validator_3 = @0x3, + validator_4 = @0x4, + validator_5 = @0x5 + ) + ] fun test_validator_consensus_infos_from_validator_set( supra_framework: &signer, validator_1: &signer, validator_2: &signer, validator_3: &signer, validator_4: &signer, - validator_5: &signer, + validator_5: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { let v1_addr = signer::address_of(validator_1); let v2_addr = signer::address_of(validator_2); @@ -2901,47 +4153,73 @@ module supra_framework::stake { join_validator_set(validator_1, v1_addr); join_validator_set(validator_5, v5_addr); end_epoch(); - let vci_vec_0 = validator_consensus_infos_from_validator_set(borrow_global(@supra_framework)); - let vci_addrs = vector::map_ref(&vci_vec_0, |obj|{ - let vci: &ValidatorConsensusInfo = obj; - validator_consensus_info::get_addr(vci) - }); - let vci_voting_powers = vector::map_ref(&vci_vec_0, |obj|{ - let vci: &ValidatorConsensusInfo = obj; - validator_consensus_info::get_voting_power(vci) - }); - assert!(vector[@0x5, @supra_framework, @0x3] == vci_addrs, 1); + let vci_vec_0 = + validator_consensus_infos_from_validator_set( + borrow_global(@supra_framework) + ); + let vci_addrs = vector::map_ref( + &vci_vec_0, + |obj| { + let vci: &ValidatorConsensusInfo = obj; + validator_consensus_info::get_addr(vci) + } + ); + let vci_voting_powers = vector::map_ref( + &vci_vec_0, + |obj| { + let vci: &ValidatorConsensusInfo = obj; + validator_consensus_info::get_voting_power(vci) + } + ); + assert!( + vector[@0x5, @supra_framework, @0x3] == vci_addrs, + 1 + ); // assert!(vector[pk_5_bytes, pk_1_bytes, pk_3_bytes] == vci_pks, 2); assert!(vector[105, 101, 103] == vci_voting_powers, 3); leave_validator_set(validator_3, v3_addr); - let vci_vec_1 = validator_consensus_infos_from_validator_set(borrow_global(@supra_framework)); + let vci_vec_1 = + validator_consensus_infos_from_validator_set( + borrow_global(@supra_framework) + ); assert!(vci_vec_0 == vci_vec_1, 11); join_validator_set(validator_2, v2_addr); - let vci_vec_2 = validator_consensus_infos_from_validator_set(borrow_global(@supra_framework)); + let vci_vec_2 = + validator_consensus_infos_from_validator_set( + borrow_global(@supra_framework) + ); assert!(vci_vec_0 == vci_vec_2, 12); leave_validator_set(validator_1, v1_addr); - let vci_vec_3 = validator_consensus_infos_from_validator_set(borrow_global(@supra_framework)); + let vci_vec_3 = + validator_consensus_infos_from_validator_set( + borrow_global(@supra_framework) + ); assert!(vci_vec_0 == vci_vec_3, 13); join_validator_set(validator_4, v4_addr); - let vci_vec_4 = validator_consensus_infos_from_validator_set(borrow_global(@supra_framework)); + let vci_vec_4 = + validator_consensus_infos_from_validator_set( + borrow_global(@supra_framework) + ); assert!(vci_vec_0 == vci_vec_4, 14); } - #[test( - supra_framework = @supra_framework, - validator_1 = @supra_framework, - validator_2 = @0x2, - validator_3 = @0x3, - validator_4 = @0x4, - validator_5 = @0x5 - )] + #[ + test( + supra_framework = @supra_framework, + validator_1 = @supra_framework, + validator_2 = @0x2, + validator_3 = @0x3, + validator_4 = @0x4, + validator_5 = @0x5 + ) + ] public entry fun test_staking_validator_index( supra_framework: &signer, validator_1: &signer, validator_2: &signer, validator_3: &signer, validator_4: &signer, - validator_5: &signer, + validator_5: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { let v1_addr = signer::address_of(validator_1); let v2_addr = signer::address_of(validator_2); @@ -3002,9 +4280,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator_1 = @0x123, validator_2 = @0x234)] public entry fun test_validator_rewards_are_performance_based( - supra_framework: &signer, - validator_1: &signer, - validator_2: &signer, + supra_framework: &signer, validator_1: &signer, validator_2: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); @@ -3019,8 +4295,10 @@ module supra_framework::stake { // Validator 2 failed proposal. let failed_proposer_indices = vector::empty(); - let validator_1_index = borrow_global(validator_1_address).validator_index; - let validator_2_index = borrow_global(validator_2_address).validator_index; + let validator_1_index = + borrow_global(validator_1_address).validator_index; + let validator_2_index = + borrow_global(validator_2_address).validator_index; vector::push_back(&mut failed_proposer_indices, validator_2_index); let proposer_indices = option::some(validator_1_index); update_performance_statistics(proposer_indices, failed_proposer_indices); @@ -3034,8 +4312,10 @@ module supra_framework::stake { unlock(validator_2, 100); leave_validator_set(validator_2, validator_2_address); let failed_proposer_indices = vector::empty(); - let validator_1_index = borrow_global(validator_1_address).validator_index; - let validator_2_index = borrow_global(validator_2_address).validator_index; + let validator_1_index = + borrow_global(validator_1_address).validator_index; + let validator_2_index = + borrow_global(validator_2_address).validator_index; vector::push_back(&mut failed_proposer_indices, validator_1_index); vector::push_back(&mut failed_proposer_indices, validator_2_index); update_performance_statistics(option::none(), failed_proposer_indices); @@ -3050,9 +4330,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator_1 = @0x123, validator_2 = @0x234)] public entry fun test_validator_rewards_rate_decrease_over_time( - supra_framework: &signer, - validator_1: &signer, - validator_2: &signer, + supra_framework: &signer, validator_1: &signer, validator_2: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); @@ -3080,9 +4358,13 @@ module supra_framework::stake { fixed_point64::create_from_rational(3, 1000), one_year_in_secs, genesis_time_in_secs, - fixed_point64::create_from_rational(50, 100), + fixed_point64::create_from_rational(50, 100) + ); + features::change_feature_flags_for_testing( + supra_framework, + vector[features::get_periodical_reward_rate_decrease_feature()], + vector[] ); - features::change_feature_flags_for_testing(supra_framework, vector[features::get_periodical_reward_rate_decrease_feature()], vector[]); // For some reason, this epoch is very long. It has been 1 year since genesis when the epoch ends. timestamp::fast_forward_seconds(one_year_in_secs - EPOCH_DURATION * 3); @@ -3107,8 +4389,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_update_performance_statistics_should_not_fail_due_to_out_of_bounds( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); @@ -3116,7 +4397,8 @@ module supra_framework::stake { let (_sk, pk) = generate_identity(); initialize_test_validator(&pk, validator, 100, true, true); - let valid_validator_index = borrow_global(validator_address).validator_index; + let valid_validator_index = + borrow_global(validator_address).validator_index; let out_of_bounds_index = valid_validator_index + 100; // Invalid validator index in the failed proposers vector should not lead to abort. @@ -3138,15 +4420,28 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x1000B, location = Self)] public entry fun test_invalid_config( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorSet { - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 100, 100); + initialize_for_test_custom( + supra_framework, + 50, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 100, + 100 + ); // Call initialize_stake_owner, which only initializes the stake pool but not validator config. let validator_address = signer::address_of(validator); account::create_account_for_test(validator_address); - initialize_stake_owner(validator, 0, validator_address, validator_address); + initialize_stake_owner( + validator, + 0, + validator_address, + validator_address + ); mint_and_add_stake(validator, 100); // Join the validator set with enough stake. This should fail because the validator didn't initialize validator @@ -3156,21 +4451,35 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_valid_config( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorSet { - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 100, 100); + initialize_for_test_custom( + supra_framework, + 50, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 100, + 100 + ); // Call initialize_stake_owner, which only initializes the stake pool but not validator config. let validator_address = signer::address_of(validator); account::create_account_for_test(validator_address); - initialize_stake_owner(validator, 0, validator_address, validator_address); + initialize_stake_owner( + validator, + 0, + validator_address, + validator_address + ); mint_and_add_stake(validator, 100); // Initialize validator config. let validator_address = signer::address_of(validator); - let (_sk_new, pk_new) = generate_identity(); - let pk_new_bytes = ed25519::unvalidated_public_key_to_bytes(&pk_new); + let (sk_new, pk_new) = generate_identity(); + let pk_new_bytes = + validator_public_keys::serialized_keys_with_pop_for_test(&sk_new, &pk_new); rotate_consensus_key(validator, validator_address, pk_new_bytes); // Join the validator set with enough stake. This now wouldn't fail since the validator config already exists. @@ -3184,13 +4493,14 @@ module supra_framework::stake { let num_total_proposals = 200; let rewards_rate = 700; let rewards_rate_denominator = 777; - let rewards_amount = calculate_rewards_amount( - stake_amount, - num_successful_proposals, - num_total_proposals, - rewards_rate, - rewards_rate_denominator - ); + let rewards_amount = + calculate_rewards_amount( + stake_amount, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ); // Consider `amount_imprecise` and `amount_precise` defined as follows: // amount_imprecise = (stake_amount * rewards_rate / rewards_rate_denominator) * num_successful_proposals / num_total_proposals // amount_precise = stake_amount * rewards_rate * num_successful_proposals / (rewards_rate_denominator * num_total_proposals) @@ -3205,45 +4515,61 @@ module supra_framework::stake { let rewards_rate = 3141592; let rewards_rate_denominator = 10000000; // This should not abort due to an arithmetic overflow. - let rewards_amount = calculate_rewards_amount( - stake_amount, - num_successful_proposals, - num_total_proposals, - rewards_rate, - rewards_rate_denominator - ); + let rewards_amount = + calculate_rewards_amount( + stake_amount, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ); assert!(rewards_amount == 31412778408000000, 0); } #[test_only] public fun set_validator_perf_at_least_one_block() acquires ValidatorPerformance { let validator_perf = borrow_global_mut(@supra_framework); - vector::for_each_mut(&mut validator_perf.validators, |validator|{ - let validator: &mut IndividualValidatorPerformance = validator; - if (validator.successful_proposals + validator.failed_proposals < 1) { - validator.successful_proposals = 1; - }; - }); + vector::for_each_mut( + &mut validator_perf.validators, + |validator| { + let validator: &mut IndividualValidatorPerformance = validator; + if (validator.successful_proposals + validator.failed_proposals < 1) { + validator.successful_proposals = 1; + }; + } + ); } #[test(supra_framework = @0x1, validator_1 = @0x123, validator_2 = @0x234)] public entry fun test_removing_validator_from_active_set( - supra_framework: &signer, - validator_1: &signer, - validator_2: &signer, + supra_framework: &signer, validator_1: &signer, validator_2: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { initialize_for_test(supra_framework); let (_sk_1, pk_1) = generate_identity(); let (_sk_2, pk_2) = generate_identity(); initialize_test_validator(&pk_1, validator_1, 100, true, false); initialize_test_validator(&pk_2, validator_2, 100, true, true); - assert!(vector::length(&borrow_global(@supra_framework).active_validators) == 2, 0); + assert!( + vector::length( + &borrow_global(@supra_framework).active_validators + ) == 2, + 0 + ); // Remove validator 1 from the active validator set. Only validator 2 remains. let validator_to_remove = signer::address_of(validator_1); remove_validators(supra_framework, &vector[validator_to_remove]); - assert!(vector::length(&borrow_global(@supra_framework).active_validators) == 1, 0); - assert!(get_validator_state(validator_to_remove) == VALIDATOR_STATUS_PENDING_INACTIVE, 1); + assert!( + vector::length( + &borrow_global(@supra_framework).active_validators + ) == 1, + 0 + ); + assert!( + get_validator_state(validator_to_remove) + == VALIDATOR_STATUS_PENDING_INACTIVE, + 1 + ); } #[test(vm = @0x0, supra_framework = @0x1, validator_0 = @0x123, validator_1 = @0x234)] @@ -3333,8 +4659,7 @@ module supra_framework::stake { } #[test_only] - public fun end_epoch( - ) acquires SupraCoinCapabilities, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { + public fun end_epoch() acquires SupraCoinCapabilities, PendingTransactionFee, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet { // Set the number of blocks to 1, to give out rewards to non-failing validators. set_validator_perf_at_least_one_block(); timestamp::fast_forward_seconds(EPOCH_DURATION); @@ -3349,7 +4674,7 @@ module supra_framework::stake { active_stake: u64, inactive_stake: u64, pending_active_stake: u64, - pending_inactive_stake: u64, + pending_inactive_stake: u64 ) acquires StakePool { let stake_pool = borrow_global(pool_address); let actual_active_stake = coin::value(&stake_pool.active); @@ -3357,9 +4682,15 @@ module supra_framework::stake { let actual_inactive_stake = coin::value(&stake_pool.inactive); assert!(actual_inactive_stake == inactive_stake, actual_inactive_stake); let actual_pending_active_stake = coin::value(&stake_pool.pending_active); - assert!(actual_pending_active_stake == pending_active_stake, actual_pending_active_stake); + assert!( + actual_pending_active_stake == pending_active_stake, + actual_pending_active_stake + ); let actual_pending_inactive_stake = coin::value(&stake_pool.pending_inactive); - assert!(actual_pending_inactive_stake == pending_inactive_stake, actual_pending_inactive_stake); + assert!( + actual_pending_inactive_stake == pending_inactive_stake, + actual_pending_inactive_stake + ); } #[test_only] @@ -3369,17 +4700,25 @@ module supra_framework::stake { inactive_stake: u64, pending_active_stake: u64, pending_inactive_stake: u64, - validator_index: u64, + validator_index: u64 ) acquires StakePool, ValidatorConfig { - assert_stake_pool(pool_address, active_stake, inactive_stake, pending_active_stake, pending_inactive_stake); + assert_stake_pool( + pool_address, + active_stake, + inactive_stake, + pending_active_stake, + pending_inactive_stake + ); let validator_config = borrow_global(pool_address); - assert!(validator_config.validator_index == validator_index, validator_config.validator_index); + assert!( + validator_config.validator_index == validator_index, + validator_config.validator_index + ); } #[test(supra_framework = @0x1, validator = @0x123)] public entry fun test_allowed_validators( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, ValidatorSet { let addr = signer::address_of(validator); let (burn, mint) = supra_coin::initialize_for_test(supra_framework); @@ -3395,8 +4734,7 @@ module supra_framework::stake { #[test(supra_framework = @0x1, validator = @0x123)] #[expected_failure(abort_code = 0x60011, location = Self)] public entry fun test_not_allowed_validators( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, ValidatorSet { configure_allowed_validators(supra_framework, vector[]); let (burn, mint) = supra_coin::initialize_for_test(supra_framework); @@ -3411,7 +4749,8 @@ module supra_framework::stake { #[test_only] public fun with_rewards(amount: u64): u64 { - let (numerator, denominator) = staking_config::get_reward_rate(&staking_config::get()); + let (numerator, denominator) = + staking_config::get_reward_rate(&staking_config::get()); amount + amount * numerator / denominator } } diff --git a/aptos-move/framework/supra-framework/sources/stake.spec.move b/aptos-move/framework/supra-framework/sources/stake.spec.move index 185c0c11caf..7bbf062f54f 100644 --- a/aptos-move/framework/supra-framework/sources/stake.spec.move +++ b/aptos-move/framework/supra-framework/sources/stake.spec.move @@ -127,6 +127,10 @@ spec supra_framework::stake { ){ pragma verify = false; + // Partial: the function also aborts when `consensus_pubkey` or `network_addresses` + // collide with another validator in the next validator set. + pragma aborts_if_is_partial = true; + include AbortsIfSignerPermissionStake { s: account }; @@ -370,6 +374,9 @@ spec supra_framework::stake { new_network_addresses: vector, new_fullnode_addresses: vector, ) { + // Partial: the function also aborts when `new_network_addresses` collides + // with another validator in the next validator set. + pragma aborts_if_is_partial = true; include AbortsIfSignerPermissionStake { s: operator }; @@ -418,6 +425,9 @@ spec supra_framework::stake { pool_address: address, new_consensus_pubkey: vector, ) { + // Partial: the function also aborts when `new_consensus_pubkey` collides + // with another validator in the next validator set. + pragma aborts_if_is_partial = true; include AbortsIfSignerPermissionStake { s: operator }; @@ -427,10 +437,12 @@ spec supra_framework::stake { aborts_if !exists(pool_address); aborts_if signer::address_of(operator) != pre_stake_pool.operator_address; aborts_if !exists(pool_address); - let is_public_key_validated = ed25519::spec_public_key_validate_internal( + + //todo: fix this check + /*let is_public_key_validated = ed25519::spec_public_key_validate_internal( new_consensus_pubkey, ); - aborts_if !is_public_key_validated; + aborts_if !is_public_key_validated;*/ modifies global(pool_address); include StakedValueNochange; @@ -992,3 +1004,4 @@ spec supra_framework::stake { pragma verify = false; } } + diff --git a/aptos-move/framework/supra-framework/sources/supra_dkg.move b/aptos-move/framework/supra-framework/sources/supra_dkg.move new file mode 100644 index 00000000000..4d2d46b6d74 --- /dev/null +++ b/aptos-move/framework/supra-framework/sources/supra_dkg.move @@ -0,0 +1,234 @@ +// Copyright (c) 2024 Supra. +/// DKG on-chain states and helper functions. +module supra_framework::supra_dkg { + use std::dkg_committee::{DkgCommittee, ReceiverCommittee, new_dkg_committee_output}; + use std::error; + use std::option; + use std::option::{Option}; + use std::vector; + use aptos_std::any; + use aptos_std::type_info; + use supra_framework::event::emit; + use supra_framework::system_addresses; + use supra_framework::timestamp; + use supra_framework::stake; + + friend supra_framework::block; + friend supra_framework::reconfiguration_with_dkg; + + const EDKG_NOT_IN_PROGRESS: u64 = 1; + const EDKG_META_ALREADY_SET: u64 = 2; + const EDKG_META_NOT_SET: u64 = 3; + const EDKG_INVALID_PK_SHARES: u64 = 4; + + #[event] + struct DKGStartEvent has drop, store { + session_metadata: DKGSessionMetadata, + start_time_us: u64 + } + + #[event] + struct DKGMetaSetEvent has drop, store { + dkg_meta_transcript: vector + } + + #[event] + struct DKGFinishEvent has drop, store { + target_committees_public_key_shares: vector + } + + /// This can be considered as the public input of DKG. + struct DKGSessionMetadata has copy, drop, store { + dealer_epoch: u64, + randomness_seed: vector, + dealer_committee: DkgCommittee, + target_committees: vector + } + + /// The input and output of a DKG session. + /// The validator set of epoch `x` works together for an DKG output for the target validator set of epoch `x+1`. + struct DKGSessionState has copy, store, drop { + metadata: DKGSessionMetadata, + start_time_us: u64, + dkg_meta_transcript: vector, + target_committees_public_key_shares: vector + } + + /// The completed and in-progress DKG sessions. + struct DKGState has key { + last_completed: Option, + in_progress: Option + } + + struct OnChainAggregateCommitment has copy, drop { + bls12381_commitment_g: vector, + bls12381_commitment_evals: vector>, + dealer_ids: vector, + committee_index: u32, + epoch: u64, + chain_id: u8, + threshold_type: u8 + } + + struct OnChainAggregateCommitmentAllCommittees has copy, drop { + commitments: vector + } + + /// Called in genesis to initialize on-chain states when DKG is active from genesis, + /// otherwise, must be called from a governance script before the DKG feature flag + /// is activated. + public fun initialize(supra_framework: &signer) { + system_addresses::assert_supra_framework(supra_framework); + if (!exists(@supra_framework)) { + move_to( + supra_framework, + DKGState { + last_completed: std::option::none(), + in_progress: std::option::none() + } + ); + }; + } + + /// Mark on-chain DKG state as in-progress. Notify validators to start DKG. + /// Abort if a DKG is already in progress. + public(friend) fun start( + dealer_epoch: u64, + randomness_seed: vector, + dealer_committee: DkgCommittee, + target_committees: vector + ) acquires DKGState { + let dkg_state = borrow_global_mut(@supra_framework); + let new_session_metadata = DKGSessionMetadata { + dealer_epoch, + randomness_seed, + dealer_committee, + target_committees + }; + let start_time_us = timestamp::now_microseconds(); + dkg_state.in_progress = std::option::some( + DKGSessionState { + metadata: new_session_metadata, + start_time_us, + dkg_meta_transcript: vector[], + target_committees_public_key_shares: vector[] + } + ); + + emit(DKGStartEvent { start_time_us, session_metadata: new_session_metadata }); + } + + /// Family Node sets the DKGMeta for the in-progress DKG session + /// The dkg transcript is assumed to have been already verified by the aptos VM in `process_dkg_result` method + public(friend) fun set_dkg_meta(dkg_meta_all_committees: vector) acquires DKGState { + // ensure dkg is in progress + let dkg_state = borrow_global_mut(@supra_framework); + assert!( + option::is_some(&dkg_state.in_progress), + error::invalid_state(EDKG_NOT_IN_PROGRESS) + ); + + // we only add the first DKG Meta proposed and ignore the rest + let session = option::extract(&mut dkg_state.in_progress); + assert!( + vector::length(&session.dkg_meta_transcript) == 0, + error::already_exists(EDKG_META_ALREADY_SET) + ); + session.dkg_meta_transcript = dkg_meta_all_committees; + dkg_state.in_progress = option::some(session); + + emit(DKGMetaSetEvent { dkg_meta_transcript: dkg_meta_all_committees }); + } + + /// Family Node sets the `target_committees_public_key_shares` for the in-progress DKG session and + /// marks the incomplete DKG session completed. + ///The `target_committees_public_key_shares` is assumed to be verified by the aptos VM before calling this function + public(friend) fun finish( + target_committees_public_key_shares: vector + ) acquires DKGState { + // ensure dkg is in progress + let dkg_state = borrow_global_mut(@supra_framework); + assert!( + option::is_some(&dkg_state.in_progress), + error::invalid_state(EDKG_NOT_IN_PROGRESS) + ); + + // DKG meta should be already set before `finish` is called + let session = option::extract(&mut dkg_state.in_progress); + assert!( + vector::length(&session.dkg_meta_transcript) > 0, + error::already_exists(EDKG_META_NOT_SET) + ); + + session.target_committees_public_key_shares = target_committees_public_key_shares; + dkg_state.last_completed = option::some(session); + dkg_state.in_progress = option::none(); + + // propagate updated keys to stake.move for all threshold types + let public_key_shares_all_comms_serialized = + any::new( + type_info::type_name(), + target_committees_public_key_shares + ); + let public_key_shares_all_comms = + any::unpack( + public_key_shares_all_comms_serialized + ); + + // Build a vector of DkgCommitteeOutput for all committees + let committee_outputs = vector[]; + let i = 0; + let len = vector::length(&public_key_shares_all_comms.commitments); + while (i < len) { + let commitment = vector::borrow(&public_key_shares_all_comms.commitments, i); + // As the first index contains the committee's threshold public key, we can skip that + let evals = vector::slice( + &commitment.bls12381_commitment_evals, + 1, + vector::length(&commitment.bls12381_commitment_evals) + ); + + vector::push_back( + &mut committee_outputs, + new_dkg_committee_output(commitment.threshold_type, evals) + ); + i = i + 1; + }; + + // Set all keys for all threshold types + stake::set_dkg_output_keys(committee_outputs); + emit(DKGFinishEvent { target_committees_public_key_shares }); + } + + /// Delete the currently incomplete session, if it exists. + public fun try_clear_incomplete_session(fx: &signer) acquires DKGState { + system_addresses::assert_supra_framework(fx); + if (exists(@supra_framework)) { + let dkg_state = borrow_global_mut(@supra_framework); + dkg_state.in_progress = option::none(); + } + } + + /// Return the incomplete DKG session state, if it exists. + public fun incomplete_session(): Option acquires DKGState { + if (exists(@supra_framework)) { + borrow_global(@supra_framework).in_progress + } else { + option::none() + } + } + + /// Return the last completed DKG session state, if it exists. + public fun last_completed_session(): Option acquires DKGState { + if (exists(@supra_framework)) { + borrow_global(@supra_framework).last_completed + } else { + option::none() + } + } + + /// Return the dealer epoch of a `DKGSessionState`. + public fun session_dealer_epoch(session: &DKGSessionState): u64 { + session.metadata.dealer_epoch + } +} diff --git a/aptos-move/framework/supra-framework/sources/supra_dkg.spec.move b/aptos-move/framework/supra-framework/sources/supra_dkg.spec.move new file mode 100644 index 00000000000..71bd99ead49 --- /dev/null +++ b/aptos-move/framework/supra-framework/sources/supra_dkg.spec.move @@ -0,0 +1,54 @@ +spec supra_framework::supra_dkg { + + spec module { + use supra_framework::chain_status; + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); + } + + spec initialize(supra_framework: &signer) { + use std::signer; + let supra_framework_addr = signer::address_of(supra_framework); + aborts_if supra_framework_addr != @supra_framework; + } + + spec start( + dealer_epoch: u64, + randomness_seed: vector, + dealer_committee: DkgCommittee, + target_committees: vector + ) { + aborts_if !exists(@supra_framework); + aborts_if !exists(@supra_framework); + } + + spec set_dkg_meta(dkg_meta_all_committees: vector) { + use std::option; + requires exists(@supra_framework); + requires option::is_some(global(@supra_framework).in_progress); + aborts_if false; + } + + spec finish(target_committees_public_key_shares: vector) { + use std::option; + requires exists(@supra_framework); + requires option::is_some(global(@supra_framework).in_progress); + aborts_if false; + } + + spec fun has_incomplete_session(): bool { + if (exists(@supra_framework)) { + option::spec_is_some(global(@supra_framework).in_progress) + } else { false } + } + + spec try_clear_incomplete_session(fx: &signer) { + use std::signer; + let addr = signer::address_of(fx); + aborts_if addr != @supra_framework; + } + + spec incomplete_session(): Option { + aborts_if false; + } +} diff --git a/aptos-move/framework/supra-framework/sources/supra_governance.move b/aptos-move/framework/supra-framework/sources/supra_governance.move index 6f49a9b4378..e5128fb0b6b 100644 --- a/aptos-move/framework/supra-framework/sources/supra_governance.move +++ b/aptos-move/framework/supra-framework/sources/supra_governance.move @@ -57,13 +57,13 @@ module supra_framework::supra_governance { /// Store the SignerCapabilities of accounts under the on-chain governance's control. struct GovernanceResponsbility has key { - signer_caps: SimpleMap, + signer_caps: SimpleMap } /// Used to track which execution script hashes have been approved by governance. /// This is required to bypass cases where the execution scripts exceed the size limit imposed by mempool. struct ApprovedExecutionHashes has key { - hashes: SimpleMap>, + hashes: SimpleMap> } /// Configurations of the SupraGovernance, set during Genesis and can be updated by the same process offered @@ -71,14 +71,14 @@ module supra_framework::supra_governance { struct SupraGovernanceConfig has key { voting_duration_secs: u64, min_voting_threshold: u64, - voters: vector
, + voters: vector
} /// Events generated by interactions with the SupraGovernance module. struct SupraGovernanceEvents has key { create_proposal_events: EventHandle, update_config_events: EventHandle, - vote_events: EventHandle, + vote_events: EventHandle } /// Event emitted when a proposal is created. @@ -86,21 +86,21 @@ module supra_framework::supra_governance { proposer: address, proposal_id: u64, execution_hash: vector, - proposal_metadata: SimpleMap>, + proposal_metadata: SimpleMap> } /// Event emitted when the governance configs are updated. struct SupraUpdateConfigEvent has drop, store { voting_duration_secs: u64, min_voting_threshold: u64, - voters: vector
, + voters: vector
} /// Event emitted when there's a vote on a proposa; struct SupraVoteEvent has drop, store { proposal_id: u64, voter: address, - should_pass: bool, + should_pass: bool } #[event] @@ -109,7 +109,7 @@ module supra_framework::supra_governance { proposer: address, proposal_id: u64, execution_hash: vector, - proposal_metadata: SimpleMap>, + proposal_metadata: SimpleMap> } #[event] @@ -117,7 +117,7 @@ module supra_framework::supra_governance { struct SupraVote has drop, store { proposal_id: u64, voter: address, - should_pass: bool, + should_pass: bool } #[event] @@ -125,15 +125,13 @@ module supra_framework::supra_governance { struct SupraUpdateConfig has drop, store { voting_duration_secs: u64, min_voting_threshold: u64, - voters: vector
, + voters: vector
} /// Can be called during genesis or by the governance itself. /// Stores the signer capability for a given address. public fun store_signer_cap( - supra_framework: &signer, - signer_address: address, - signer_cap: SignerCapability, + supra_framework: &signer, signer_address: address, signer_cap: SignerCapability ) acquires GovernanceResponsbility { system_addresses::assert_supra_framework(supra_framework); system_addresses::assert_framework_reserved(signer_address); @@ -141,11 +139,14 @@ module supra_framework::supra_governance { if (!exists(@supra_framework)) { move_to( supra_framework, - GovernanceResponsbility { signer_caps: simple_map::create() } + GovernanceResponsbility { + signer_caps: simple_map::create() + } ); }; - let signer_caps = &mut borrow_global_mut(@supra_framework).signer_caps; + let signer_caps = + &mut borrow_global_mut(@supra_framework).signer_caps; simple_map::add(signer_caps, signer_address, signer_cap); } @@ -156,26 +157,42 @@ module supra_framework::supra_governance { supra_framework: &signer, voting_duration_secs: u64, min_voting_threshold: u64, - voters: vector
, + voters: vector
) { multisig_voting::register(supra_framework); - assert!(vector::length(&voters) >= min_voting_threshold && min_voting_threshold > vector::length(&voters) / 2, error::invalid_argument(ETHRESHOLD_EXCEEDS_VOTERS)); - assert!(min_voting_threshold > 1, error::invalid_argument(ETHRESHOLD_MUST_BE_GREATER_THAN_ONE)); + assert!( + vector::length(&voters) >= min_voting_threshold + && min_voting_threshold > vector::length(&voters) / 2, + error::invalid_argument(ETHRESHOLD_EXCEEDS_VOTERS) + ); + assert!( + min_voting_threshold > 1, + error::invalid_argument(ETHRESHOLD_MUST_BE_GREATER_THAN_ONE) + ); - move_to(supra_framework, SupraGovernanceConfig { - voting_duration_secs, - min_voting_threshold, - voters, - }); - move_to(supra_framework, SupraGovernanceEvents { - create_proposal_events: account::new_event_handle(supra_framework), - update_config_events: account::new_event_handle(supra_framework), - vote_events: account::new_event_handle(supra_framework), - }); - move_to(supra_framework, ApprovedExecutionHashes { - hashes: simple_map::create>(), - }) + move_to( + supra_framework, + SupraGovernanceConfig { voting_duration_secs, min_voting_threshold, voters } + ); + move_to( + supra_framework, + SupraGovernanceEvents { + create_proposal_events: account::new_event_handle( + supra_framework + ), + update_config_events: account::new_event_handle( + supra_framework + ), + vote_events: account::new_event_handle(supra_framework) + } + ); + move_to( + supra_framework, + ApprovedExecutionHashes { + hashes: simple_map::create>() + } + ) } /// Update the governance configurations. This can only be called as part of resolving a proposal in this same @@ -184,35 +201,35 @@ module supra_framework::supra_governance { supra_framework: &signer, voting_duration_secs: u64, min_voting_threshold: u64, - voters: vector
, + voters: vector
) acquires SupraGovernanceConfig, SupraGovernanceEvents { system_addresses::assert_supra_framework(supra_framework); - assert!(vector::length(&voters) >= min_voting_threshold && min_voting_threshold > vector::length(&voters) / 2, error::invalid_argument(ETHRESHOLD_EXCEEDS_VOTERS)); - assert!(min_voting_threshold > 1, error::invalid_argument(ETHRESHOLD_MUST_BE_GREATER_THAN_ONE)); + assert!( + vector::length(&voters) >= min_voting_threshold + && min_voting_threshold > vector::length(&voters) / 2, + error::invalid_argument(ETHRESHOLD_EXCEEDS_VOTERS) + ); + assert!( + min_voting_threshold > 1, + error::invalid_argument(ETHRESHOLD_MUST_BE_GREATER_THAN_ONE) + ); - let supra_governance_config = borrow_global_mut(@supra_framework); + let supra_governance_config = + borrow_global_mut(@supra_framework); supra_governance_config.voting_duration_secs = voting_duration_secs; supra_governance_config.min_voting_threshold = min_voting_threshold; supra_governance_config.voters = voters; if (std::features::module_event_migration_enabled()) { event::emit( - SupraUpdateConfig { - min_voting_threshold, - voting_duration_secs, - voters, - }, + SupraUpdateConfig { min_voting_threshold, voting_duration_secs, voters } ) }; let events = borrow_global_mut(@supra_framework); event::emit_event( &mut events.update_config_events, - SupraUpdateConfigEvent { - min_voting_threshold, - voting_duration_secs, - voters, - }, + SupraUpdateConfigEvent { min_voting_threshold, voting_duration_secs, voters } ); } @@ -238,9 +255,15 @@ module supra_framework::supra_governance { proposer: &signer, execution_hash: vector, metadata_location: vector, - metadata_hash: vector, + metadata_hash: vector ) acquires SupraGovernanceConfig, SupraGovernanceEvents { - supra_create_proposal_v2(proposer, execution_hash, metadata_location, metadata_hash, false); + supra_create_proposal_v2( + proposer, + execution_hash, + metadata_location, + metadata_hash, + false + ); } /// Create a single-step or multi-step proposal with the backing `stake_pool`. @@ -251,7 +274,7 @@ module supra_framework::supra_governance { execution_hash: vector, metadata_location: vector, metadata_hash: vector, - is_multi_step_proposal: bool, + is_multi_step_proposal: bool ) acquires SupraGovernanceConfig, SupraGovernanceEvents { supra_create_proposal_v2_impl( proposer, @@ -271,38 +294,46 @@ module supra_framework::supra_governance { execution_hash: vector, metadata_location: vector, metadata_hash: vector, - is_multi_step_proposal: bool, + is_multi_step_proposal: bool ): u64 acquires SupraGovernanceConfig, SupraGovernanceEvents { let proposer_address = signer::address_of(proposer); - let supra_governance_config = borrow_global(@supra_framework); + let supra_governance_config = + borrow_global(@supra_framework); - assert!(vector::contains(&supra_governance_config.voters, &proposer_address), error::permission_denied(EACCOUNT_NOT_AUTHORIZED)); + assert!( + vector::contains(&supra_governance_config.voters, &proposer_address), + error::permission_denied(EACCOUNT_NOT_AUTHORIZED) + ); - let proposal_expiration = timestamp::now_seconds() + supra_governance_config.voting_duration_secs; + let proposal_expiration = + timestamp::now_seconds() + supra_governance_config.voting_duration_secs; // Create and validate proposal metadata. - let proposal_metadata = create_proposal_metadata(metadata_location, metadata_hash); - - let proposal_id = multisig_voting::create_proposal_v2( - proposer_address, - @supra_framework, - governance_proposal::create_proposal(), - execution_hash, - supra_governance_config.min_voting_threshold, - supra_governance_config.voters, - proposal_expiration, - proposal_metadata, - is_multi_step_proposal, + let proposal_metadata = create_proposal_metadata( + metadata_location, metadata_hash ); + let proposal_id = + multisig_voting::create_proposal_v2( + proposer_address, + @supra_framework, + governance_proposal::create_proposal(), + execution_hash, + supra_governance_config.min_voting_threshold, + supra_governance_config.voters, + proposal_expiration, + proposal_metadata, + is_multi_step_proposal + ); + if (std::features::module_event_migration_enabled()) { event::emit( SupraCreateProposal { proposal_id, proposer: proposer_address, execution_hash, - proposal_metadata, - }, + proposal_metadata + } ); }; let events = borrow_global_mut(@supra_framework); @@ -312,17 +343,15 @@ module supra_framework::supra_governance { proposal_id, proposer: proposer_address, execution_hash, - proposal_metadata, - }, + proposal_metadata + } ); proposal_id } /// Vote on proposal with `proposal_id` and all voting power from `stake_pool`. public entry fun supra_vote( - voter: &signer, - proposal_id: u64, - should_pass: bool, + voter: &signer, proposal_id: u64, should_pass: bool ) acquires ApprovedExecutionHashes, SupraGovernanceEvents, SupraGovernanceConfig { supra_vote_internal(voter, proposal_id, should_pass); } @@ -332,56 +361,58 @@ module supra_framework::supra_governance { /// If a stake pool has already voted on a proposal before partial governance voting is enabled, the stake pool /// cannot vote on the proposal even after partial governance voting is enabled. fun supra_vote_internal( - voter: &signer, - proposal_id: u64, - should_pass: bool, + voter: &signer, proposal_id: u64, should_pass: bool ) acquires ApprovedExecutionHashes, SupraGovernanceEvents, SupraGovernanceConfig { let voter_address = signer::address_of(voter); - let supra_governance_config = borrow_global(@supra_framework); - assert!(vector::contains(&supra_governance_config.voters, &signer::address_of(voter)), error::permission_denied(EACCOUNT_NOT_AUTHORIZED)); + let supra_governance_config = + borrow_global(@supra_framework); + assert!( + vector::contains( + &supra_governance_config.voters, &signer::address_of(voter) + ), + error::permission_denied(EACCOUNT_NOT_AUTHORIZED) + ); // The voter's stake needs to be locked up at least as long as the proposal's expiration. - let proposal_expiration = multisig_voting::get_proposal_expiration_secs( - @supra_framework, - proposal_id + let proposal_expiration = + multisig_voting::get_proposal_expiration_secs( + @supra_framework, proposal_id + ); + assert!( + timestamp::now_seconds() <= proposal_expiration, + error::invalid_argument(EPROPOSAL_IS_EXPIRE) ); - assert!(timestamp::now_seconds() <= proposal_expiration, error::invalid_argument(EPROPOSAL_IS_EXPIRE)); multisig_voting::vote( voter, &governance_proposal::create_empty_proposal(), @supra_framework, proposal_id, - should_pass, + should_pass ); if (std::features::module_event_migration_enabled()) { - event::emit( - SupraVote { - proposal_id, - voter: voter_address, - should_pass, - }, - ); + event::emit(SupraVote { proposal_id, voter: voter_address, should_pass }); }; let events = borrow_global_mut(@supra_framework); event::emit_event( &mut events.vote_events, - SupraVoteEvent { - proposal_id, - voter: voter_address, - should_pass, - }, + SupraVoteEvent { proposal_id, voter: voter_address, should_pass } ); - let proposal_state = multisig_voting::get_proposal_state(@supra_framework, proposal_id); + let proposal_state = + multisig_voting::get_proposal_state( + @supra_framework, proposal_id + ); if (proposal_state == PROPOSAL_STATE_SUCCEEDED) { add_supra_approved_script_hash(proposal_id); } } - public entry fun add_supra_approved_script_hash_script(proposal_id: u64) acquires ApprovedExecutionHashes { + public entry fun add_supra_approved_script_hash_script( + proposal_id: u64 + ) acquires ApprovedExecutionHashes { add_supra_approved_script_hash(proposal_id) } @@ -389,18 +420,29 @@ module supra_framework::supra_governance { /// This is needed to bypass the mempool transaction size limit for approved governance proposal transactions that /// are too large (e.g. module upgrades). public fun add_supra_approved_script_hash(proposal_id: u64) acquires ApprovedExecutionHashes { - let approved_hashes = borrow_global_mut(@supra_framework); + let approved_hashes = + borrow_global_mut(@supra_framework); // Ensure the proposal can be resolved. - let proposal_state = multisig_voting::get_proposal_state(@supra_framework, proposal_id); - assert!(proposal_state == PROPOSAL_STATE_SUCCEEDED, error::invalid_argument(EPROPOSAL_NOT_RESOLVABLE_YET)); + let proposal_state = + multisig_voting::get_proposal_state( + @supra_framework, proposal_id + ); + assert!( + proposal_state == PROPOSAL_STATE_SUCCEEDED, + error::invalid_argument(EPROPOSAL_NOT_RESOLVABLE_YET) + ); - let execution_hash = multisig_voting::get_execution_hash(@supra_framework, proposal_id); + let execution_hash = + multisig_voting::get_execution_hash( + @supra_framework, proposal_id + ); // If this is a multi-step proposal, the proposal id will already exist in the ApprovedExecutionHashes map. // We will update execution hash in ApprovedExecutionHashes to be the next_execution_hash. if (simple_map::contains_key(&approved_hashes.hashes, &proposal_id)) { - let current_execution_hash = simple_map::borrow_mut(&mut approved_hashes.hashes, &proposal_id); + let current_execution_hash = + simple_map::borrow_mut(&mut approved_hashes.hashes, &proposal_id); *current_execution_hash = execution_hash; } else { simple_map::add(&mut approved_hashes.hashes, proposal_id, execution_hash); @@ -410,8 +452,7 @@ module supra_framework::supra_governance { /// Resolve a successful single-step proposal. This would fail if the proposal is not successful (not enough votes or more no /// than yes). public fun supra_resolve( - proposal_id: u64, - signer_address: address + proposal_id: u64, signer_address: address ): signer acquires ApprovedExecutionHashes, GovernanceResponsbility { multisig_voting::resolve(@supra_framework, proposal_id); remove_supra_approved_hash(proposal_id); @@ -420,11 +461,11 @@ module supra_framework::supra_governance { /// Resolve a successful multi-step proposal. This would fail if the proposal is not successful. public fun resolve_supra_multi_step_proposal( - proposal_id: u64, - signer_address: address, - next_execution_hash: vector + proposal_id: u64, signer_address: address, next_execution_hash: vector ): signer acquires GovernanceResponsbility, ApprovedExecutionHashes { - multisig_voting::resolve_proposal_v2(@supra_framework, proposal_id, next_execution_hash); + multisig_voting::resolve_proposal_v2( + @supra_framework, proposal_id, next_execution_hash + ); // If the current step is the last step of this multi-step proposal, // we will remove the execution hash from the ApprovedExecutionHashes map. if (vector::length(&next_execution_hash) == 0) { @@ -441,11 +482,14 @@ module supra_framework::supra_governance { /// Remove an approved proposal's execution script hash. public fun remove_supra_approved_hash(proposal_id: u64) acquires ApprovedExecutionHashes { assert!( - multisig_voting::is_resolved(@supra_framework, proposal_id), - error::invalid_argument(EPROPOSAL_NOT_RESOLVED_YET), + multisig_voting::is_resolved( + @supra_framework, proposal_id + ), + error::invalid_argument(EPROPOSAL_NOT_RESOLVED_YET) ); - let approved_hashes = &mut borrow_global_mut(@supra_framework).hashes; + let approved_hashes = + &mut borrow_global_mut(@supra_framework).hashes; if (simple_map::contains_key(approved_hashes, &proposal_id)) { simple_map::remove(approved_hashes, &proposal_id); }; @@ -454,15 +498,19 @@ module supra_framework::supra_governance { /// Manually reconfigure. Called at the end of a governance txn that alters on-chain configs. /// /// WARNING: this function always ensures a reconfiguration starts, but when the reconfiguration finishes depends. - /// - If feature `RECONFIGURE_WITH_DKG` is disabled, it finishes immediately. + /// - If feature `SUPRA_DKG` is disabled, it finishes immediately. /// - At the end of the calling transaction, we will be in a new epoch. - /// - If feature `RECONFIGURE_WITH_DKG` is enabled, it starts DKG, and the new epoch will start in a block prologue after DKG finishes. + /// - If feature `SUPRA_DKG` is enabled, it starts DKG, and the new epoch will start in a block prologue after DKG finishes. /// /// This behavior affects when an update of an on-chain config (e.g. `ConsensusConfig`, `Features`) takes effect, - /// since such updates are applied whenever we enter an new epoch. + /// since such updates are applied whenever we enter a new epoch. public entry fun reconfigure(supra_framework: &signer) { system_addresses::assert_supra_framework(supra_framework); - if (consensus_config::validator_txn_enabled() && randomness_config::enabled()) { + + // The block executor should seed the randomness config with the digest of the last + // block of the first epoch in which the DKG is enabled, so the second conjunct should + // always be true once the first is true. We keep it for safety in case of regression. + if (features::supra_dkg_enabled() && randomness_config::enabled()) { reconfiguration_with_dkg::try_start(); } else { reconfiguration_with_dkg::finish(supra_framework); @@ -470,7 +518,7 @@ module supra_framework::supra_governance { } /// Change epoch immediately. - /// If `RECONFIGURE_WITH_DKG` is enabled and we are in the middle of a DKG, + /// If `SUPRA_DKG` is enabled and we are in the middle of a DKG, /// stop waiting for DKG and enter the new epoch without randomness. /// /// WARNING: currently only used by tests. In most cases you should use `reconfigure()` instead. @@ -482,14 +530,18 @@ module supra_framework::supra_governance { /// `force_end_epoch()` equivalent but only called in testnet, /// where the core resources account exists and has been granted power to mint Supra coins. - public entry fun force_end_epoch_test_only(supra_framework: &signer) acquires GovernanceResponsbility { + public entry fun force_end_epoch_test_only( + supra_framework: &signer + ) acquires GovernanceResponsbility { let core_signer = get_signer_testnet_only(supra_framework, @0x1); system_addresses::assert_supra_framework(&core_signer); reconfiguration_with_dkg::finish(&core_signer); } /// Update feature flags and also trigger reconfiguration. - public fun toggle_features(supra_framework: &signer, enable: vector, disable: vector) { + public fun toggle_features( + supra_framework: &signer, enable: vector, disable: vector + ) { system_addresses::assert_supra_framework(supra_framework); features::change_feature_flags_for_next_epoch(supra_framework, enable, disable); reconfigure(supra_framework); @@ -497,26 +549,37 @@ module supra_framework::supra_governance { /// Only called in testnet where the core resources account exists and has been granted power to mint Supra coins. public fun get_signer_testnet_only( - core_resources: &signer, signer_address: address): signer acquires GovernanceResponsbility { + core_resources: &signer, signer_address: address + ): signer acquires GovernanceResponsbility { system_addresses::assert_core_resource(core_resources); // Core resources account only has mint capability in tests/testnets. - assert!(supra_coin::has_mint_capability(core_resources), error::unauthenticated(EUNAUTHORIZED)); + assert!( + supra_coin::has_mint_capability(core_resources), + error::unauthenticated(EUNAUTHORIZED) + ); get_signer(signer_address) } /// Return a signer for making changes to 0x1 as part of on-chain governance proposal process. fun get_signer(signer_address: address): signer acquires GovernanceResponsbility { - let governance_responsibility = borrow_global(@supra_framework); - let signer_cap = simple_map::borrow(&governance_responsibility.signer_caps, &signer_address); + let governance_responsibility = + borrow_global(@supra_framework); + let signer_cap = + simple_map::borrow(&governance_responsibility.signer_caps, &signer_address); create_signer_with_capability(signer_cap) } fun create_proposal_metadata( - metadata_location: vector, - metadata_hash: vector + metadata_location: vector, metadata_hash: vector ): SimpleMap> { - assert!(string::length(&utf8(metadata_location)) <= 256, error::invalid_argument(EMETADATA_LOCATION_TOO_LONG)); - assert!(string::length(&utf8(metadata_hash)) <= 256, error::invalid_argument(EMETADATA_HASH_TOO_LONG)); + assert!( + string::length(&utf8(metadata_location)) <= 256, + error::invalid_argument(EMETADATA_LOCATION_TOO_LONG) + ); + assert!( + string::length(&utf8(metadata_hash)) <= 256, + error::invalid_argument(EMETADATA_HASH_TOO_LONG) + ); let metadata = simple_map::create>(); simple_map::add(&mut metadata, utf8(METADATA_LOCATION_KEY), metadata_location); @@ -526,26 +589,14 @@ module supra_framework::supra_governance { #[test_only] public entry fun supra_create_proposal_for_test( - proposer: &signer, - multi_step: bool, + proposer: &signer, multi_step: bool ) acquires SupraGovernanceConfig, SupraGovernanceEvents { let execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); if (multi_step) { - supra_create_proposal_v2( - proposer, - execution_hash, - b"", - b"", - true, - ); + supra_create_proposal_v2(proposer, execution_hash, b"", b"", true); } else { - supra_create_proposal( - proposer, - execution_hash, - b"", - b"", - ); + supra_create_proposal(proposer, execution_hash, b"", b""); }; } @@ -561,9 +612,13 @@ module supra_framework::supra_governance { vector::push_back(&mut execution_hash, 1); if (finish_multi_step_execution) { - resolve_supra_multi_step_proposal(proposal_id, signer_address, vector::empty()) + resolve_supra_multi_step_proposal( + proposal_id, signer_address, vector::empty() + ) } else { - resolve_supra_multi_step_proposal(proposal_id, signer_address, execution_hash) + resolve_supra_multi_step_proposal( + proposal_id, signer_address, execution_hash + ) } } else { supra_resolve(proposal_id, signer_address) @@ -572,7 +627,9 @@ module supra_framework::supra_governance { #[test_only] /// Force reconfigure. To be called at the end of a proposal that alters on-chain configs. - public fun toggle_features_for_test(enable: vector, disable: vector) { + public fun toggle_features_for_test( + enable: vector, disable: vector + ) { toggle_features(&account::create_signer_for_test(@0x1), enable, disable); } @@ -583,9 +640,13 @@ module supra_framework::supra_governance { yes_voter: &signer, no_voter: &signer, multi_step: bool, - use_generic_resolve_function: bool, + use_generic_resolve_function: bool ) acquires ApprovedExecutionHashes, SupraGovernanceConfig, GovernanceResponsbility, SupraGovernanceEvents { - let voters = vector[signer::address_of(proposer), signer::address_of(yes_voter), signer::address_of(no_voter)]; + let voters = vector[ + signer::address_of(proposer), + signer::address_of(yes_voter), + signer::address_of(no_voter) + ]; supra_setup_voting(supra_framework, voters); let execution_hash = vector::empty(); @@ -597,73 +658,144 @@ module supra_framework::supra_governance { supra_vote(yes_voter, 0, true); supra_vote(no_voter, 0, false); - supra_test_resolving_proposal_generic(supra_framework, use_generic_resolve_function, execution_hash); + supra_test_resolving_proposal_generic( + supra_framework, use_generic_resolve_function, execution_hash + ); } #[test_only] public entry fun supra_test_resolving_proposal_generic( supra_framework: &signer, use_generic_resolve_function: bool, - execution_hash: vector, + execution_hash: vector ) acquires ApprovedExecutionHashes, GovernanceResponsbility { // Once expiration time has passed, the proposal should be considered resolve now as there are more yes votes // than no. timestamp::update_global_time_for_test(100001000000); - let proposal_state = multisig_voting::get_proposal_state(signer::address_of(supra_framework), 0); + let proposal_state = + multisig_voting::get_proposal_state( + signer::address_of(supra_framework), 0 + ); assert!(proposal_state == PROPOSAL_STATE_SUCCEEDED, proposal_state); // Add approved script hash. add_supra_approved_script_hash(0); - let approved_hashes = borrow_global(@supra_framework).hashes; + let approved_hashes = + borrow_global(@supra_framework).hashes; assert!(*simple_map::borrow(&approved_hashes, &0) == execution_hash, 0); // Resolve the proposal. - let account = supra_resolve_proposal_for_test(0, @supra_framework, use_generic_resolve_function, true); + let account = + supra_resolve_proposal_for_test( + 0, + @supra_framework, + use_generic_resolve_function, + true + ); assert!(signer::address_of(&account) == @supra_framework, 1); - assert!(multisig_voting::is_resolved(@supra_framework, 0), 2); - let approved_hashes = borrow_global(@supra_framework).hashes; + assert!( + multisig_voting::is_resolved(@supra_framework, 0), 2 + ); + let approved_hashes = + borrow_global(@supra_framework).hashes; assert!(!simple_map::contains_key(&approved_hashes, &0), 3); } - #[test(supra_framework = @supra_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + yes_voter = @0x234, + no_voter = @345 + ) + ] public entry fun test_voting( supra_framework: &signer, proposer: &signer, yes_voter: &signer, - no_voter: &signer, + no_voter: &signer ) acquires ApprovedExecutionHashes, SupraGovernanceConfig, GovernanceResponsbility, SupraGovernanceEvents { - test_voting_generic(supra_framework, proposer, yes_voter, no_voter, false, false); + test_voting_generic( + supra_framework, + proposer, + yes_voter, + no_voter, + false, + false + ); } - #[test(supra_framework = @supra_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + yes_voter = @0x234, + no_voter = @345 + ) + ] public entry fun test_voting_multi_step( supra_framework: &signer, proposer: &signer, yes_voter: &signer, - no_voter: &signer, + no_voter: &signer ) acquires ApprovedExecutionHashes, SupraGovernanceConfig, GovernanceResponsbility, SupraGovernanceEvents { - test_voting_generic(supra_framework, proposer, yes_voter, no_voter, true, true); + test_voting_generic( + supra_framework, + proposer, + yes_voter, + no_voter, + true, + true + ); } - #[test(supra_framework = @supra_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + yes_voter = @0x234, + no_voter = @345 + ) + ] #[expected_failure(abort_code = 0x5000a, location = supra_framework::multisig_voting)] public entry fun test_voting_multi_step_cannot_use_single_step_resolve( supra_framework: &signer, proposer: &signer, yes_voter: &signer, - no_voter: &signer, + no_voter: &signer ) acquires ApprovedExecutionHashes, SupraGovernanceConfig, GovernanceResponsbility, SupraGovernanceEvents { - test_voting_generic(supra_framework, proposer, yes_voter, no_voter, true, false); + test_voting_generic( + supra_framework, + proposer, + yes_voter, + no_voter, + true, + false + ); } - #[test(supra_framework = @supra_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + yes_voter = @0x234, + no_voter = @345 + ) + ] public entry fun test_voting_single_step_can_use_generic_resolve_function( supra_framework: &signer, proposer: &signer, yes_voter: &signer, - no_voter: &signer, + no_voter: &signer ) acquires ApprovedExecutionHashes, SupraGovernanceConfig, GovernanceResponsbility, SupraGovernanceEvents { - test_voting_generic(supra_framework, proposer, yes_voter, no_voter, false, true); + test_voting_generic( + supra_framework, + proposer, + yes_voter, + no_voter, + false, + true + ); } #[test_only] @@ -672,9 +804,13 @@ module supra_framework::supra_governance { proposer: &signer, yes_voter: &signer, no_voter: &signer, - multi_step: bool, + multi_step: bool ) acquires ApprovedExecutionHashes, GovernanceResponsbility, SupraGovernanceEvents, SupraGovernanceConfig { - let voters = vector[signer::address_of(proposer), signer::address_of(yes_voter), signer::address_of(no_voter)]; + let voters = vector[ + signer::address_of(proposer), + signer::address_of(yes_voter), + signer::address_of(no_voter) + ]; supra_setup_voting(supra_framework, voters); supra_create_proposal_for_test(proposer, multi_step); @@ -691,8 +827,13 @@ module supra_framework::supra_governance { let execution_hash = vector::empty(); let next_execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); - multisig_voting::resolve_proposal_v2(@supra_framework, 0, next_execution_hash); - assert!(multisig_voting::is_resolved(@supra_framework, 0), 0); + multisig_voting::resolve_proposal_v2( + @supra_framework, 0, next_execution_hash + ); + assert!( + multisig_voting::is_resolved(@supra_framework, 0), + 0 + ); if (vector::length(&next_execution_hash) == 0) { remove_supra_approved_hash(0); } else { @@ -700,19 +841,30 @@ module supra_framework::supra_governance { }; } else { multisig_voting::resolve(@supra_framework, 0); - assert!(multisig_voting::is_resolved(@supra_framework, 0), 0); + assert!( + multisig_voting::is_resolved(@supra_framework, 0), + 0 + ); remove_supra_approved_hash(0); }; - let approved_hashes = borrow_global(@supra_framework).hashes; + let approved_hashes = + borrow_global(@supra_framework).hashes; assert!(!simple_map::contains_key(&approved_hashes, &0), 1); } - #[test(supra_framework = @supra_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + yes_voter = @0x234, + no_voter = @345 + ) + ] public entry fun test_can_remove_approved_hash_if_executed_directly_via_voting( supra_framework: &signer, proposer: &signer, yes_voter: &signer, - no_voter: &signer, + no_voter: &signer ) acquires ApprovedExecutionHashes, GovernanceResponsbility, SupraGovernanceEvents, SupraGovernanceConfig { test_can_remove_approved_hash_if_executed_directly_via_voting_generic( supra_framework, @@ -723,12 +875,19 @@ module supra_framework::supra_governance { ); } - #[test(supra_framework = @supra_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + yes_voter = @0x234, + no_voter = @345 + ) + ] public entry fun test_can_remove_approved_hash_if_executed_directly_via_voting_multi_step( supra_framework: &signer, proposer: &signer, yes_voter: &signer, - no_voter: &signer, + no_voter: &signer ) acquires ApprovedExecutionHashes, GovernanceResponsbility, SupraGovernanceEvents, SupraGovernanceConfig { test_can_remove_approved_hash_if_executed_directly_via_voting_generic( supra_framework, @@ -739,23 +898,29 @@ module supra_framework::supra_governance { ); } - #[test(supra_framework = @supra_framework, proposer = @0x123, voter_1 = @0x234, voter_2 = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + voter_1 = @0x234, + voter_2 = @345 + ) + ] #[expected_failure(abort_code = 0x8000d, location = supra_framework::multisig_voting)] public entry fun test_cannot_double_vote( supra_framework: &signer, proposer: &signer, voter_1: &signer, - voter_2: &signer, + voter_2: &signer ) acquires ApprovedExecutionHashes, GovernanceResponsbility, SupraGovernanceConfig, SupraGovernanceEvents { - let voters = vector[signer::address_of(proposer), signer::address_of(voter_1), signer::address_of(voter_2)]; + let voters = vector[ + signer::address_of(proposer), + signer::address_of(voter_1), + signer::address_of(voter_2) + ]; supra_setup_voting(supra_framework, voters); - supra_create_proposal( - proposer, - b"random-test", - b"", - b"", - ); + supra_create_proposal(proposer, b"random-test", b"", b""); // Double voting should throw an error. supra_vote(voter_1, 0, true); @@ -764,8 +929,7 @@ module supra_framework::supra_governance { #[test_only] public fun supra_setup_voting( - supra_framework: &signer, - voters: vector
, + supra_framework: &signer, voters: vector
) acquires GovernanceResponsbility { use supra_framework::account; @@ -777,13 +941,13 @@ module supra_framework::supra_governance { store_signer_cap( supra_framework, @supra_framework, - account::create_test_signer_cap(@supra_framework), + account::create_test_signer_cap(@supra_framework) ); } #[test(supra_framework = @supra_framework)] public entry fun test_update_governance_config( - supra_framework: signer, + supra_framework: signer ) acquires SupraGovernanceEvents, SupraGovernanceConfig { account::create_account_for_test(signer::address_of(&supra_framework)); let voters = vector[@0xa1, @0xa2, @0xa3]; @@ -799,8 +963,9 @@ module supra_framework::supra_governance { #[test(account = @0x123)] #[expected_failure(abort_code = 0x50003, location = supra_framework::system_addresses)] - public entry fun test_update_governance_config_unauthorized_should_fail(account: signer) - acquires SupraGovernanceConfig, SupraGovernanceEvents { + public entry fun test_update_governance_config_unauthorized_should_fail( + account: signer + ) acquires SupraGovernanceConfig, SupraGovernanceEvents { account::create_account_for_test(signer::address_of(&account)); let voters = vector[@0xa1, @0xa2, @0xa3]; @@ -808,14 +973,25 @@ module supra_framework::supra_governance { update_supra_governance_config(&account, 1500, 2, voters); } - #[test(supra_framework = @supra_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + yes_voter = @0x234, + no_voter = @345 + ) + ] public entry fun test_replace_execution_hash( supra_framework: &signer, proposer: &signer, yes_voter: &signer, - no_voter: &signer, + no_voter: &signer ) acquires GovernanceResponsbility, ApprovedExecutionHashes, SupraGovernanceConfig, SupraGovernanceEvents { - let voters = vector[signer::address_of(proposer), signer::address_of(yes_voter), signer::address_of(no_voter)]; + let voters = vector[ + signer::address_of(proposer), + signer::address_of(yes_voter), + signer::address_of(no_voter) + ]; supra_setup_voting(supra_framework, voters); supra_create_proposal_for_test(proposer, true); @@ -833,7 +1009,9 @@ module supra_framework::supra_governance { vector::push_back(&mut execution_hash, 1); vector::push_back(&mut next_execution_hash, 10); - multisig_voting::resolve_proposal_v2(@supra_framework, 0, next_execution_hash); + multisig_voting::resolve_proposal_v2( + @supra_framework, 0, next_execution_hash + ); if (vector::length(&next_execution_hash) == 0) { remove_supra_approved_hash(0); @@ -841,8 +1019,12 @@ module supra_framework::supra_governance { add_supra_approved_script_hash(0) }; - let approved_hashes = borrow_global(@supra_framework).hashes; - assert!(*simple_map::borrow(&approved_hashes, &0) == vector[10u8, ], 1); + let approved_hashes = + borrow_global(@supra_framework).hashes; + assert!( + *simple_map::borrow(&approved_hashes, &0) == vector[10u8], + 1 + ); } #[verify_only] @@ -850,8 +1032,13 @@ module supra_framework::supra_governance { supra_framework: &signer, voting_duration_secs: u64, supra_min_voting_threshold: u64, - voters: vector
, + voters: vector
) { - initialize(supra_framework, voting_duration_secs, supra_min_voting_threshold, voters); + initialize( + supra_framework, + voting_duration_secs, + supra_min_voting_threshold, + voters + ); } } diff --git a/aptos-move/framework/supra-framework/sources/transaction_context.move b/aptos-move/framework/supra-framework/sources/transaction_context.move index bc67915eb21..1c22f8feac6 100644 --- a/aptos-move/framework/supra-framework/sources/transaction_context.move +++ b/aptos-move/framework/supra-framework/sources/transaction_context.move @@ -170,6 +170,15 @@ module supra_framework::transaction_context { } native fun multisig_payload_internal(): Option; + /// Returns the Keccak-256 hash of the current signed transaction (the `transaction consensus hash`). + /// This is distinct from `get_transaction_hash()`, which returns the session UUID hash. + /// Aborts if called outside a user transaction context. + public fun get_transaction_consensus_hash(): vector { + assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + get_transaction_consensus_hash_internal() + } + native fun get_transaction_consensus_hash_internal(): vector; + /// Returns the multisig account address of the multisig payload. public fun multisig_address(payload: &MultisigPayload): address { assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); @@ -276,4 +285,14 @@ module supra_framework::transaction_context { // expected to fail with the error code of `invalid_state(E_TRANSACTION_CONTEXT_NOT_AVAILABLE)` let _multisig = multisig_payload(); } + + /// SUPRA_AUTOMATION_V2_1 is not in the default feature set, so calling `get_transaction_consensus_hash()` + /// aborts at the Move-level assert with error::invalid_state(ETRANSACTION_CONTEXT_NOT_AVAILABLE). + /// Even if the feature were enabled in a test environment, the native would also abort with + /// the same code because there is no real user transaction context in a unit test. + #[test] + #[expected_failure(abort_code=196609, location = Self)] + fun test_call_get_transaction_consensus_hash() { + let _hash = get_transaction_consensus_hash(); + } } diff --git a/aptos-move/framework/supra-framework/sources/transaction_validation.move b/aptos-move/framework/supra-framework/sources/transaction_validation.move index 9cf97230cbd..25bd7e0d8a6 100644 --- a/aptos-move/framework/supra-framework/sources/transaction_validation.move +++ b/aptos-move/framework/supra-framework/sources/transaction_validation.move @@ -373,8 +373,6 @@ module supra_framework::transaction_validation { timestamp::now_seconds() < txn_expiration_time, error::invalid_argument(PROLOGUE_ETRANSACTION_EXPIRED), ); - // TODO check whether is makes sense to do authenthicator key check as it was done in scope of common - // prologue. It might not be necessary as automated transactions are system created. // Task is not gas-less/GST, // gas-less automated transactions are not charged so no need to check eligability to pay the gas-fee. @@ -392,9 +390,10 @@ module supra_framework::transaction_validation { error::invalid_argument(PROLOGUE_ECANT_PAY_GAS_DEPOSIT) ); }; - assert!(automation_registry::has_sender_active_task_with_id(signer::address_of(&sender), task_index), - error::invalid_state(PROLOGUE_ENO_ACTIVE_AUTOMATED_TASK)) - } + }; + + assert!(automation_registry::has_sender_active_task_with_id_and_type(address_of(&sender), task_index, task_type), + error::invalid_state(PROLOGUE_ENO_ACTIVE_AUTOMATED_TASK)) } diff --git a/aptos-move/framework/supra-framework/sources/validator_public_keys.move b/aptos-move/framework/supra-framework/sources/validator_public_keys.move new file mode 100644 index 00000000000..d22e1f1a562 --- /dev/null +++ b/aptos-move/framework/supra-framework/sources/validator_public_keys.move @@ -0,0 +1,573 @@ +// Copyright (c) 2024 Supra. +module supra_framework::validator_public_keys { + use std::bcs; + use std::error; + use std::option; + use aptos_std::any; + use aptos_std::bls12381; + use aptos_std::ed25519; + use aptos_std::type_info; + use supra_std::class_groups; + use std::vector; + #[test_only] + use aptos_std::bls12381::public_key_with_pop_to_normal; + #[test_only] + use supra_framework::validator_public_keys; + + /// The integer should match the Rust enum value representation in `CertificateThresholdType`. + /// f+1, given there are f Byzantine nodes in the [Committee]. + const CERTIFICATE_THRESHOLD_TYPE_VALIDITY: u8 = 0; + /// The integer should match the Rust enum value representation in `CertificateThresholdType`. + /// 2f+1, given there are f Byzantine nodes in the [Committee] and n >= 3f + 1 nodes in total. + const CERTIFICATE_THRESHOLD_TYPE_QUORUM: u8 = 1; + /// The integer should match the Rust enum value representation in `CertificateThresholdType`. + /// n, where n is the total number of nodes in the [Committee]. + const CERTIFICATE_THRESHOLD_TYPE_UNANIMOUS: u8 = 2; + /// The integer should match the Rust enum value representation in `CertificateThresholdType`. + /// f+1, given there are f Byzantine nodes and c crash-only nodes in the [Committee] with n >= 3f + 2c + 1 nodes. + const CERTIFICATE_THRESHOLD_TYPE_BCFT_VALIDITY: u8 = 3; + /// The integer should match the Rust enum value representation in `CertificateThresholdType` + /// 2f + c + 1, given there are f Byzantine nodes and c crash-only nodes in the [Committee] with n >= 3f + 2c + 1 nodes. + const CERTIFICATE_THRESHOLD_TYPE_BCFT_QUORUM: u8 = 4; + /// The integer should match the Rust enum value representation in `CertificateThresholdType`. + /// n - f - c, given there are f Byzantine nodes and c crash-only nodes in the [Committee] with n >= 3f + 2c + 1 nodes. + const CERTIFICATE_THRESHOLD_TYPE_BCFT_FALLBACK_VIEW_CHANGE: u8 = 5; + /// The integer should match the Rust enum value representation in `CertificateThresholdType`. + /// f+1, given there are f Byzantine nodes in the [Committee] with n >= 2f + 1 nodes. + const CERTIFICATE_THRESHOLD_TYPE_CLAN_MAJORITY: u8 = 6; + + /// Error: Unknown certificate threshold type. + const EUNKNOWN_THRESHOLD_TYPE: u64 = 1; + /// Error: A consensus key blob is too short to contain an appended BLS proof-of-possession. + const EINVALID_POP_LENGTH: u64 = 2; + + /// Internal tag wrapper + struct CertificateThresholdType has copy, drop, store { + tag: u8 + } + + public fun validity_certificate_type(): CertificateThresholdType { + CertificateThresholdType { tag: CERTIFICATE_THRESHOLD_TYPE_VALIDITY } + } + + public fun quorum_certificate_type(): CertificateThresholdType { + CertificateThresholdType { tag: CERTIFICATE_THRESHOLD_TYPE_QUORUM } + } + + public fun unanimous_certificate_type(): CertificateThresholdType { + CertificateThresholdType { tag: CERTIFICATE_THRESHOLD_TYPE_UNANIMOUS } + } + + public fun bcft_validity_certificate_type(): CertificateThresholdType { + CertificateThresholdType { tag: CERTIFICATE_THRESHOLD_TYPE_BCFT_VALIDITY } + } + + public fun bcft_quorum_certificate_type(): CertificateThresholdType { + CertificateThresholdType { tag: CERTIFICATE_THRESHOLD_TYPE_BCFT_QUORUM } + } + + public fun bcft_fallback_view_change_certificate_type(): CertificateThresholdType { + CertificateThresholdType { + tag: CERTIFICATE_THRESHOLD_TYPE_BCFT_FALLBACK_VIEW_CHANGE + } + } + + public fun clan_majority_certificate_type(): CertificateThresholdType { + CertificateThresholdType { tag: CERTIFICATE_THRESHOLD_TYPE_CLAN_MAJORITY } + } + + public fun is_validity_certificate_type(t: &CertificateThresholdType): bool { + t.tag == CERTIFICATE_THRESHOLD_TYPE_VALIDITY + } + + public fun is_quorum_certificate_type(t: &CertificateThresholdType): bool { + t.tag == CERTIFICATE_THRESHOLD_TYPE_QUORUM + } + + public fun is_unanimous_certificate_type( + t: &CertificateThresholdType + ): bool { + t.tag == CERTIFICATE_THRESHOLD_TYPE_UNANIMOUS + } + + public fun is_bcft_validity_certificate_type( + t: &CertificateThresholdType + ): bool { + t.tag == CERTIFICATE_THRESHOLD_TYPE_BCFT_VALIDITY + } + + public fun is_bcft_quorum_certificate_type( + t: &CertificateThresholdType + ): bool { + t.tag == CERTIFICATE_THRESHOLD_TYPE_BCFT_QUORUM + } + + public fun is_bcft_fallback_view_change_certificate_type( + t: &CertificateThresholdType + ): bool { + t.tag == CERTIFICATE_THRESHOLD_TYPE_BCFT_FALLBACK_VIEW_CHANGE + } + + public fun is_clan_majority_certificate_type( + t: &CertificateThresholdType + ): bool { + t.tag == CERTIFICATE_THRESHOLD_TYPE_CLAN_MAJORITY + } + + /// The size of a serialized ed25519 public key, in bytes. + const ED25519_PUBLIC_KEY_NUM_BYTES: u64 = 32; + /// The size of a serialized bls12381 G1 public key, in bytes. + const BLS12381_G1_PUBLIC_KEY_NUM_BYTES: u64 = 48; + /// The size of a serialized bls12381 proof-of-possession (a G2 signature), in bytes. + const BLS12381_POP_NUM_BYTES: u64 = 96; + + /// InternalPublicKeys consists of: + /// 1. bls multisig key + /// 2. bls threshold key shares for various certificate types + /// 3. classgroup key + /// 4. ed25519 key + struct InternalPublicKeys has copy, drop, store { + bls_multisig_key: bls12381::PublicKey, + bls_threshold_validity_certificate_key: option::Option, + bls_threshold_quorum_certificate_key: option::Option, + bls_threshold_unanimous_certificate_key: option::Option, + bls_threshold_bcft_validity_certificate_key: option::Option, + bls_threshold_bcft_quorum_certificate_key: option::Option, + bls_threshold_bcft_fallback_view_change_certificate_key: option::Option, + bls_threshold_clan_majority_certificate_key: option::Option, + class_group_key: class_groups::CGPublicKey, + ed25519_key: ed25519::ValidatedPublicKey + } + + /// ValidatorPublicKeys consists of: + /// 1. network key + /// 2. supra's internal keys + struct ValidatorPublicKeys has copy, drop, store { + network_key: ed25519::ValidatedPublicKey, + supra_keys: InternalPublicKeys + } + + #[test_only] + /// This struct holds calidator secret key that can be used during testing. + struct ValidatorSecretKeys has drop { + network_key: ed25519::SecretKey, + supra_bls_multi_sig_bls_key: bls12381::SecretKey, + supra_bls_threshold_validity_key: option::Option, + supra_bls_threshold_quorum_key: option::Option, + supra_bls_threshold_unanimous_key: option::Option, + supra_bls_threshold_bcft_validity_key: option::Option, + supra_bls_threshold_bcft_quorum_key: option::Option, + supra_bls_threshold_bcft_fallback_view_change_key: option::Option, + supra_bls_threshold_clan_majority_key: option::Option, + cg_key: class_groups::SecretKey, + supra_ed_key: ed25519::SecretKey + } + + public fun validator_public_keys_from_bytes(bytes: vector): ValidatorPublicKeys { + // bcs deserialization + let bytes_serialized = + any::new(type_info::type_name(), bytes); + let validator_public_keys = any::unpack(bytes_serialized); + validator_public_keys + } + + public fun public_key_to_bytes(pk: ValidatorPublicKeys): vector { + // bcs deserialization + bcs::to_bytes(&pk) + } + + public fun get_network_key(pk: &ValidatorPublicKeys): ed25519::ValidatedPublicKey { + pk.network_key + } + + public fun get_supra_bls_multi_sig_pub_key(pk: &ValidatorPublicKeys): bls12381::PublicKey { + pk.supra_keys.bls_multisig_key + } + + public fun get_supra_cg_key(pk: &ValidatorPublicKeys): class_groups::CGPublicKey { + pk.supra_keys.class_group_key + } + + public fun get_supra_ed_key(pk: &ValidatorPublicKeys): ed25519::ValidatedPublicKey { + pk.supra_keys.ed25519_key + } + + /// Overwrites the four static keys of `target` (network_key, bls_multisig_key, class_group_key, + /// ed25519_key) with those from `source`, leaving the DKG-managed BLS threshold key fields of + /// `target` untouched. Used by `stake::rotate_consensus_key` so that an operator key rotation + /// only changes the static keys and cannot clobber the threshold keys written by the DKG via + /// `stake::set_dkg_output_keys`. + public fun replace_static_keys( + target: &mut ValidatorPublicKeys, source: &ValidatorPublicKeys + ) { + target.network_key = source.network_key; + target.supra_keys.bls_multisig_key = source.supra_keys.bls_multisig_key; + target.supra_keys.class_group_key = source.supra_keys.class_group_key; + target.supra_keys.ed25519_key = source.supra_keys.ed25519_key; + } + + /// Returns true iff the four static (non-DKG) public keys decode to cryptographically valid + /// keys: the network key, the BLS multisig key, the class-group key and the ed25519 key. + /// + /// `validator_public_keys_from_bytes` reconstructs each key's raw bytes via BCS without + /// running the per-key validation natives, so a registration blob can carry malformed keys + /// (the `Validated*`/`PublicKey` types are a misnomer after deserialization). This re-runs + /// each key's validating constructor on the recovered bytes to reject them. + /// + /// The DKG-managed BLS threshold key shares are intentionally not checked: they are absent at + /// registration and are produced/overwritten by the protocol via `stake::set_dkg_output_keys` + /// (which validates them). Proof-of-possession is not verified here either (no PoP is supplied + /// at registration); only key well-formedness / subgroup membership is checked. + public fun validate_static_keys(pk: &ValidatorPublicKeys): bool { + is_valid_ed25519_key(&pk.network_key) + && is_valid_bls12381_key(&pk.supra_keys.bls_multisig_key) + && is_valid_cg_key(&pk.supra_keys.class_group_key) + && is_valid_ed25519_key(&pk.supra_keys.ed25519_key) + } + + fun is_valid_ed25519_key(pk: &ed25519::ValidatedPublicKey): bool { + option::is_some( + &ed25519::new_validated_public_key_from_bytes( + ed25519::validated_public_key_to_bytes(pk) + ) + ) + } + + fun is_valid_bls12381_key(pk: &bls12381::PublicKey): bool { + option::is_some( + &bls12381::public_key_from_bytes(bls12381::public_key_to_bytes(pk)) + ) + } + + fun is_valid_cg_key(pk: &class_groups::CGPublicKey): bool { + option::is_some( + &class_groups::public_key_from_bytes(class_groups::public_key_to_bytes(pk)) + ) + } + + /// Splits a submitted consensus key blob into its `ValidatorPublicKeys` bytes (the prefix) and + /// the appended BLS12-381 proof-of-possession (the trailing `BLS12381_POP_NUM_BYTES` bytes). + /// Operators submit the PoP appended to the key bytes so that the contract can verify it + /// without a dedicated entry-function parameter (Move forbids changing public signatures). + public fun split_consensus_key_and_pop(blob: vector): (vector, vector) { + let len = vector::length(&blob); + assert!(len >= BLS12381_POP_NUM_BYTES, error::invalid_argument(EINVALID_POP_LENGTH)); + let pop = vector::trim(&mut blob, len - BLS12381_POP_NUM_BYTES); + (blob, pop) + } + + /// Returns true iff `pop_bytes` is a valid BLS12-381 proof-of-possession for the BLS multisig + /// key in `pk`. The multisig key is the only aggregatable (hence rogue-key-attackable) key an + /// operator submits, so it is the only one that requires a PoP; the class-group key carries its + /// own ZK PoP (verified by its `validate_pubkey_internal` native), the ed25519 keys are + /// non-aggregated, and the BLS threshold shares are produced by the DKG. + public fun verify_bls_multisig_pop( + pk: &ValidatorPublicKeys, pop_bytes: vector + ): bool { + let pk_bytes = bls12381::public_key_to_bytes(&pk.supra_keys.bls_multisig_key); + let pop = bls12381::proof_of_possession_from_bytes(pop_bytes); + option::is_some(&bls12381::public_key_from_bytes_with_pop(pk_bytes, &pop)) + } + + #[test_only] + /// Returns the BLS threshold key for the given threshold type, used by tests to assert that + /// the DKG-managed threshold keys survive an operator key rotation. + public fun get_supra_bls_threshold_key_by_type( + pk: &ValidatorPublicKeys, threshold_type: u8 + ): option::Option { + if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_VALIDITY) { + pk.supra_keys.bls_threshold_validity_certificate_key + } else if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_QUORUM) { + pk.supra_keys.bls_threshold_quorum_certificate_key + } else if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_UNANIMOUS) { + pk.supra_keys.bls_threshold_unanimous_certificate_key + } else if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_BCFT_VALIDITY) { + pk.supra_keys.bls_threshold_bcft_validity_certificate_key + } else if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_BCFT_QUORUM) { + pk.supra_keys.bls_threshold_bcft_quorum_certificate_key + } else if (threshold_type + == CERTIFICATE_THRESHOLD_TYPE_BCFT_FALLBACK_VIEW_CHANGE) { + pk.supra_keys.bls_threshold_bcft_fallback_view_change_certificate_key + } else if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_CLAN_MAJORITY) { + pk.supra_keys.bls_threshold_clan_majority_certificate_key + } else { + abort error::invalid_argument(EUNKNOWN_THRESHOLD_TYPE) + } + } + + public fun rotate_supra_bls_threshold_validity_key( + pk: &mut ValidatorPublicKeys, new_bls_threshold_validity_key: bls12381::PublicKey + ) { + pk.supra_keys.bls_threshold_validity_certificate_key = option::some( + new_bls_threshold_validity_key + ); + } + + public fun rotate_supra_bls_threshold_quorum_key( + pk: &mut ValidatorPublicKeys, new_bls_threshold_quorum_key: bls12381::PublicKey + ) { + pk.supra_keys.bls_threshold_quorum_certificate_key = option::some( + new_bls_threshold_quorum_key + ); + } + + public fun rotate_supra_bls_threshold_unanimous_key( + pk: &mut ValidatorPublicKeys, new_key: bls12381::PublicKey + ) { + pk.supra_keys.bls_threshold_unanimous_certificate_key = option::some(new_key); + } + + public fun rotate_supra_bls_threshold_bcft_validity_key( + pk: &mut ValidatorPublicKeys, new_key: bls12381::PublicKey + ) { + pk.supra_keys.bls_threshold_bcft_validity_certificate_key = option::some(new_key); + } + + public fun rotate_supra_bls_threshold_bcft_quorum_key( + pk: &mut ValidatorPublicKeys, new_key: bls12381::PublicKey + ) { + pk.supra_keys.bls_threshold_bcft_quorum_certificate_key = option::some(new_key); + } + + public fun rotate_supra_bls_threshold_bcft_fallback_view_change_key( + pk: &mut ValidatorPublicKeys, new_key: bls12381::PublicKey + ) { + pk.supra_keys.bls_threshold_bcft_fallback_view_change_certificate_key = option::some( + new_key + ); + } + + public fun rotate_supra_bls_threshold_clan_majority_key( + pk: &mut ValidatorPublicKeys, new_key: bls12381::PublicKey + ) { + pk.supra_keys.bls_threshold_clan_majority_certificate_key = option::some(new_key); + } + + /// Rotate a threshold key based on the threshold type tag. + /// threshold_type: 0=validity, 1=quorum, 2=unanimous, 3=bcft_validity, 4=bcft_quorum, 5=bcft_fallback_view_change, 6=clan_majority + public fun rotate_supra_bls_threshold_key_by_type( + pk: &mut ValidatorPublicKeys, threshold_type: u8, new_key: bls12381::PublicKey + ) { + if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_VALIDITY) { + rotate_supra_bls_threshold_validity_key(pk, new_key); + } else if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_QUORUM) { + rotate_supra_bls_threshold_quorum_key(pk, new_key); + } else if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_UNANIMOUS) { + rotate_supra_bls_threshold_unanimous_key(pk, new_key); + } else if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_BCFT_VALIDITY) { + rotate_supra_bls_threshold_bcft_validity_key(pk, new_key); + } else if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_BCFT_QUORUM) { + rotate_supra_bls_threshold_bcft_quorum_key(pk, new_key); + } else if (threshold_type + == CERTIFICATE_THRESHOLD_TYPE_BCFT_FALLBACK_VIEW_CHANGE) { + rotate_supra_bls_threshold_bcft_fallback_view_change_key(pk, new_key); + } else if (threshold_type == CERTIFICATE_THRESHOLD_TYPE_CLAN_MAJORITY) { + rotate_supra_bls_threshold_clan_majority_key(pk, new_key); + } else { + abort error::invalid_argument(EUNKNOWN_THRESHOLD_TYPE) + }; + } + + #[test_only] + /// Generates validator key pair for testing. + public fun generate_keys(): (ValidatorSecretKeys, ValidatorPublicKeys) { + let (network_key_sk, network_key_pk) = ed25519::generate_keys(); + let (supra_bls12381_multi_sig_sk, supra_bls12381_multi_sig_pk) = + bls12381::generate_keys(); + let (supra_cg_sk, supra_cg_pk) = class_groups::generate_keys(); + let (supra_ed_key_sk, supra_ed_key_pk) = ed25519::generate_keys(); + + let sk = ValidatorSecretKeys { + network_key: network_key_sk, + supra_bls_multi_sig_bls_key: supra_bls12381_multi_sig_sk, + supra_bls_threshold_validity_key: option::none(), + supra_bls_threshold_quorum_key: option::none(), + supra_bls_threshold_unanimous_key: option::none(), + supra_bls_threshold_bcft_validity_key: option::none(), + supra_bls_threshold_bcft_quorum_key: option::none(), + supra_bls_threshold_bcft_fallback_view_change_key: option::none(), + supra_bls_threshold_clan_majority_key: option::none(), + cg_key: supra_cg_sk, + supra_ed_key: supra_ed_key_sk + }; + + let pk = ValidatorPublicKeys { + network_key: network_key_pk, + supra_keys: InternalPublicKeys { + bls_multisig_key: public_key_with_pop_to_normal( + &supra_bls12381_multi_sig_pk + ), + bls_threshold_validity_certificate_key: option::none(), + bls_threshold_quorum_certificate_key: option::none(), + bls_threshold_unanimous_certificate_key: option::none(), + bls_threshold_bcft_validity_certificate_key: option::none(), + bls_threshold_bcft_quorum_certificate_key: option::none(), + bls_threshold_bcft_fallback_view_change_certificate_key: option::none(), + bls_threshold_clan_majority_certificate_key: option::none(), + class_group_key: supra_cg_pk, + ed25519_key: supra_ed_key_pk + } + }; + + (sk, pk) + } + + #[test_only] + /// Serializes `pk` and appends a valid BLS multisig proof-of-possession generated from `sk`, + /// producing the exact blob an operator submits to `stake::rotate_consensus_key` under the v2 + /// identity format. + public fun serialized_keys_with_pop_for_test( + sk: &ValidatorSecretKeys, pk: &ValidatorPublicKeys + ): vector { + let pop = bls12381::generate_proof_of_possession(&sk.supra_bls_multi_sig_bls_key); + let blob = public_key_to_bytes(*pk); + vector::append(&mut blob, bls12381::proof_of_possession_to_bytes(&pop)); + blob + } + + #[test] + fun test_verify_bls_multisig_pop() { + let (sk, pk) = validator_public_keys::generate_keys(); + // A PoP generated from the matching secret verifies. + let pop = bls12381::generate_proof_of_possession(&sk.supra_bls_multi_sig_bls_key); + assert!( + verify_bls_multisig_pop(&pk, bls12381::proof_of_possession_to_bytes(&pop)), + 5001 + ); + // A PoP for a different key does not. + let (other_sk, _other_pk) = validator_public_keys::generate_keys(); + let other_pop = + bls12381::generate_proof_of_possession(&other_sk.supra_bls_multi_sig_bls_key); + assert!( + !verify_bls_multisig_pop(&pk, bls12381::proof_of_possession_to_bytes(&other_pop)), + 5002 + ); + } + + #[test] + fun test_split_consensus_key_and_pop_roundtrip() { + let (sk, pk) = validator_public_keys::generate_keys(); + let keys_bytes = public_key_to_bytes(pk); + let blob = serialized_keys_with_pop_for_test(&sk, &pk); + let (split_keys, split_pop) = split_consensus_key_and_pop(blob); + // The prefix is exactly the original key bytes... + assert!(split_keys == keys_bytes, 5101); + // ...and the suffix is a PoP that verifies against the multisig key. + assert!(verify_bls_multisig_pop(&pk, split_pop), 5102); + } + + #[test] + fun test_serde_roundtrip() { + // Generate full keypair + let (_sk, pk) = validator_public_keys::generate_keys(); + + // Serialize + let bytes = validator_public_keys::public_key_to_bytes(pk); + + // Parse + let parsed = validator_public_keys::validator_public_keys_from_bytes(bytes); + + // Compare network key + let ed0 = get_network_key(&pk); + let ed1 = get_network_key(&parsed); + assert!(ed0 == ed1, 1001); + + // BLS multi sig equal + let b0 = get_supra_bls_multi_sig_pub_key(&pk); + let b1 = get_supra_bls_multi_sig_pub_key(&parsed); + assert!(b0 == b1, 1002); + + // CG key equal + let c0 = get_supra_cg_key(&pk); + let c1 = get_supra_cg_key(&parsed); + assert!(c0 == c1, 1003); + + // Compare ED bytes + let ed0 = get_supra_ed_key(&pk); + let ed1 = get_supra_ed_key(&parsed); + assert!(ed0 == ed1, 1004); + } + + #[test] + fun test_replace_static_keys_preserves_threshold_keys() { + // `target` carries a DKG-style threshold key; `source` carries only static keys (its + // threshold fields are `none`, modelling an operator's rotation payload). + let (_sk_a, pk_a) = validator_public_keys::generate_keys(); + let (_sk_b, pk_b) = validator_public_keys::generate_keys(); + + let (_t_sk, t_pop_pk) = bls12381::generate_keys(); + let threshold_key = public_key_with_pop_to_normal(&t_pop_pk); + rotate_supra_bls_threshold_validity_key(&mut pk_a, threshold_key); + + replace_static_keys(&mut pk_a, &pk_b); + + // The four static keys now equal those of `source`. + assert!(get_network_key(&pk_a) == get_network_key(&pk_b), 2001); + assert!( + get_supra_bls_multi_sig_pub_key(&pk_a) + == get_supra_bls_multi_sig_pub_key(&pk_b), + 2002 + ); + assert!(get_supra_cg_key(&pk_a) == get_supra_cg_key(&pk_b), 2003); + assert!(get_supra_ed_key(&pk_a) == get_supra_ed_key(&pk_b), 2004); + + // The DKG-managed threshold key was preserved (it was `none` in `source`). + let preserved = + get_supra_bls_threshold_key_by_type( + &pk_a, CERTIFICATE_THRESHOLD_TYPE_VALIDITY + ); + assert!(option::is_some(&preserved), 2005); + assert!(option::extract(&mut preserved) == threshold_key, 2006); + } + + #[test_only] + /// Rewrites a serialized `ValidatorPublicKeys` blob so its network key is malformed (replaced + /// with an empty byte vector) while keeping the BCS framing intact, so it still deserializes via + /// `validator_public_keys_from_bytes` yet fails `validate_static_keys`. + fun with_empty_network_key(bytes: vector): vector { + // The network key is the first BCS field: a 32-byte vector encoded as `0x20 ++ 32 bytes`. + // Replace it with an empty vector (`0x00`) and keep the remaining fields untouched. + let corrupt = vector::empty(); + vector::push_back(&mut corrupt, 0); + let i = 33; // skip the original length byte (0x20) plus the 32 key bytes. + let len = vector::length(&bytes); + while (i < len) { + vector::push_back(&mut corrupt, *vector::borrow(&bytes, i)); + i = i + 1; + }; + corrupt + } + + #[test_only] + /// Returns a malformed (empty network key) `ValidatorPublicKeys` blob with no appended PoP. Used + /// to exercise `validate_static_keys` directly. + public fun serialized_keys_with_invalid_network_key_for_test(): vector { + let (_sk, pk) = validator_public_keys::generate_keys(); + with_empty_network_key(public_key_to_bytes(pk)) + } + + #[test_only] + /// Returns a malformed (empty network key) blob with a *valid* BLS multisig PoP appended -- the + /// shape an operator submits under v2. PoP verification passes (the multisig key is untouched), + /// so `stake::validate_consensus_public_key` reaches and fails the static-key check, exercising + /// the full registration path. + public fun serialized_keys_with_invalid_network_key_and_pop_for_test(): vector { + let (sk, pk) = validator_public_keys::generate_keys(); + let corrupt = with_empty_network_key(public_key_to_bytes(pk)); + let pop = bls12381::generate_proof_of_possession(&sk.supra_bls_multi_sig_bls_key); + vector::append(&mut corrupt, bls12381::proof_of_possession_to_bytes(&pop)); + corrupt + } + + #[test] + fun test_validate_static_keys_rejects_malformed_key() { + // Freshly generated keys are valid. + let (_sk, pk) = validator_public_keys::generate_keys(); + assert!(validate_static_keys(&pk), 4001); + + // A blob carrying a malformed (empty) network key deserializes but fails validation. + let corrupt = serialized_keys_with_invalid_network_key_for_test(); + let bad = validator_public_keys_from_bytes(corrupt); + assert!(!validate_static_keys(&bad), 4002); + } +} diff --git a/aptos-move/framework/supra-framework/sources/vesting_without_staking.move b/aptos-move/framework/supra-framework/sources/vesting_without_staking.move index 0822dd66d94..468b978cdb4 100644 --- a/aptos-move/framework/supra-framework/sources/vesting_without_staking.move +++ b/aptos-move/framework/supra-framework/sources/vesting_without_staking.move @@ -62,6 +62,8 @@ module supra_framework::vesting_without_staking { const ESHAREHOLDER_NOT_EXIST: u64 = 18; /// Invalid vesting schedule parameter const EINVALID_VESTING_SCHEDULE: u64 = 19; + /// Invalid vesting delay parameter + const EINVALID_VESTING_DELAY: u64 = 20; /// Vesting contract states. /// Vesting contract is active and distributions can be made. @@ -209,11 +211,10 @@ module supra_framework::vesting_without_staking { vesting_contract_address: address, shareholder_address: address ): (u64, u64, u64) acquires VestingContract { assert_vesting_contract_exists(vesting_contract_address); - let vesting_record = - simple_map::borrow( - &borrow_global(vesting_contract_address).shareholders, - &shareholder_address, - ); + let vesting_record = simple_map::borrow( + &borrow_global(vesting_contract_address).shareholders, + &shareholder_address, + ); ( vesting_record.init_amount, vesting_record.left_amount, @@ -324,7 +325,7 @@ module supra_framework::vesting_without_staking { // last vesting fraction must be non zero to ensure that no amount remains unvested forever. assert!( fixed_point32::get_raw_value(*vector::borrow(&schedule, schedule_len - 1)) != - 0, + 0, error::invalid_argument(EEMPTY_VESTING_SCHEDULE), ); assert!( @@ -441,20 +442,23 @@ module supra_framework::vesting_without_staking { // Initialize the vesting contract in a new resource account. This allows the same admin to create multiple // pools. - let (contract_signer, contract_signer_cap) = - create_vesting_contract_account(admin, contract_creation_seed); + let (contract_signer, contract_signer_cap) = create_vesting_contract_account( + admin, contract_creation_seed + ); let contract_signer_address = signer::address_of(&contract_signer); let schedule = vector::map_ref( &vesting_numerators, |numerator| { - let event = - fixed_point32::create_from_rational(*numerator, vesting_denominator); + let event = fixed_point32::create_from_rational( + *numerator, vesting_denominator + ); event }, ); - let vesting_schedule = - create_vesting_schedule(schedule, start_timestamp_secs, period_duration); + let vesting_schedule = create_vesting_schedule( + schedule, start_timestamp_secs, period_duration + ); let shareholders_map = simple_map::create(); let grant_amount = 0; vector::for_each_reverse( @@ -568,8 +572,9 @@ module supra_framework::vesting_without_staking { // Initialize the vesting contract in a new resource account. This allows the same admin to create multiple // pools. - let (contract_signer, contract_signer_cap) = - create_vesting_contract_account(admin, contract_creation_seed); + let (contract_signer, contract_signer_cap) = create_vesting_contract_account( + admin, contract_creation_seed + ); let contract_signer_address = signer::address_of(&contract_signer); coin::deposit(contract_signer_address, grant); @@ -645,10 +650,9 @@ module supra_framework::vesting_without_staking { return }; - let vesting_record = - simple_map::borrow_mut( - &mut vesting_contract.shareholders, &shareholder_address - ); + let vesting_record = simple_map::borrow_mut( + &mut vesting_contract.shareholders, &shareholder_address + ); let signer_cap = &vesting_contract.signer_cap; // Check if the next vested period has already passed. If not, short-circuit since there's nothing to vest. @@ -656,9 +660,9 @@ module supra_framework::vesting_without_staking { let schedule = &vesting_schedule.schedule; let last_vested_period = vesting_record.last_vested_period; let next_period_to_vest = last_vested_period + 1; - let last_completed_period = - (timestamp::now_seconds() - vesting_schedule.start_timestamp_secs) / vesting_schedule - .period_duration; + let last_completed_period = ( + timestamp::now_seconds() - vesting_schedule.start_timestamp_secs + ) / vesting_schedule.period_duration; // Index is 0-based while period is 1-based so we need to subtract 1. let one = fixed_point32::create_from_rational(1, 1); @@ -683,9 +687,10 @@ module supra_framework::vesting_without_staking { let final_fraction = *vector::borrow(schedule, vector::length(schedule) - 1); // Determine how many periods is needed based on the left_amount periods_fast_forward = last_completed_period - next_period_to_vest + 1; - let added_fraction = fixed_point32::multiply_u64_return_fixpoint32( - periods_fast_forward, final_fraction - ); + let added_fraction = + fixed_point32::multiply_u64_return_fixpoint32( + periods_fast_forward, final_fraction + ); // If the added_fraction is greater than or equal to the left_amount, then we can vest all the left_amount total_vesting_fraction = fixed_point32::add( total_vesting_fraction, added_fraction @@ -695,12 +700,13 @@ module supra_framework::vesting_without_staking { // Make sure the total vesting fraction is not greater than 1. total_vesting_fraction = fixed_point32::min(total_vesting_fraction, one); // We don't need to check vesting_record.left_amount > 0 because vest_transfer will handle that. - let transfer_happened = vest_transfer( - vesting_record, - signer_cap, - beneficiary, - total_vesting_fraction, - ); + let transfer_happened = + vest_transfer( + vesting_record, + signer_cap, + beneficiary, + total_vesting_fraction, + ); //If no amount was transferred DO NOT advance last_vested_period in the vesting record // This check is needed because if the fraction is too low, `vesting_record.init_amount * vesting_fraction` // may be 0. By not advancing, we allow for the possibility for `vesting_fraction` to become large enough @@ -733,11 +739,10 @@ module supra_framework::vesting_without_staking { let vesting_signer = account::create_signer_with_capability(signer_cap); //amount to be transfer is minimum of what is left and vesting fraction due of init_amount - let amount = - min( - vesting_record.left_amount, - fixed_point32::multiply_u64(vesting_record.init_amount, vesting_fraction), - ); + let amount = min( + vesting_record.left_amount, + fixed_point32::multiply_u64(vesting_record.init_amount, vesting_fraction), + ); if (amount > 0) { //update left_amount for the shareholder vesting_record.left_amount = vesting_record.left_amount - amount; @@ -746,6 +751,30 @@ module supra_framework::vesting_without_staking { } else { false } } + // CAUTION: This function will delay all shareholders' vesting by `delay_periods`. To be called + // by multisig admin only with extreme caution. + public entry fun admin_delay_vesting( + admin: &signer, contract_address: address, delay_periods: u64 + ) acquires VestingContract { + assert_active_vesting_contract(contract_address); + let vesting_contract = borrow_global_mut(contract_address); + verify_admin(admin, vesting_contract); + + assert!(delay_periods > 0, error::invalid_argument(EINVALID_VESTING_DELAY)); + let (shareholders, vrecords) = simple_map::to_vec_pair( + vesting_contract.shareholders + ); + vector::zip_mut( + &mut shareholders, + &mut vrecords, + |_s, vrecord| { + let mrecord: &mut VestingRecord = vrecord; + mrecord.last_vested_period = mrecord.last_vested_period + delay_periods; + }, + ); + vesting_contract.shareholders = simple_map::new_from(shareholders, vrecords); + } + public entry fun set_vesting_schedule( admin: &signer, contract_address: address, @@ -775,9 +804,8 @@ module supra_framework::vesting_without_staking { &mut values, |shareholder, srecord| { let msrecord: &mut VestingRecord = srecord; - let new_last_vested_period = ( - msrecord.last_vested_period * old_period_duration - ) / period_duration; + let new_last_vested_period = + (msrecord.last_vested_period * old_period_duration) / period_duration; msrecord.last_vested_period = new_last_vested_period; }, ); @@ -806,8 +834,9 @@ module supra_framework::vesting_without_staking { let vesting_contract = borrow_global_mut(contract_address); verify_admin(admin, vesting_contract); let vesting_signer = get_vesting_account_signer_internal(vesting_contract); - let shareholder_amount = - simple_map::borrow(&vesting_contract.shareholders, &shareholder_address).left_amount; + let shareholder_amount = simple_map::borrow( + &vesting_contract.shareholders, &shareholder_address + ).left_amount; coin::transfer( &vesting_signer, vesting_contract.withdrawal_address, shareholder_amount ); @@ -822,16 +851,18 @@ module supra_framework::vesting_without_staking { // remove `shareholder_address`` from `vesting_contract.shareholders` let shareholders = &mut vesting_contract.shareholders; - let (_, shareholders_vesting) = - simple_map::remove(shareholders, &shareholder_address); + let (_, shareholders_vesting) = simple_map::remove( + shareholders, &shareholder_address + ); // remove `shareholder_address` from `vesting_contract.beneficiaries` let beneficiary = option::none(); let shareholder_beneficiaries = &mut vesting_contract.beneficiaries; // Not all shareholders have their beneficiaries, so before removing them, we need to check if the beneficiary exists if (simple_map::contains_key(shareholder_beneficiaries, &shareholder_address)) { - let (_, shareholder_baneficiary) = - simple_map::remove(shareholder_beneficiaries, &shareholder_address); + let (_, shareholder_baneficiary) = simple_map::remove( + shareholder_beneficiaries, &shareholder_address + ); beneficiary = option::some(shareholder_baneficiary); }; @@ -862,10 +893,9 @@ module supra_framework::vesting_without_staking { vector::for_each_ref( &shareholders_address, |shareholder| { - let shareholder_amount = - simple_map::borrow_mut( - &mut vesting_contract.shareholders, shareholder - ); + let shareholder_amount = simple_map::borrow_mut( + &mut vesting_contract.shareholders, shareholder + ); shareholder_amount.left_amount = 0; }, ); @@ -938,9 +968,9 @@ module supra_framework::vesting_without_staking { let vesting_contract = borrow_global_mut(contract_address); let addr = signer::address_of(account); assert!( - addr == vesting_contract.admin - || addr - == get_role_holder(contract_address, utf8(ROLE_BENEFICIARY_RESETTER)), + addr == vesting_contract.admin || addr == get_role_holder( + contract_address, utf8(ROLE_BENEFICIARY_RESETTER) + ), error::permission_denied(EPERMISSION_DENIED), ); @@ -966,8 +996,7 @@ module supra_framework::vesting_without_staking { VestingAccountManagement { roles: simple_map::create() }, ) }; - let roles = - &mut borrow_global_mut(contract_address).roles; + let roles = &mut borrow_global_mut(contract_address).roles; simple_map::upsert(roles, role, role_holder); } @@ -1155,12 +1184,11 @@ module supra_framework::vesting_without_staking { ); }, ); - let vesting_schedule = - create_vesting_schedule( - schedule, - timestamp::now_seconds() + VESTING_SCHEDULE_CLIFF, - VESTING_PERIOD, - ); + let vesting_schedule = create_vesting_schedule( + schedule, + timestamp::now_seconds() + VESTING_SCHEDULE_CLIFF, + VESTING_PERIOD, + ); let buy_ins = simple_map::create>(); vector::enumerate_ref( @@ -1240,18 +1268,17 @@ module supra_framework::vesting_without_staking { ); stake::mint(admin, GRANT_AMOUNT); // Contract with monthly vesting 10% - let contract_address = - setup_vesting_contract_with_amount_with_schedule( - admin, - shareholders, - shares, - withdrawal_address, - vector[10], - 100, - ); + let contract_address = setup_vesting_contract_with_amount_with_schedule( + admin, + shareholders, + shares, + withdrawal_address, + vector[10], + 100, + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount_1 = 0; @@ -1279,8 +1306,9 @@ module supra_framework::vesting_without_staking { vested_amount_2 = 7; // 1% of 750 is 7 with rounding let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(init_amount - left_amount == vested_amount_2, 0); assert!(last_vested_period == 1, 0); @@ -1290,8 +1318,9 @@ module supra_framework::vesting_without_staking { vested_amount_2 = 14; // 2% of 750 is 14 with rounding shareholder_2_balance = coin::balance(shareholder_2_address); assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(init_amount - left_amount == vested_amount_2, left_amount); assert!(last_vested_period == 2, 0); @@ -1306,13 +1335,15 @@ module supra_framework::vesting_without_staking { 600, ); // last vested period for shareholder 2 should be number of 10 minute periods in 2 years - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 105120, last_vested_period); // no vesting has been called for shareholder 1 yet - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 0, last_vested_period); // When you vest now, shareholder 1 will move to minutes equivalent to 631 = (365*2)+1 days, @@ -1320,15 +1351,17 @@ module supra_framework::vesting_without_staking { //vesting fraction would be too small to vest even 1 quant vest(contract_address); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 105120, last_vested_period); let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(init_amount - left_amount == shareholder_2_balance, 0); assert!(shareholder_2_balance == 14, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 105264, last_vested_period); //shareholder 1 correctly gets 5 quant for 2 year + 1 day of advancement @@ -1365,18 +1398,17 @@ module supra_framework::vesting_without_staking { ); stake::mint(admin, GRANT_AMOUNT); // Contract with monthly vesting 10% - let contract_address = - setup_vesting_contract_with_amount_with_schedule( - admin, - shareholders, - shares, - withdrawal_address, - vector[10], - 100, - ); + let contract_address = setup_vesting_contract_with_amount_with_schedule( + admin, + shareholders, + shares, + withdrawal_address, + vector[10], + 100, + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount_1 = 0; @@ -1404,8 +1436,9 @@ module supra_framework::vesting_without_staking { vested_amount_2 = 7; // 1% of 750 is 7 with rounding let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(init_amount - left_amount == vested_amount_2, 0); assert!(last_vested_period == 1, 0); @@ -1415,8 +1448,9 @@ module supra_framework::vesting_without_staking { vested_amount_2 = 14; // 2% of 750 is 14 with rounding shareholder_2_balance = coin::balance(shareholder_2_address); assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(init_amount - left_amount == vested_amount_2, left_amount); assert!(last_vested_period == 2, 0); @@ -1431,12 +1465,14 @@ module supra_framework::vesting_without_staking { 300, ); // last vested period for shareholder 2 should be number of 5 min periods in 2 years - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 210240, last_vested_period); - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 0, last_vested_period); // When you vest now, both shareholders should vest @@ -1444,16 +1480,18 @@ module supra_framework::vesting_without_staking { // 1 day period is too small to vest anything so last_vested_period and balance will not mvoe // for shareholder 2 - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 210240, last_vested_period); let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(init_amount - left_amount == shareholder_2_balance, 0); assert!(shareholder_2_balance == 14, shareholder_2_balance); //shareholder 1 last_vested_amount will move as per 5 min period in 2year + 1 day - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 210528, last_vested_period); let shareholder_1_balance = coin::balance(shareholder_1_address); @@ -1491,18 +1529,17 @@ module supra_framework::vesting_without_staking { ); stake::mint(admin, GRANT_AMOUNT); // Contract with monthly vesting 10% - let contract_address = - setup_vesting_contract_with_amount_with_schedule( - admin, - shareholders, - shares, - withdrawal_address, - vector[10], - 100, - ); + let contract_address = setup_vesting_contract_with_amount_with_schedule( + admin, + shareholders, + shares, + withdrawal_address, + vector[10], + 100, + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount_1 = 0; @@ -1530,8 +1567,9 @@ module supra_framework::vesting_without_staking { vested_amount_2 = 7; // 1% of 750 is 7 with rounding let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(init_amount - left_amount == vested_amount_2, 0); assert!(last_vested_period == 1, 0); @@ -1541,8 +1579,9 @@ module supra_framework::vesting_without_staking { vested_amount_2 = 14; // 2% of 750 is 14 with rounding shareholder_2_balance = coin::balance(shareholder_2_address); assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(init_amount - left_amount == vested_amount_2, left_amount); assert!(last_vested_period == 2, 0); @@ -1557,27 +1596,31 @@ module supra_framework::vesting_without_staking { 60, ); // last vested period for shareholder 2 should be number of minutes in 2 years - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 1051200, last_vested_period); - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 0, last_vested_period); vest(contract_address); //for shareholder 2, 1 day period is too small to vest anything so last_vested_period and balance will not mvoe - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 1051200, last_vested_period); let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(init_amount - left_amount == shareholder_2_balance, 0); assert!(shareholder_2_balance == 14, shareholder_2_balance); //for shareholder 1, last_vested_period will be numbbeer of minutes in 2 year + 1 day - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 1052640, last_vested_period); // precision is too low so the balance will be 4 instead of 5 @@ -1614,18 +1657,17 @@ module supra_framework::vesting_without_staking { ); stake::mint(admin, GRANT_AMOUNT); // Contract with monthly vesting 10% - let contract_address = - setup_vesting_contract_with_amount_with_schedule( - admin, - shareholders, - shares, - withdrawal_address, - vector[10], - 100, - ); + let contract_address = setup_vesting_contract_with_amount_with_schedule( + admin, + shareholders, + shares, + withdrawal_address, + vector[10], + 100, + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount_1 = 0; @@ -1653,8 +1695,9 @@ module supra_framework::vesting_without_staking { vested_amount_2 = 7; // 1% of 750 is 7 with rounding let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(init_amount - left_amount == vested_amount_2, 0); assert!(last_vested_period == 1, 0); @@ -1664,8 +1707,9 @@ module supra_framework::vesting_without_staking { vested_amount_2 = 14; // 2% of 750 is 14 with rounding shareholder_2_balance = coin::balance(shareholder_2_address); assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(init_amount - left_amount == vested_amount_2, left_amount); assert!(last_vested_period == 2, 0); @@ -1679,20 +1723,23 @@ module supra_framework::vesting_without_staking { 365 * ONE_DAY * 10000, 1, ); - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 63072000, last_vested_period); - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 0, last_vested_period); // When you vest now, both shareholder 1 and shareholder 2 should have 9 weeks passed vest(contract_address); // for shareholder 2, last_vested_period will be number of seconds in 2 years - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 63072000, last_vested_period); // 1 day period is too small to vest anything so last_vested_period and balance will not mvoe let shareholder_2_balance = coin::balance(shareholder_2_address); @@ -1700,8 +1747,9 @@ module supra_framework::vesting_without_staking { assert!(shareholder_2_balance == 14, shareholder_2_balance); //for shareholder 1, last_vested_period will be number of seconds in 2 year + 1 day - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 63158400, last_vested_period); //precision is too low, the fraction loses 38-40% of the value @@ -1738,18 +1786,17 @@ module supra_framework::vesting_without_staking { ); stake::mint(admin, GRANT_AMOUNT); // Contract with monthly vesting 10% - let contract_address = - setup_vesting_contract_with_amount_with_schedule( - admin, - shareholders, - shares, - withdrawal_address, - vector[10], - 100, - ); + let contract_address = setup_vesting_contract_with_amount_with_schedule( + admin, + shareholders, + shares, + withdrawal_address, + vector[10], + 100, + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount_1 = 0; @@ -1769,8 +1816,9 @@ module supra_framework::vesting_without_staking { vested_amount_2 = GRANT_AMOUNT * 3 * 10 / 400 - 1; // diff of 1 because of rounding let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(init_amount - left_amount == vested_amount_2, 0); assert!(last_vested_period == 1, 0); @@ -1780,8 +1828,9 @@ module supra_framework::vesting_without_staking { vested_amount_2 = GRANT_AMOUNT * 3 * 20 / 400 - 2; shareholder_2_balance = coin::balance(shareholder_2_address); assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(init_amount - left_amount == vested_amount_2, left_amount); assert!(last_vested_period == 2, 0); @@ -1797,19 +1846,22 @@ module supra_framework::vesting_without_staking { ); // last vested period for shareholder 2 should be 8, while total 65 days have passed but his // last vesting corresponds to 60 days, so 8 weeks have passed - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 8, last_vested_period); - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 0, last_vested_period); // When you vest now, both shareholder 1 and shareholder 2 should have 9 weeks passed vest(contract_address); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 9, last_vested_period); let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(init_amount - left_amount == shareholder_2_balance, 0); @@ -1817,8 +1869,9 @@ module supra_framework::vesting_without_staking { // so instead of 157 ( 17.49 * 9) he will get 165 assert!(shareholder_2_balance == 165, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 9, last_vested_period); let shareholder_1_balance = coin::balance(shareholder_1_address); @@ -1833,19 +1886,22 @@ module supra_framework::vesting_without_staking { 1000, 3 * ONE_DAY, ); - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 21, last_vested_period); - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 21, last_vested_period); // When you vest now, both shareholder 1 and shareholder 2 should have 9 weeks passed vest(contract_address); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 22, last_vested_period); let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(init_amount - left_amount == shareholder_2_balance, 0); @@ -1853,8 +1909,9 @@ module supra_framework::vesting_without_staking { // so instead of 157 ( 17.49 * 9) he will get 165 assert!(shareholder_2_balance == 172, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 22, last_vested_period); let shareholder_1_balance = coin::balance(shareholder_1_address); @@ -1871,19 +1928,22 @@ module supra_framework::vesting_without_staking { 3000, ONE_DAY, ); - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 66, last_vested_period); - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 66, last_vested_period); // When you vest now, both shareholder 1 and shareholder 2 should have 9 weeks passed vest(contract_address); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 68, last_vested_period); let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(init_amount - left_amount == shareholder_2_balance, 0); @@ -1891,8 +1951,9 @@ module supra_framework::vesting_without_staking { // so instead of 157 ( 17.49 * 9) he will get 165 assert!(shareholder_2_balance == 176, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 68, last_vested_period); let shareholder_1_balance = coin::balance(shareholder_1_address); @@ -1910,19 +1971,22 @@ module supra_framework::vesting_without_staking { 1, ); //last vesting happened at 68 days meaning 5875200 seconds - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 5875200, last_vested_period); - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 5875200, last_vested_period); // When you vest now, both shareholder 1 and shareholder 2 should have 9 weeks passed vest(contract_address); // if the vesting fraction is too low so that vesting amount is zero, last_vested_period should not advance - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 5875200, last_vested_period); let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(init_amount - left_amount == shareholder_2_balance, 0); @@ -1930,8 +1994,9 @@ module supra_framework::vesting_without_staking { // so instead of 157 ( 17.49 * 9) he will get 165 assert!(shareholder_2_balance == 176, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 5875200, last_vested_period); let shareholder_1_balance = coin::balance(shareholder_1_address); @@ -1941,8 +2006,9 @@ module supra_framework::vesting_without_staking { timestamp::fast_forward_seconds(2 * ONE_DAY); vest(contract_address); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 6051600, last_vested_period); let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(init_amount - left_amount == shareholder_2_balance, 0); @@ -1950,8 +2016,9 @@ module supra_framework::vesting_without_staking { // so instead of 157 ( 17.49 * 9) he will get 165 assert!(shareholder_2_balance == 181, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 6051600, last_vested_period); let shareholder_1_balance = coin::balance(shareholder_1_address); @@ -1988,18 +2055,17 @@ module supra_framework::vesting_without_staking { ); stake::mint(admin, GRANT_AMOUNT); // Contract with monthly vesting 10% - let contract_address = - setup_vesting_contract_with_amount_with_schedule( - admin, - shareholders, - shares, - withdrawal_address, - vector[10], - 100, - ); + let contract_address = setup_vesting_contract_with_amount_with_schedule( + admin, + shareholders, + shares, + withdrawal_address, + vector[10], + 100, + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount_1 = 0; @@ -2019,8 +2085,9 @@ module supra_framework::vesting_without_staking { vested_amount_2 = GRANT_AMOUNT * 3 * 10 / 400 - 1; // diff of 1 because of rounding let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(init_amount - left_amount == vested_amount_2, 0); assert!(last_vested_period == 1, 0); @@ -2030,8 +2097,9 @@ module supra_framework::vesting_without_staking { vested_amount_2 = GRANT_AMOUNT * 3 * 20 / 400 - 2; shareholder_2_balance = coin::balance(shareholder_2_address); assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(init_amount - left_amount == vested_amount_2, left_amount); assert!(last_vested_period == 2, 0); @@ -2049,7 +2117,8 @@ module supra_framework::vesting_without_staking { } #[test(supra_framework = @0x1, admin = @0x123, shareholder_1 = @0x234, shareholder_2 = @0x345, withdrawal = @111)] - public entry fun test_e2e_with_vesting_schedule_update_increasing_period( + #[expected_failure(abort_code = 262151, location = Self)] + public entry fun test_e2e_with_admin_vesting_delay_increasing_period( supra_framework: &signer, admin: &signer, shareholder_1: &signer, @@ -2075,15 +2144,14 @@ module supra_framework::vesting_without_staking { ); stake::mint(admin, GRANT_AMOUNT); // Contract with monthly vesting 10% - let contract_address = - setup_vesting_contract_with_amount_with_schedule( - admin, - shareholders, - shares, - withdrawal_address, - vector[10], - 100, - ); + let contract_address = setup_vesting_contract_with_amount_with_schedule( + admin, + shareholders, + shares, + withdrawal_address, + vector[10], + 100, + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == 1, @@ -2106,8 +2174,9 @@ module supra_framework::vesting_without_staking { vested_amount_2 = GRANT_AMOUNT * 3 * 10 / 400 - 1; // diff of 1 because of rounding let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(init_amount - left_amount == vested_amount_2, 0); assert!(last_vested_period == 1, 0); @@ -2117,36 +2186,187 @@ module supra_framework::vesting_without_staking { vested_amount_2 = GRANT_AMOUNT * 3 * 20 / 400 - 2; shareholder_2_balance = coin::balance(shareholder_2_address); assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(init_amount - left_amount == vested_amount_2, left_amount); assert!(last_vested_period == 2, 0); - // Fast forward time to another 42 days, total 102 days from start - timestamp::fast_forward_seconds(42 * ONE_DAY); - // Note that per month 10% would now translate to 4/30 , approx 13.3333333% per 40 days - set_vesting_schedule( - admin, - contract_address, - vector[40], - 300, - 40 * ONE_DAY, + //increase delay by 2 periods (months) + admin_delay_vesting( + admin, contract_address, 2 ); - // last vested period for shareholder 2 should be 1, while total 102 days have passed, from last vesting at 60 day - // only one 40 day period has passed - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); - assert!(last_vested_period == 1, last_vested_period); - - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); - assert!(last_vested_period == 0, last_vested_period); - // When you vest now, both shareholder 1 and shareholder 2 should have 2* 40 day period passed + //assert last_vested_period is 4 and 2 for shareholder 2 and 1 respectively + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); + assert!(last_vested_period == 4, last_vested_period); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); + assert!(last_vested_period == 2, last_vested_period); + + // fast forward by one period, now 3 periods have passed + timestamp::fast_forward_seconds(period_duration_secs(contract_address)); + // When you vest now, both shareholder 1 will get 1 vesting fraction and shareholder 2 will + // stay the same as last_vested_period is 4 vest(contract_address); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); + assert!(last_vested_period == 4, last_vested_period); + let shareholder_2_balance = coin::balance(shareholder_2_address); + assert!(init_amount - left_amount == shareholder_2_balance, 0); + // balance is 148 as shareholder 2 has 2 vested fractions of 75 each but lost 2 due to corresponding + // vest_individual (directly or indirectly by vest) was called twice for this shareholder + assert!(shareholder_2_balance == 148, shareholder_2_balance); + + // for shareholder 1, 3 periods have passed + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); + assert!(last_vested_period == 3, last_vested_period); + + // for shareholder 1, 10% of 250 would be 24 (1 missed due to rounding) + // even though 3 periods is passed, got only one fraction due to delay introduced + let shareholder_1_balance = coin::balance(shareholder_1_address); + assert!(init_amount - left_amount == shareholder_1_balance, 0); + assert!(shareholder_1_balance == 24, shareholder_1_balance); + + // fast forward by 4 periods, now 7 periods have passed + timestamp::fast_forward_seconds(period_duration_secs(contract_address) * 4); + // now last vested period should be 7 for both shareholders + vest(contract_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); + assert!(last_vested_period == 7, last_vested_period); + let shareholder_2_balance = coin::balance(shareholder_2_address); + assert!(init_amount - left_amount == shareholder_2_balance, 0); + // shareholder will have 5 vested fractions (2 missed due to introduced delay) 75 * 5 = 375 but missing 3 due to rounding + assert!(shareholder_2_balance == 372, shareholder_2_balance); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); + assert!(last_vested_period == 7, last_vested_period); + let shareholder_1_balance = coin::balance(shareholder_1_address); + assert!(init_amount - left_amount == shareholder_1_balance, 0); + //shareholder 1 will ahve 5 vested fractions 25 * 5 =125 but missing 2 due to rounding + assert!(shareholder_1_balance == 123, shareholder_1_balance); + + //finally test that non admin can not invoke + admin_delay_vesting( + shareholder_1, + contract_address, + 3, + ); + } + + #[test(supra_framework = @0x1, admin = @0x123, shareholder_1 = @0x234, shareholder_2 = @0x345, withdrawal = @111)] + public entry fun test_e2e_with_vesting_schedule_update_increasing_period( + supra_framework: &signer, + admin: &signer, + shareholder_1: &signer, + shareholder_2: &signer, + withdrawal: &signer + ) acquires AdminStore, VestingContract { + let admin_address = signer::address_of(admin); + let withdrawal_address = signer::address_of(withdrawal); + let shareholder_1_address = signer::address_of(shareholder_1); + let shareholder_2_address = signer::address_of(shareholder_2); + let shareholders = vector[shareholder_1_address, shareholder_2_address]; + let shareholder_1_share = GRANT_AMOUNT / 4; + let shareholder_2_share = GRANT_AMOUNT * 3 / 4; + let shares = vector[shareholder_1_share, shareholder_2_share]; + // Create the vesting contract. + setup( + supra_framework, + vector[ + admin_address, + withdrawal_address, + shareholder_1_address, + shareholder_2_address], + ); + stake::mint(admin, GRANT_AMOUNT); + // Contract with monthly vesting 10% + let contract_address = setup_vesting_contract_with_amount_with_schedule( + admin, + shareholders, + shares, + withdrawal_address, + vector[10], + 100, + ); + assert!( + vector::length(&borrow_global(admin_address).vesting_contracts) == + 1, + 0, + ); + let vested_amount_1 = 0; + let vested_amount_2 = 0; + + assert!(coin::balance(contract_address) == GRANT_AMOUNT, 0); + assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); + assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); + + // Time is now at the start time, vest will unlock the first period, which is 1/10. + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + period_duration_secs(contract_address), + ); + + // After 1st vesting shareholder 2 should have 1/10 of the total amount modulo rounding + vest_individual(contract_address, shareholder_2_address); + vested_amount_2 = GRANT_AMOUNT * 3 * 10 / 400 - 1; // diff of 1 because of rounding + let shareholder_2_balance = coin::balance(shareholder_2_address); + assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); + assert!(init_amount - left_amount == vested_amount_2, 0); + assert!(last_vested_period == 1, 0); + + // Fast forward another month, shareholder 2 should now have 2/10 (20%) vested modulo rounding + timestamp::fast_forward_seconds(period_duration_secs(contract_address)); + vest_individual(contract_address, shareholder_2_address); + vested_amount_2 = GRANT_AMOUNT * 3 * 20 / 400 - 2; + shareholder_2_balance = coin::balance(shareholder_2_address); + assert!(shareholder_2_balance == vested_amount_2, shareholder_2_balance); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); + assert!(init_amount - left_amount == vested_amount_2, left_amount); + assert!(last_vested_period == 2, 0); + + // Fast forward time to another 42 days, total 102 days from start + timestamp::fast_forward_seconds(42 * ONE_DAY); + // Note that per month 10% would now translate to 4/30 , approx 13.3333333% per 40 days + set_vesting_schedule( + admin, + contract_address, + vector[40], + 300, + 40 * ONE_DAY, + ); + // last vested period for shareholder 2 should be 1, while total 102 days have passed, from last vesting at 60 day + // only one 40 day period has passed + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); + assert!(last_vested_period == 1, last_vested_period); + + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); + assert!(last_vested_period == 0, last_vested_period); + + // When you vest now, both shareholder 1 and shareholder 2 should have 2* 40 day period passed + vest(contract_address); + + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 2, last_vested_period); let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(init_amount - left_amount == shareholder_2_balance, 0); @@ -2154,8 +2374,9 @@ module supra_framework::vesting_without_staking { // so instead of 199 shareholder will get 247 assert!(shareholder_2_balance == 247, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 2, last_vested_period); // for shareholder 1, 26.66% of 250 would be 66 @@ -2172,19 +2393,22 @@ module supra_framework::vesting_without_staking { 2 * VESTING_PERIOD, ); //We are still at 102 days so only 1 * 2 month period - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 1, last_vested_period); - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 1, last_vested_period); // When you vest now, both shareholder 1 and shareholder 2 should have 102 days (one 60 day period) passed vest(contract_address); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 1, last_vested_period); let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(init_amount - left_amount == shareholder_2_balance, 0); @@ -2192,8 +2416,9 @@ module supra_framework::vesting_without_staking { // so instead of 157 ( 17.49 * 9) he will get 165 assert!(shareholder_2_balance == 247, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 1, last_vested_period); let shareholder_1_balance = coin::balance(shareholder_1_address); @@ -2210,19 +2435,22 @@ module supra_framework::vesting_without_staking { 100, 4 * VESTING_PERIOD, ); - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 0, last_vested_period); - let (_, _, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (_, _, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 0, last_vested_period); // When you vest now, both shareholder 1 and shareholder 2 should have 9 weeks passed vest(contract_address); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 0, last_vested_period); let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(init_amount - left_amount == shareholder_2_balance, 0); @@ -2230,8 +2458,9 @@ module supra_framework::vesting_without_staking { // so instead of 157 ( 17.49 * 9) he will get 165 assert!(shareholder_2_balance == 247, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 0, last_vested_period); let shareholder_1_balance = coin::balance(shareholder_1_address); @@ -2242,8 +2471,9 @@ module supra_framework::vesting_without_staking { timestamp::fast_forward_seconds(10 * ONE_DAY); vest(contract_address); //last vesting happened at 60 days as per records - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 1, last_vested_period); let shareholder_2_balance = coin::balance(shareholder_2_address); @@ -2253,8 +2483,9 @@ module supra_framework::vesting_without_staking { // so instead of 300 he will get 546 assert!(shareholder_2_balance == 546, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 1, last_vested_period); let shareholder_1_balance = coin::balance(shareholder_1_address); @@ -2271,16 +2502,18 @@ module supra_framework::vesting_without_staking { ); vest(contract_address); // for shareholder 2 scaled last_vested_period would be 4 and upon calling vest would go to 5 - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(last_vested_period == 5, last_vested_period); let shareholder_2_balance = coin::balance(shareholder_2_address); assert!(init_amount - left_amount == shareholder_2_balance, 0); //1 vesting would occur at 10% rate again, so 546 + 74 would be 620 assert!(shareholder_2_balance == 620, shareholder_2_balance); - let (init_amount, left_amount, last_vested_period) = - get_vesting_record(contract_address, shareholder_1_address); + let (init_amount, left_amount, last_vested_period) = get_vesting_record( + contract_address, shareholder_1_address + ); assert!(last_vested_period == 5, last_vested_period); let shareholder_1_balance = coin::balance(shareholder_1_address); @@ -2316,18 +2549,17 @@ module supra_framework::vesting_without_staking { shareholder_1_address, shareholder_2_address], ); - let contract_address = - setup_vesting_contract_with_schedule( - admin, - shareholders, - shares, - withdrawal_address, - &vector[1], - 1, - ); + let contract_address = setup_vesting_contract_with_schedule( + admin, + shareholders, + shares, + withdrawal_address, + &vector[1], + 1, + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount_1 = 0; @@ -2381,18 +2613,17 @@ module supra_framework::vesting_without_staking { shareholder_2_address], ); stake::mint(admin, GRANT_AMOUNT); - let contract_address = - setup_vesting_contract_with_amount_with_schedule( - admin, - shareholders, - shares, - withdrawal_address, - vector[1], - 1, - ); + let contract_address = setup_vesting_contract_with_amount_with_schedule( + admin, + shareholders, + shares, + withdrawal_address, + vector[1], + 1, + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount_1 = 0; @@ -2443,16 +2674,15 @@ module supra_framework::vesting_without_staking { shareholder_1_address, shareholder_2_address], ); - let contract_address = - setup_vesting_contract( - admin, - shareholders, - shares, - withdrawal_address, - ); + let contract_address = setup_vesting_contract( + admin, + shareholders, + shares, + withdrawal_address, + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount_1 = 0; @@ -2495,16 +2725,15 @@ module supra_framework::vesting_without_staking { shareholder_1_address, shareholder_2_address], ); - let contract_address = - setup_vesting_contract( - admin, - shareholders, - shares, - withdrawal_address, - ); + let contract_address = setup_vesting_contract( + admin, + shareholders, + shares, + withdrawal_address, + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount_1 = 0; @@ -2537,7 +2766,7 @@ module supra_framework::vesting_without_staking { timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 2, + * 2, ); vest_individual(contract_address, shareholder_1_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 2, 10); @@ -2564,7 +2793,7 @@ module supra_framework::vesting_without_staking { timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 3, + * 3, ); vest_individual(contract_address, shareholder_1_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 1, 10); @@ -2615,16 +2844,15 @@ module supra_framework::vesting_without_staking { shareholder_1_address, shareholder_2_address], ); - let contract_address = - setup_vesting_contract( - admin, - shareholders, - shares, - withdrawal_address, - ); + let contract_address = setup_vesting_contract( + admin, + shareholders, + shares, + withdrawal_address, + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount_1 = 0; @@ -2633,7 +2861,7 @@ module supra_framework::vesting_without_staking { // Time is now at the start time, vest will unlock the first period, which is 2/10. timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 50, + * 50, ); vest_individual(contract_address, shareholder_1_address); vested_amount_1 = vested_amount_1 + GRANT_AMOUNT / 4; @@ -2657,16 +2885,14 @@ module supra_framework::vesting_without_staking { ); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); - let vesting_record_1 = - simple_map::borrow( - &borrow_global(contract_address).shareholders, - &shareholder_1_address, - ); - let vesting_record_2 = - simple_map::borrow( - &borrow_global(contract_address).shareholders, - &shareholder_2_address, - ); + let vesting_record_1 = simple_map::borrow( + &borrow_global(contract_address).shareholders, + &shareholder_1_address, + ); + let vesting_record_2 = simple_map::borrow( + &borrow_global(contract_address).shareholders, + &shareholder_2_address, + ); //Check that loop only as many vesting periods have passed which is required to vest everything assert!( vesting_record_1.last_vested_period == 50, @@ -2704,16 +2930,15 @@ module supra_framework::vesting_without_staking { shareholder_1_address, shareholder_2_address], ); - let contract_address = - setup_vesting_contract( - admin, - shareholders, - shares, - withdrawal_address, - ); + let contract_address = setup_vesting_contract( + admin, + shareholders, + shares, + withdrawal_address, + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount_1 = 0; @@ -2736,7 +2961,7 @@ module supra_framework::vesting_without_staking { timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 2, + * 2, ); vest(contract_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 2, 10); @@ -2746,7 +2971,7 @@ module supra_framework::vesting_without_staking { timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 3, + * 3, ); vest(contract_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 1, 10); @@ -2756,7 +2981,7 @@ module supra_framework::vesting_without_staking { timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 4, + * 4, ); vest(contract_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 1, 10); @@ -2766,7 +2991,7 @@ module supra_framework::vesting_without_staking { timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 5, + * 5, ); vest(contract_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 1, 10); @@ -2776,7 +3001,7 @@ module supra_framework::vesting_without_staking { timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 6, + * 6, ); vest(contract_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 1, 10); @@ -2786,7 +3011,7 @@ module supra_framework::vesting_without_staking { timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 7, + * 7, ); vest(contract_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 1, 10); @@ -2796,7 +3021,7 @@ module supra_framework::vesting_without_staking { timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 8, + * 8, ); vest(contract_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 1, 10); @@ -2806,7 +3031,7 @@ module supra_framework::vesting_without_staking { timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 9, + * 9, ); vest(contract_address); vested_amount_1 = shareholder_1_share; @@ -2925,16 +3150,15 @@ module supra_framework::vesting_without_staking { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, vector[admin_address, shareholder_address]); - let contract_address = - setup_vesting_contract_with_schedule( - admin, - &vector[shareholder_address], - &vector[GRANT_AMOUNT], - admin_address, - // First vest = 3/4 but last vest should only be for the remaining 1/4. - &vector[3], - 4, - ); + let contract_address = setup_vesting_contract_with_schedule( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + // First vest = 3/4 but last vest should only be for the remaining 1/4. + &vector[3], + 4, + ); // First vest is 3/4 timestamp::update_global_time_for_test_secs( @@ -2964,16 +3188,15 @@ module supra_framework::vesting_without_staking { let shareholder_address = signer::address_of(shareholder); setup(supra_framework, vector[admin_address, shareholder_address]); stake::mint(admin, GRANT_AMOUNT); - let contract_address = - setup_vesting_contract_with_amount_with_schedule( - admin, - vector[shareholder_address], - vector[GRANT_AMOUNT], - admin_address, - // First vest = 3/4 but last vest should only be for the remaining 1/4. - vector[3], - 4, - ); + let contract_address = setup_vesting_contract_with_amount_with_schedule( + admin, + vector[shareholder_address], + vector[GRANT_AMOUNT], + admin_address, + // First vest = 3/4 but last vest should only be for the remaining 1/4. + vector[3], + 4, + ); // First vest is 3/4 timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + VESTING_PERIOD @@ -3002,13 +3225,12 @@ module supra_framework::vesting_without_staking { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, vector[admin_address, shareholder_address]); - let contract_address = - setup_vesting_contract( - admin, - &vector[shareholder_address], - &vector[GRANT_AMOUNT], - admin_address, - ); + let contract_address = setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + ); // Immediately terminate. Calling vest should now fail. terminate_vesting_contract(admin, contract_address); @@ -3023,13 +3245,12 @@ module supra_framework::vesting_without_staking { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, vector[admin_address, shareholder_address]); - let contract_address = - setup_vesting_contract( - admin, - &vector[shareholder_address], - &vector[GRANT_AMOUNT], - admin_address, - ); + let contract_address = setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + ); // Call terminate_vesting_contract twice should fail. terminate_vesting_contract(admin, contract_address); @@ -3044,13 +3265,12 @@ module supra_framework::vesting_without_staking { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, vector[admin_address, shareholder_address]); - let contract_address = - setup_vesting_contract( - admin, - &vector[shareholder_address], - &vector[GRANT_AMOUNT], - admin_address, - ); + let contract_address = setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + ); // Calling admin_withdraw should fail as contract has not been terminated. admin_withdraw(admin, contract_address); @@ -3063,13 +3283,12 @@ module supra_framework::vesting_without_staking { ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address]); - let contract_address = - setup_vesting_contract( - admin, - &vector[@1, @2], - &vector[GRANT_AMOUNT, GRANT_AMOUNT], - admin_address, - ); + let contract_address = setup_vesting_contract( + admin, + &vector[@1, @2], + &vector[GRANT_AMOUNT, GRANT_AMOUNT], + admin_address, + ); set_beneficiary(admin, contract_address, @1, @11); } @@ -3080,13 +3299,12 @@ module supra_framework::vesting_without_staking { ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address]); - let contract_address = - setup_vesting_contract( - admin, - &vector[@1, @2], - &vector[GRANT_AMOUNT, GRANT_AMOUNT], - admin_address, - ); + let contract_address = setup_vesting_contract( + admin, + &vector[@1, @2], + &vector[GRANT_AMOUNT, GRANT_AMOUNT], + admin_address, + ); create_account_for_test(@11); set_beneficiary(admin, contract_address, @1, @11); } @@ -3097,13 +3315,12 @@ module supra_framework::vesting_without_staking { ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address, @11]); - let contract_address = - setup_vesting_contract( - admin, - &vector[@1], - &vector[GRANT_AMOUNT], - admin_address, - ); + let contract_address = setup_vesting_contract( + admin, + &vector[@1], + &vector[GRANT_AMOUNT], + admin_address, + ); set_beneficiary(admin, contract_address, @1, @11); assert!(beneficiary(contract_address, @1) == @11, 0); @@ -3124,13 +3341,12 @@ module supra_framework::vesting_without_staking { ) acquires AdminStore, VestingAccountManagement, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address]); - let contract_address = - setup_vesting_contract( - admin, - &vector[@11], - &vector[GRANT_AMOUNT], - admin_address, - ); + let contract_address = setup_vesting_contract( + admin, + &vector[@11], + &vector[GRANT_AMOUNT], + admin_address, + ); let role = utf8(b"RANDOM"); set_management_role(admin, contract_address, role, @12); assert!(get_role_holder(contract_address, role) == @12, 0); @@ -3147,13 +3363,12 @@ module supra_framework::vesting_without_staking { supra_framework, vector[admin_address, @11, @12], ); - let contract_address = - setup_vesting_contract( - admin, - &vector[@11], - &vector[GRANT_AMOUNT], - admin_address, - ); + let contract_address = setup_vesting_contract( + admin, + &vector[@11], + &vector[GRANT_AMOUNT], + admin_address, + ); set_beneficiary(admin, contract_address, @11, @12); assert!(beneficiary(contract_address, @11) == @12, 0); @@ -3189,13 +3404,12 @@ module supra_framework::vesting_without_staking { supra_framework, vector[admin_address, @11, @12], ); - let contract_address = - setup_vesting_contract( - admin, - &vector[@11], - &vector[GRANT_AMOUNT], - admin_address, - ); + let contract_address = setup_vesting_contract( + admin, + &vector[@11], + &vector[GRANT_AMOUNT], + admin_address, + ); set_beneficiary(admin, contract_address, @11, @12); assert!(beneficiary(contract_address, @11) == @12, 0); @@ -3222,13 +3436,12 @@ module supra_framework::vesting_without_staking { ) acquires AdminStore, VestingAccountManagement, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address, @11]); - let contract_address = - setup_vesting_contract( - admin, - &vector[@11], - &vector[GRANT_AMOUNT], - admin_address, - ); + let contract_address = setup_vesting_contract( + admin, + &vector[@11], + &vector[GRANT_AMOUNT], + admin_address, + ); // Reset the beneficiary with a random account. This should failed. set_beneficiary_resetter(admin, contract_address, signer::address_of(resetter)); @@ -3244,13 +3457,12 @@ module supra_framework::vesting_without_staking { supra_framework, vector[admin_address, @11, @12], ); - let contract_address = - setup_vesting_contract( - admin, - &vector[@11], - &vector[GRANT_AMOUNT], - admin_address, - ); + let contract_address = setup_vesting_contract( + admin, + &vector[@11], + &vector[GRANT_AMOUNT], + admin_address, + ); // Confirm that the lookup returns the same address when a shareholder is // passed for which there is no beneficiary. @@ -3298,12 +3510,13 @@ module supra_framework::vesting_without_staking { supra_framework, vector[admin_address, withdrawal_address, shareholder_address], ); - let contract_address = setup_vesting_contract( - admin, shareholders, shares, withdrawal_address - ); + let contract_address = + setup_vesting_contract( + admin, shareholders, shares, withdrawal_address + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount = 0; @@ -3322,7 +3535,7 @@ module supra_framework::vesting_without_staking { timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 9, + * 9, ); vest(contract_address); vested_amount = shareholder_share; @@ -3347,12 +3560,13 @@ module supra_framework::vesting_without_staking { supra_framework, vector[admin_address, withdrawal_address, shareholder_address], ); - let contract_address = setup_vesting_contract( - admin, shareholders, shares, withdrawal_address - ); + let contract_address = + setup_vesting_contract( + admin, shareholders, shares, withdrawal_address + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount = 0; @@ -3371,7 +3585,7 @@ module supra_framework::vesting_without_staking { timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 9, + * 9, ); vest(contract_address); vested_amount = shareholder_share; @@ -3396,12 +3610,13 @@ module supra_framework::vesting_without_staking { supra_framework, vector[admin_address, withdrawal_address, shareholder_address], ); - let contract_address = setup_vesting_contract( - admin, shareholders, shares, withdrawal_address - ); + let contract_address = + setup_vesting_contract( + admin, shareholders, shares, withdrawal_address + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount = 0; @@ -3424,7 +3639,7 @@ module supra_framework::vesting_without_staking { timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 9, + * 9, ); vest(contract_address); vested_amount = shareholder_share; @@ -3449,17 +3664,18 @@ module supra_framework::vesting_without_staking { supra_framework, vector[admin_address, withdrawal_address, shareholder_address], ); - let contract_address = setup_vesting_contract_with_schedule( - admin, - shareholders, - shares, - withdrawal_address, - &vector[2, 3, 1], - 10, - ); + let contract_address = + setup_vesting_contract_with_schedule( + admin, + shareholders, + shares, + withdrawal_address, + &vector[2, 3, 1], + 10, + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount = 0; @@ -3470,7 +3686,7 @@ module supra_framework::vesting_without_staking { // Time is now at the start time, vest will unlock the first period, which is 2/10. timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 2, + * 2, ); vest(contract_address); vested_amount = vested_amount + fraction(shareholder_share, 5, 10); @@ -3496,17 +3712,18 @@ module supra_framework::vesting_without_staking { supra_framework, vector[admin_address, withdrawal_address, shareholder_address], ); - let contract_address = setup_vesting_contract_with_schedule( - admin, - shareholders, - shares, - withdrawal_address, - &vector[2, 3, 1], - 10, - ); + let contract_address = + setup_vesting_contract_with_schedule( + admin, + shareholders, + shares, + withdrawal_address, + &vector[2, 3, 1], + 10, + ); assert!( vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, + 1, 0, ); let vested_amount = 0; @@ -3519,7 +3736,7 @@ module supra_framework::vesting_without_staking { // Time is now at the start time, vest will unlock the first period, which is 2/10. timestamp::update_global_time_for_test_secs( vesting_start_secs(contract_address) + period_duration_secs(contract_address) - * 4, + * 4, ); vest(contract_address); vested_amount = vested_amount + fraction(shareholder_share, 7, 10); @@ -3560,14 +3777,15 @@ module supra_framework::vesting_without_staking { let numerators: vector = vector[1]; // Create vesting contract with period_duration = 1, vesting_numerators = [1], vesting_denominator = 1 - let contract_address = setup_vesting_contract_with_amount_with_schedule( - admin, - shareholders, - shares, - withdrawal_address, - numerators, - 1, - ); + let contract_address = + setup_vesting_contract_with_amount_with_schedule( + admin, + shareholders, + shares, + withdrawal_address, + numerators, + 1, + ); set_vesting_schedule( admin, contract_address, @@ -3587,10 +3805,12 @@ module supra_framework::vesting_without_staking { vest_individual(contract_address, shareholder_2_address); // Assert both shareholders have received their full original amount - let (init_amount_1, left_amount_1, _) = - get_vesting_record(contract_address, shareholder_1_address); - let (init_amount_2, left_amount_2, _) = - get_vesting_record(contract_address, shareholder_2_address); + let (init_amount_1, left_amount_1, _) = get_vesting_record( + contract_address, shareholder_1_address + ); + let (init_amount_2, left_amount_2, _) = get_vesting_record( + contract_address, shareholder_2_address + ); assert!(left_amount_1 == 0, left_amount_1); assert!(left_amount_2 == 0, left_amount_2); @@ -3601,4 +3821,4 @@ module supra_framework::vesting_without_staking { assert!(balance_1 == shareholder_1_share, balance_1); assert!(balance_2 == shareholder_2_share, balance_2); } -} +} \ No newline at end of file diff --git a/aptos-move/framework/supra-framework/tests/automation_registry_tests.move b/aptos-move/framework/supra-framework/tests/automation_registry_tests.move index 2743f509df2..971e111d9ea 100644 --- a/aptos-move/framework/supra-framework/tests/automation_registry_tests.move +++ b/aptos-move/framework/supra-framework/tests/automation_registry_tests.move @@ -12,7 +12,7 @@ module std::automation_registry_tests { use supra_framework::multisig_account; use supra_framework::automation_registry::{ check_task_priority, check_cycle_state_and_duration, check_next_task_index_to_be_processed, - calculate_automation_fee_multiplier_for_committed_occupancy, AutomationRegistryConfigV2, + calculate_automation_fee_multiplier_for_committed_occupancy, AutomationRegistryConfigV2, check_locked_fee, }; use supra_framework::coin; use supra_framework::config_buffer; @@ -114,6 +114,8 @@ module std::automation_registry_tests { const EREGISTRY_SYSTEM_MAX_GAS_CAP_NON_ZERO: u64 = 46; /// The input address is not identified as multisig account. const EUNKNOWN_MULTISIG_ADDRESS: u64 = 47; + /// Supra automation v2.1 feature is not enabled. + const EDISABLED_AUTOMATION_V2_1_FEATURE: u64 = 49; /// Constants describing CYCLE state. /// State transition flow is: @@ -2841,11 +2843,12 @@ module std::automation_registry_tests { }); // 0.002 (*4) - automation_epoch_fee_per_second, 7200 epoch duration - let expected_automation_fee = 4 * (max_gas_amount * EPOCH_INTERVAL_FOR_TEST_IN_SECS / 100000); - expected_current_balance = expected_current_balance - expected_automation_fee; - expected_registry_balance = expected_registry_balance + expected_automation_fee; - check_account_balance(user_account, expected_current_balance ); - check_account_balance( registry_fee_address, expected_registry_balance ); + let expected_automation_fees = 4 * (max_gas_amount * EPOCH_INTERVAL_FOR_TEST_IN_SECS / 100000); + expected_current_balance = expected_current_balance - expected_automation_fees; + expected_registry_balance = expected_registry_balance + expected_automation_fees; + check_account_balance(user_account, expected_current_balance); + check_account_balance(registry_fee_address, expected_registry_balance); + check_locked_fee(expected_automation_fees); timestamp::update_global_time_for_test_secs( EPOCH_INTERVAL_FOR_TEST_IN_SECS + (EPOCH_INTERVAL_FOR_TEST_IN_SECS / 2) @@ -2869,6 +2872,8 @@ module std::automation_registry_tests { expected_registry_balance = expected_registry_balance - expected_refund; check_account_balance(user_account, expected_current_balance); check_account_balance(registry_fee_address, expected_registry_balance); + // locked cycle fees are deducted by the full cycle fee amount for the user + check_locked_fee((expected_automation_fees * 3) / 4); // Add and stop the task in the same epoch. Task index will be 4 assert!(automation_registry::get_next_task_index() == 4, 1); @@ -2903,6 +2908,8 @@ module std::automation_registry_tests { expected_refund = automation_fee_cap / REFUND_FACTOR; check_account_balance(user_account, expected_current_balance + expected_refund); check_account_balance(registry_fee_address, expected_registry_balance - expected_refund); + // As long as the task was not active, no locked fee for it will be unlocked + check_locked_fee((expected_automation_fees * 3) / 4); } #[test(framework = @supra_framework, user = @0x1cafe, user2 = @0x1cafa)] @@ -4048,58 +4055,78 @@ module std::automation_registry_tests { initialize_registry_test(framework, user); let (multisig_address, multisig_signer) = setup_multisig_account(framework, user); automation_registry::grant_authorization(framework, multisig_address); + let max_gas_amount = 10; let _ = automation_registry::register_system_task_with_state( &multisig_signer, - 10, + max_gas_amount, 86400, ACTIVE ); let _ = automation_registry::register_system_task_with_state( &multisig_signer, - 10, + max_gas_amount, 86400, ACTIVE ); - // check account balances after registration + // check account balances after registration, no charges are expected let registry_fee_address = automation_registry::get_registry_fee_address(); let user_address = address_of(user); check_account_balance(user_address, ACCOUNT_BALANCE); check_account_balance(multisig_address, ACCOUNT_BALANCE); check_account_balance(registry_fee_address, REGISTRY_DEFAULT_BALANCE); - assert!(20 == automation_registry::get_system_gas_committed_for_next_cycle(), 1); + assert!((2 * max_gas_amount) == automation_registry::get_system_gas_committed_for_next_cycle(), 1); let active_task_ids = automation_registry::get_active_task_ids(); let expected_ids = vector[0, 1]; vector::for_each(expected_ids, |task_index| { assert!(vector::contains(&active_task_ids, &task_index), 1); }); - // Cancel task 2. The committed gas for the next epoch will be updated, + let system_task_ids = automation_registry::get_system_task_indexes(); + vector::for_each(expected_ids, |task_index| { + assert!(vector::contains(&system_task_ids, &task_index), 1); + }); + // Cancel second registered task . The committed gas for the next cycle by system tasks will be updated, // but when requested active task it will be still available in the list automation_registry::cancel_system_task(&multisig_signer, 1); // Task will be still available in the registry but with cancelled state automation_registry::check_task_state(1, true, CANCELLED); - assert!(10 == automation_registry::get_system_gas_committed_for_next_cycle(), 1); + assert!(max_gas_amount == automation_registry::get_system_gas_committed_for_next_cycle(), 1); let active_task_ids = automation_registry::get_active_task_ids(); vector::for_each(expected_ids, |task_index| { assert!(vector::contains(&active_task_ids, &task_index), 1); + }); + let system_task_ids = automation_registry::get_system_task_indexes(); + vector::for_each(expected_ids, |task_index| { + assert!(vector::contains(&system_task_ids, &task_index), 1); }); - // Add and cancel the task in the same epoch. Task index will be 4 + // Add and cancel the task in the same cycle. Task index will be 2 assert!(automation_registry::get_next_task_index() == 2, 1); automation_registry::register_system_task_with_state(&multisig_signer, 10, 86400, PENDING, ); + let expected_system_ids = vector[0, 1, 2]; + let system_task_ids = automation_registry::get_system_task_indexes(); + vector::for_each(expected_ids, |task_index| { + assert!(vector::contains(&system_task_ids, &task_index), 1); + }); automation_registry::cancel_system_task(&multisig_signer, 2); - assert!(10 == automation_registry::get_system_gas_committed_for_next_cycle(), 1); + assert!(max_gas_amount == automation_registry::get_system_gas_committed_for_next_cycle(), 1); let active_task_ids = automation_registry::get_active_task_ids(); vector::for_each(expected_ids, |task_index| { assert!(vector::contains(&active_task_ids, &task_index), 1); }); + let expected_system_ids = vector[0, 1]; + let system_task_ids = automation_registry::get_system_task_indexes(); + vector::for_each(expected_ids, |task_index| { + assert!(vector::contains(&system_task_ids, &task_index), 1); + }); + // there is no task with index 2 and the next task index will be 3. assert!(!automation_registry::has_task_with_id(2), 1); assert!(automation_registry::get_next_task_index() == 3, 1); @@ -4202,7 +4229,7 @@ module std::automation_registry_tests { } #[test(framework = @supra_framework, user = @0x1caff)] - fun check_system_task_successful_stopped( + fun check_system_task_successfully_stopped( framework: &signer, user: &signer ) { @@ -4259,7 +4286,12 @@ module std::automation_registry_tests { assert!(vector::contains(&active_task_ids, &task_index), 2); }); - // 0.002 (*4) - automation_epoch_fee_per_second, 7200 epoch duration + let system_task_ids = automation_registry::get_system_task_indexes(); + vector::for_each(expected_ids, |task_index| { + assert!(vector::contains(&active_task_ids, &task_index), 2); + }); + + // No fees are charged check_account_balance( multisig_address, ACCOUNT_BALANCE ); check_account_balance(user_account, ACCOUNT_BALANCE ); check_account_balance( registry_fee_address, REGISTRY_DEFAULT_BALANCE ); @@ -4311,7 +4343,7 @@ module std::automation_registry_tests { assert!(automation_registry::get_next_task_index() == 5, 1); assert!(3 * max_gas_amount == automation_registry::get_system_gas_committed_for_next_cycle(), 1); - // Check balances after test execution + // Check balances after test execution, no fees are charged or refunded. check_account_balance(multisig_address, ACCOUNT_BALANCE); check_account_balance(user_account, ACCOUNT_BALANCE); check_account_balance(registry_fee_address, REGISTRY_DEFAULT_BALANCE); @@ -4396,4 +4428,128 @@ module std::automation_registry_tests { assert!(automation_registry::is_authorized_account(multisig_address2), 4); } + // ------------------------------------------------------------------------- + // Tests for register_without_validation (SUPRA_AUTOMATION_V2_1 feature) + // ------------------------------------------------------------------------- + + /// `register_without_validation` must abort with EDISABLED_AUTOMATION_V2_1_FEATURE when + /// SUPRA_AUTOMATION_V2_1 is not enabled. SUPRA_NATIVE_AUTOMATION and SUPRA_AUTOMATION_V2 + /// are both enabled by `initialize_registry_test`, but V2_1 is deliberately omitted. + #[test(supra_framework = @supra_framework, user = @0x1cafe)] + #[expected_failure(abort_code = EDISABLED_AUTOMATION_V2_1_FEATURE, location = automation_registry)] + fun test_register_without_validation_v2_1_feature_disabled( + supra_framework: &signer, + user: &signer, + ) { + initialize_registry_test(supra_framework, user); + toggle_custom_feature_flags( + supra_framework, + vector[features::get_supra_automation_v2_1_feature()], + false, + ); + // Expiry must be after the current time plus at least one cycle duration. + let expiry_time = EPOCH_INTERVAL_FOR_TEST_IN_SECS + 86400; + automation_registry::register_without_validation( + user, + PAYLOAD, + expiry_time, + 10_000, + 100, + 1_000, + AUX_DATA, + ); + } + + /// When SUPRA_AUTOMATION_V2_1 is enabled, `register_without_validation` calls + /// `get_txn_app_hash()` which requires a real user transaction context. In a Move unit + /// test that context does not exist, so the native function aborts with + /// error::invalid_state(ETRANSACTION_CONTEXT_NOT_AVAILABLE) = 196609. + #[test(supra_framework = @supra_framework, user = @0x1cafe)] + #[expected_failure(abort_code = 196609, location = supra_framework::transaction_context)] + fun test_register_without_validation_aborts_outside_txn_context( + supra_framework: &signer, + user: &signer, + ) { + initialize_registry_test(supra_framework, user); + // Enable V2_1 so the feature guard passes; the native should then abort because + // there is no real user transaction context in a unit test. + toggle_custom_feature_flags( + supra_framework, + vector[features::get_supra_automation_v2_1_feature()], + true, + ); + let expiry_time = EPOCH_INTERVAL_FOR_TEST_IN_SECS + 86400; + automation_registry::register_without_validation( + user, + PAYLOAD, + expiry_time, + 10_000, + 100, + 1_000, + AUX_DATA, + ); + } + + // ------------------------------------------------------------------------- + // Tests for register_system_task_without_validation (SUPRA_AUTOMATION_V2_1 feature) + // ------------------------------------------------------------------------- + + /// `register_system_task_without_validation` must abort with EDISABLED_AUTOMATION_V2_1_FEATURE + /// when SUPRA_AUTOMATION_V2_1 is not enabled. `initialize_registry_test` enables + /// SUPRA_NATIVE_AUTOMATION and SUPRA_AUTOMATION_V2 but deliberately omits V2_1. + /// The V2_1 guard fires before any authorization or registry logic is reached, so + /// the caller does not need to be an authorized multisig account for this test. + #[test(supra_framework = @supra_framework, user = @0x1cafe)] + #[expected_failure(abort_code = EDISABLED_AUTOMATION_V2_1_FEATURE, location = automation_registry)] + fun test_register_system_task_without_validation_v2_1_feature_disabled( + supra_framework: &signer, + user: &signer, + ) { + initialize_registry_test(supra_framework, user); + toggle_custom_feature_flags( + supra_framework, + vector[features::get_supra_automation_v2_1_feature()], + false, + ); + // V2_1 is not enabled, the function must abort immediately. + let expiry_time = EPOCH_INTERVAL_FOR_TEST_IN_SECS + 86400; + automation_registry::register_system_task_without_validation( + user, + PAYLOAD, + expiry_time, + 10_000, + SYS_AUX_DATA, + ); + } + + /// When SUPRA_AUTOMATION_V2_1 is enabled, `register_system_task_without_validation` calls + /// `transaction_context::get_transaction_consensus_hash()` to obtain the registering + /// transaction's consensus hash. That native requires a real user transaction context which + /// does not exist in a Move unit test, so the call aborts with + /// error::invalid_state(ETRANSACTION_CONTEXT_NOT_AVAILABLE) = 196609. + /// The abort happens before authorization or registry checks, so no multisig setup is needed. + #[test(supra_framework = @supra_framework, user = @0x1cafe)] + #[expected_failure(abort_code = 196609, location = supra_framework::transaction_context)] + fun test_register_system_task_without_validation_aborts_outside_txn_context( + supra_framework: &signer, + user: &signer, + ) { + initialize_registry_test(supra_framework, user); + // Enable V2_1 so the feature guard passes; the native consensus-hash getter then + // aborts because there is no real transaction context available in unit tests. + toggle_custom_feature_flags( + supra_framework, + vector[features::get_supra_automation_v2_1_feature()], + true, + ); + let expiry_time = EPOCH_INTERVAL_FOR_TEST_IN_SECS + 86400; + automation_registry::register_system_task_without_validation( + user, + PAYLOAD, + expiry_time, + 10_000, + SYS_AUX_DATA, + ); + } + } diff --git a/aptos-move/framework/supra-framework/tests/delegation_pool_integration_tests.move b/aptos-move/framework/supra-framework/tests/delegation_pool_integration_tests.move index bb3aa72a422..72a9636dc78 100644 --- a/aptos-move/framework/supra-framework/tests/delegation_pool_integration_tests.move +++ b/aptos-move/framework/supra-framework/tests/delegation_pool_integration_tests.move @@ -14,6 +14,7 @@ module supra_framework::delegation_pool_integration_tests { use supra_framework::reconfiguration; use supra_framework::pbo_delegation_pool as dp; use supra_framework::timestamp; + use supra_framework::validator_public_keys; #[test_only] const EPOCH_DURATION: u64 = 60; @@ -36,9 +37,6 @@ module supra_framework::delegation_pool_integration_tests { #[test_only] const MODULE_EVENT: u64 = 26; - #[test_only] - const CONSENSUS_KEY_1: vector = x"c1bd3bcb387e4ee9a909f6304a1c9902661b0ecfb1e148c7892b210c7f353dfd"; - #[test_only] public fun initialize_for_test(supra_framework: &signer) { initialize_for_test_custom( @@ -136,7 +134,11 @@ module supra_framework::delegation_pool_integration_tests { ); validator_address = dp::get_owned_pool_address(validator_address); - stake::rotate_consensus_key(validator, validator_address, CONSENSUS_KEY_1); + stake::rotate_consensus_key( + validator, + validator_address, + stake::generate_unique_consensus_pubkey_bytes() + ); if (amount > 0) { mint_and_add_stake(validator, amount); @@ -808,8 +810,11 @@ module supra_framework::delegation_pool_integration_tests { stake::assert_validator_state(validator_2_address, 100 * ONE_SUPRA, 0, 0, 0, 1); // Validator 1 rotates consensus key. Validator 2 leaves. Validator 3 joins. - let (_sk_1b, _, _) = generate_identity(); - stake::rotate_consensus_key(validator_1, validator_1_address, CONSENSUS_KEY_1); + stake::rotate_consensus_key( + validator_1, + validator_1_address, + stake::generate_unique_consensus_pubkey_bytes() + ); stake::leave_validator_set(validator_2, validator_2_address); stake::join_validator_set(validator_3, validator_3_address); // Validator 2 is not effectively removed until next epoch. @@ -876,11 +881,14 @@ module supra_framework::delegation_pool_integration_tests { assert!(coin::balance(signer::address_of(validator)) == 101 * ONE_SUPRA, 1); stake::assert_validator_state(pool_address, 0, 0, 0, 0, 0); - // Operator can separately rotate consensus key. - let (_sk_new, _, _) = generate_identity(); - stake::rotate_consensus_key(validator, pool_address, CONSENSUS_KEY_1); + // Operator can separately rotate consensus key. The submission carries an appended BLS + // multisig PoP, which the contract verifies and strips before storing the canonical key. + let new_consensus_key = stake::generate_unique_consensus_pubkey_bytes(); + stake::rotate_consensus_key(validator, pool_address, new_consensus_key); let (consensus_pubkey, _, _) = stake::get_validator_config(pool_address); - assert!(consensus_pubkey == CONSENSUS_KEY_1, 2); + let (expected_stored, _pop) = + validator_public_keys::split_consensus_key_and_pop(new_consensus_key); + assert!(consensus_pubkey == expected_stored, 2); // Operator can update network and fullnode addresses. stake::update_network_and_fullnode_addresses(validator, pool_address, b"1", b"2"); @@ -1114,7 +1122,11 @@ module supra_framework::delegation_pool_integration_tests { // Initialize validator config. let (_sk_new, _, _) = generate_identity(); - stake::rotate_consensus_key(validator, validator_address, CONSENSUS_KEY_1); + stake::rotate_consensus_key( + validator, + validator_address, + stake::generate_unique_consensus_pubkey_bytes() + ); // Join the validator set with enough stake. This now wouldn't fail since the validator config already exists. stake::join_validator_set(validator, validator_address); diff --git a/aptos-move/framework/supra-framework/tests/test_leader_ban_registry.move b/aptos-move/framework/supra-framework/tests/test_leader_ban_registry.move new file mode 100644 index 00000000000..f7458704dd5 --- /dev/null +++ b/aptos-move/framework/supra-framework/tests/test_leader_ban_registry.move @@ -0,0 +1,363 @@ +#[test_only] +module std::test_leader_ban_registry { + use std::bcs; + use std::option; + use std::vector; + use aptos_std::ed25519; + use supra_framework::validator_public_keys; + use supra_framework::supra_coin; + use supra_framework::coin; + use supra_framework::supra_coin::SupraCoin; + use supra_framework::stake; + use supra_framework::leader_ban_registry; + use supra_framework::leader_ban_registry_config; + use std::signer; + use supra_framework::account; + + fun setup_staking_modules( + sender: &signer, + validator_1: &signer, + validator_2: &signer, + validator_3: &signer, + validator_4: &signer + ) { + // initialise stake module + let (_v_1_s_key, v_1_p_key) = validator_public_keys::generate_keys(); + let (_v_2_s_key, v_2_p_key) = validator_public_keys::generate_keys(); + let (_v_3_s_key, v_3_p_key) = validator_public_keys::generate_keys(); + let (_v_4_s_key, v_4_p_key) = validator_public_keys::generate_keys(); + + stake::initialize_for_test(sender); + account::create_account_for_test(signer::address_of(validator_1)); + coin::register(validator_1); + supra_coin::mint(sender, signer::address_of(validator_1), 10000000000); + + account::create_account_for_test(signer::address_of(validator_2)); + coin::register(validator_2); + supra_coin::mint(sender, signer::address_of(validator_2), 10000000000); + + account::create_account_for_test(signer::address_of(validator_3)); + coin::register(validator_3); + supra_coin::mint(sender, signer::address_of(validator_3), 10000000000); + + account::create_account_for_test(signer::address_of(validator_4)); + coin::register(validator_4); + supra_coin::mint(sender, signer::address_of(validator_4), 10000000000); + + let active_coin = coin::withdraw(validator_1, 500); + let pending_coin = coin::withdraw(validator_1, 1000); + stake::create_stake_pool( + validator_1, + active_coin, + pending_coin, + 500000000 + ); + + let active_coin = coin::withdraw(validator_2, 500); + let pending_coin = coin::withdraw(validator_2, 1000); + stake::create_stake_pool( + validator_2, + active_coin, + pending_coin, + 500000000 + ); + + let active_coin = coin::withdraw(validator_3, 500); + let pending_coin = coin::withdraw(validator_3, 1000); + stake::create_stake_pool( + validator_3, + active_coin, + pending_coin, + 500000000 + ); + + let active_coin = coin::withdraw(validator_4, 500); + let pending_coin = coin::withdraw(validator_4, 1000); + stake::create_stake_pool( + validator_4, + active_coin, + pending_coin, + 500000000 + ); + + stake::join_validator_set_for_test( + &v_4_p_key, + validator_4, + signer::address_of(validator_4), + false + ); + stake::join_validator_set_for_test( + &v_3_p_key, + validator_3, + signer::address_of(validator_3), + false + ); + stake::join_validator_set_for_test( + &v_2_p_key, + validator_2, + signer::address_of(validator_2), + false + ); + stake::join_validator_set_for_test( + &v_1_p_key, + validator_1, + signer::address_of(validator_1), + true + ); // on epoch change + } + + #[ + test( + sender = @supra_framework, + validator_1 = @0xdead01, + validator_2 = @0xdead02, + validator_3 = @0xdead03, + validator_4 = @0xdead04 + ) + ] + fun test_ban_registy_e2e( + sender: &signer, + validator_1: &signer, + validator_2: &signer, + validator_3: &signer, + validator_4: &signer + ) { + // initialise ban registry config + let ban_params = leader_ban_registry_config::get_test_ban_registry_params_v0(); + let ban_config_bytes = bcs::to_bytes(&ban_params); + leader_ban_registry_config::initialize(sender, ban_config_bytes); + + // initialise ban registry + leader_ban_registry::initialize_leader_ban_registry(sender); + setup_staking_modules( + sender, + validator_1, + validator_2, + validator_3, + validator_4 + ); + + // ===== Part 1: Basic ban -> probation -> reinstatement ===== + // Config: initial_ban_duration=4, probation_duration=4, max_ban_duration=20, committee_size=4 + + // Round 0: No failures, registry empty + leader_ban_registry::update_ban_registry(0, 0, option::some(0), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + assert!(vector::length(&ban_registry) == 0, 1); + + // Round 1: Validator 2 (index 1) fails to propose -> banned + leader_ban_registry::update_ban_registry(0, 1, option::some(2), vector[1]); + let ban_registry = leader_ban_registry::get_ban_registry(); + assert!(vector::length(&ban_registry) == 1, 2); + assert!( + signer::address_of(validator_2) + == leader_ban_registry::get_pool_address_from_vp( + vector::borrow(&ban_registry, 0) + ), + 3 + ); + + // Round 4: Ban still active (duration=4, rounds_served=3, remaining=1) + leader_ban_registry::update_ban_registry(0, 4, option::some(2), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + assert!(vector::length(&ban_registry) == 1, 4); + let vp = vector::borrow(&ban_registry, 0); + assert!(!leader_ban_registry::is_on_probation_from_vp(vp), 100); + + // Round 5: Ban expires (rounds_served=4), transitions to probation + leader_ban_registry::update_ban_registry(0, 5, option::some(2), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + assert!(vector::length(&ban_registry) == 1, 5); // Still in registry (on probation) + let vp = vector::borrow(&ban_registry, 0); + assert!(leader_ban_registry::is_on_probation_from_vp(vp), 101); + + // Round 9: Probation expires (rounds_served=4), fully reinstated + leader_ban_registry::update_ban_registry(0, 9, option::some(2), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + assert!(vector::length(&ban_registry) == 0, 6); + + // ===== Part 2: Consecutive bans via re-ban during probation ===== + + // Round 12: Validator 1 (index 0) fails -> banned, consecutive=0, duration=4 + leader_ban_registry::update_ban_registry(0, 12, option::some(1), vector[0]); + let ban_registry = leader_ban_registry::get_ban_registry(); + let vp = vector::borrow(&ban_registry, 0); + assert!( + signer::address_of(validator_1) + == leader_ban_registry::get_pool_address_from_vp(vp), + 7 + ); + assert!(leader_ban_registry::get_consecutive_count_from_vp(vp) == 0, 8); + + // Round 16: Ban expires (duration=4) -> probation + leader_ban_registry::update_ban_registry(0, 16, option::some(1), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + let vp = vector::borrow(&ban_registry, 0); + assert!(leader_ban_registry::is_on_probation_from_vp(vp), 102); + + // Round 17: Re-ban during probation -> consecutive=1, duration=8 + leader_ban_registry::update_ban_registry(0, 17, option::some(1), vector[0]); + let ban_registry = leader_ban_registry::get_ban_registry(); + let vp = vector::borrow(&ban_registry, 0); + assert!(leader_ban_registry::get_consecutive_count_from_vp(vp) == 1, 9); + assert!(!leader_ban_registry::is_on_probation_from_vp(vp), 103); + assert!(vector::length(&ban_registry) == 1, 10); + + // Round 25: Ban expires (duration=8) -> probation + leader_ban_registry::update_ban_registry(0, 25, option::some(1), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + let vp = vector::borrow(&ban_registry, 0); + assert!(leader_ban_registry::is_on_probation_from_vp(vp), 104); + + // Round 26: Re-ban during probation -> consecutive=2, duration=16 + leader_ban_registry::update_ban_registry(0, 26, option::some(1), vector[0]); + let ban_registry = leader_ban_registry::get_ban_registry(); + let vp = vector::borrow(&ban_registry, 0); + assert!(leader_ban_registry::get_consecutive_count_from_vp(vp) == 2, 11); + assert!(!leader_ban_registry::is_on_probation_from_vp(vp), 105); + assert!(vector::length(&ban_registry) == 1, 12); + + // Round 42: Ban expires (duration=16) -> probation + leader_ban_registry::update_ban_registry(0, 42, option::some(1), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + let vp = vector::borrow(&ban_registry, 0); + assert!(leader_ban_registry::is_on_probation_from_vp(vp), 106); + + // Round 43: Re-ban during probation -> consecutive=3, duration=min(32,20)=20 + leader_ban_registry::update_ban_registry(0, 43, option::some(1), vector[0]); + let ban_registry = leader_ban_registry::get_ban_registry(); + let vp = vector::borrow(&ban_registry, 0); + assert!(leader_ban_registry::get_consecutive_count_from_vp(vp) == 3, 13); + assert!(!leader_ban_registry::is_on_probation_from_vp(vp), 107); + assert!(vector::length(&ban_registry) == 1, 14); + + // Round 63: Ban expires (duration=20) -> probation + leader_ban_registry::update_ban_registry(0, 63, option::some(1), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + let vp = vector::borrow(&ban_registry, 0); + assert!(leader_ban_registry::is_on_probation_from_vp(vp), 108); + + // Round 64: Re-ban during probation -> consecutive=4, duration=min(64,20)=20 + leader_ban_registry::update_ban_registry(0, 64, option::some(1), vector[0]); + let ban_registry = leader_ban_registry::get_ban_registry(); + let vp = vector::borrow(&ban_registry, 0); + assert!(leader_ban_registry::get_consecutive_count_from_vp(vp) == 4, 15); + assert!(!leader_ban_registry::is_on_probation_from_vp(vp), 109); + assert!(vector::length(&ban_registry) == 1, 16); + + // ===== Part 3: Natural expiry of max-duration ban ===== + // Ban at round 64 with consecutive=4, duration=20 + // Ban expires at round 84, probation starts at 84, probation expires at 88 + + // At round 83, the ban should still be active (1 round remaining) + leader_ban_registry::update_ban_registry(0, 83, option::some(1), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + assert!(vector::length(&ban_registry) == 1, 17); + let vp = vector::borrow(&ban_registry, 0); + assert!(!leader_ban_registry::is_on_probation_from_vp(vp), 110); // Still banned + + // At round 84, the ban expires and validator transitions to probation + leader_ban_registry::update_ban_registry(0, 84, option::some(1), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + assert!(vector::length(&ban_registry) == 1, 18); // Still in registry (on probation) + let vp = vector::borrow(&ban_registry, 0); + assert!(leader_ban_registry::is_on_probation_from_vp(vp), 111); // Now on probation + + // At round 87, probation should still be active (1 round remaining) + leader_ban_registry::update_ban_registry(0, 87, option::some(1), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + assert!(vector::length(&ban_registry) == 1, 19); + let vp = vector::borrow(&ban_registry, 0); + assert!(leader_ban_registry::is_on_probation_from_vp(vp), 112); + + // At round 88, probation expires and validator is fully reinstated + leader_ban_registry::update_ban_registry(0, 88, option::some(1), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + assert!(vector::length(&ban_registry) == 0, 20); // Fully removed from registry + + // ===== Part 4: Multi-validator banning with proposer limit ===== + // Now lets try to fail 3 of them + leader_ban_registry::update_ban_registry(0, 90, option::some(3), vector[0, 1, 2]); + let ban_registry = leader_ban_registry::get_ban_registry(); + // only 2 will be banned because of proposer limit of 2 + assert!(vector::length(&ban_registry) == 2, 21); + + // Re-ban both validators to increase consecutive count + // Round 94: re-ban, consecutive_bans=1, duration=8, resets from round 94 + leader_ban_registry::update_ban_registry( + 0, 90 + (4 * 1), option::some(2), vector[0, 1] + ); + // Round 98: re-ban, consecutive_bans=2, duration=16, resets from round 98 + leader_ban_registry::update_ban_registry( + 0, 90 + (4 * 2), option::some(2), vector[0, 1] + ); + + // ===== Part 5: Cross-epoch ban management ===== + // Now test ban expiry across epoch change WITHOUT re-banning + // Bans were set at rounds 95/96 (consecutive=2, duration=16) + // First trigger epoch change + leader_ban_registry::on_new_epoch(); + + // In epoch 1, advance rounds without re-banning to let the ban expire naturally + // For validators banned at epoch 0 rounds 95/96: + // After on_new_epoch: rounds_served_in_previous_epochs = 3/2 + // (latest_view.round 98 - round_earned 95/96) + + // At epoch 1 round 0, ban should still be active (rounds_served = 3/2 + 0, need 16) + leader_ban_registry::update_ban_registry(1, 0, option::some(2), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + assert!(vector::length(&ban_registry) == 2, 22); + let vp = vector::borrow(&ban_registry, 0); + assert!(!leader_ban_registry::is_on_probation_from_vp(vp), 113); + + // At epoch 1 round 12, ban should still be active (rounds_served = 3+12=15/2+12=14, need 16) + leader_ban_registry::update_ban_registry(1, 12, option::some(2), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + assert!(vector::length(&ban_registry) == 2, 23); + + // At epoch 1 round 14, ban expires and validators transition to probation + // (rounds_served = 3+14=17/2+14=16 >= 16) + leader_ban_registry::update_ban_registry(1, 14, option::some(2), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + assert!(vector::length(&ban_registry) == 2, 24); // Still in registry (on probation) + let vp = vector::borrow(&ban_registry, 0); + assert!(leader_ban_registry::is_on_probation_from_vp(vp), 114); + + // At epoch 1 round 17, probation still active (17-14=3 < 4, 1 round remaining) + leader_ban_registry::update_ban_registry(1, 17, option::some(2), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + assert!(vector::length(&ban_registry) == 2, 25); + + // At epoch 1 round 18, probation expires and validators are fully reinstated + // (18-14=4 >= 4) + leader_ban_registry::update_ban_registry(1, 18, option::some(2), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + assert!(vector::length(&ban_registry) == 0, 26); + + // ===== Part 6: Re-ban during probation ===== + // Test: Re-banning during probation should increase consecutive count + // Ban validator 1 fresh (prev_round=18, so failed_round=19=current_round) + leader_ban_registry::update_ban_registry(1, 19, option::some(2), vector[0]); + let ban_registry = leader_ban_registry::get_ban_registry(); + assert!(vector::length(&ban_registry) == 1, 27); + let vp = vector::borrow(&ban_registry, 0); + assert!(leader_ban_registry::get_consecutive_count_from_vp(vp) == 0, 115); + assert!(!leader_ban_registry::is_on_probation_from_vp(vp), 116); + + // Ban duration = 4 rounds, ban earned at round 19, so ban expires at round 23 + // Transition to probation at round 23 + leader_ban_registry::update_ban_registry(1, 23, option::some(2), vector::empty()); + let ban_registry = leader_ban_registry::get_ban_registry(); + let vp = vector::borrow(&ban_registry, 0); + assert!(leader_ban_registry::is_on_probation_from_vp(vp), 117); + assert!(leader_ban_registry::get_consecutive_count_from_vp(vp) == 0, 118); + + // Re-ban during probation should increase consecutive count and reset to banned state + leader_ban_registry::update_ban_registry(1, 24, option::some(2), vector[0]); + let ban_registry = leader_ban_registry::get_ban_registry(); + let vp = vector::borrow(&ban_registry, 0); + assert!(leader_ban_registry::get_consecutive_count_from_vp(vp) == 1, 119); // Consecutive count increased + assert!(!leader_ban_registry::is_on_probation_from_vp(vp), 120); // Back to banned state + + } +} diff --git a/aptos-move/framework/supra-framework/tests/test_leader_ban_registry_config.move b/aptos-move/framework/supra-framework/tests/test_leader_ban_registry_config.move new file mode 100644 index 00000000000..80839a1aeb7 --- /dev/null +++ b/aptos-move/framework/supra-framework/tests/test_leader_ban_registry_config.move @@ -0,0 +1,125 @@ +#[test_only] +module supra_framework::test_leader_ban_registry_config { + use std::bcs; + use std::vector; + use supra_framework::config_buffer; + use supra_framework::leader_ban_registry_config; + + #[test(sender = @0xdead)] + #[expected_failure(abort_code = 0x50003, location = supra_framework::system_addresses)] + // signer is not valid + fun test_signer(sender: &signer) { + let ban_registry_param = + leader_ban_registry_config::get_test_ban_registry_params_v0(); + let config_bytes = bcs::to_bytes(&ban_registry_param); + leader_ban_registry_config::initialize(sender, config_bytes); + } + + #[test(sender = @supra_framework)] + #[ + expected_failure( + abort_code = 0x10001, location = supra_framework::leader_ban_registry_config + ) + ] + // Invalid config bytes + fun test_empty_config_value(sender: &signer) { + let config_bytes = vector::empty(); + leader_ban_registry_config::initialize(sender, config_bytes); + } + + #[test(sender = @supra_framework)] + #[ + expected_failure( + abort_code = 0x10003, location = supra_framework::leader_ban_registry_config + ) + ] + // Invalid version bytes + fun test_invalid_config_value(sender: &signer) { + let ban_registry_param = + leader_ban_registry_config::get_test_ban_registry_params_v0(); + let config_bytes = bcs::to_bytes(&ban_registry_param); + vector::push_back(&mut config_bytes, 0); + leader_ban_registry_config::initialize(sender, config_bytes); + } + + public fun init_ban_registry_params(sender: &signer) { + let ban_registry_param = + leader_ban_registry_config::get_test_ban_registry_params_v0(); + let config_bytes = bcs::to_bytes(&ban_registry_param); + leader_ban_registry_config::initialize(sender, config_bytes); + } + + #[test(sender = @supra_framework)] + public fun test_init_config_value(sender: &signer) { + init_ban_registry_params(sender); + assert!(leader_ban_registry_config::check_ban_registry_params_exist(sender), 1); + assert!( + leader_ban_registry_config::check_ban_registry_params_v0_exist(sender), 2 + ); + } + + #[test(sender = @supra_framework)] + #[ + expected_failure( + abort_code = 0x80004, location = supra_framework::leader_ban_registry_config + ) + ] + // Already initialised + fun test_init_config_value_reinit(sender: &signer) { + init_ban_registry_params(sender); + init_ban_registry_params(sender); + } + + #[test(sender = @supra_framework)] + fun test_on_epoch_change(sender: &signer) { + config_buffer::initialize(sender); + assert!( + !leader_ban_registry_config::check_ban_registry_params_exist(sender), 1 + ); + let ban_registry_param = + leader_ban_registry_config::get_test_ban_registry_params_v0(); + let config_bytes = bcs::to_bytes(&ban_registry_param); + leader_ban_registry_config::set_for_next_epoch(sender, config_bytes, 0); + leader_ban_registry_config::on_new_epoch(sender); + assert!(leader_ban_registry_config::check_ban_registry_params_exist(sender), 1); + assert!( + leader_ban_registry_config::check_ban_registry_params_v0_exist(sender), 2 + ); + + let updated_initial_e_denied = 3; + let updated_max_e_denied = 8; + let updated_minimum_u_proposers = 6; + let updated_probation_elections = 2; + + let ban_registry_param = + leader_ban_registry_config::get_custom_ban_registry_params_v0( + updated_initial_e_denied, + updated_max_e_denied, + updated_minimum_u_proposers, + updated_probation_elections + ); + let config_bytes = bcs::to_bytes(&ban_registry_param); + leader_ban_registry_config::set_for_next_epoch(sender, config_bytes, 0); + leader_ban_registry_config::on_new_epoch(sender); + assert!( + leader_ban_registry_config::get_initial_elections_denied() + == updated_initial_e_denied, + 3 + ); + assert!( + leader_ban_registry_config::get_max_elections_denied() + == updated_max_e_denied, + 4 + ); + assert!( + leader_ban_registry_config::get_minimum_unbanned_proposers() + == updated_minimum_u_proposers, + 5 + ); + assert!( + leader_ban_registry_config::get_probation_elections() + == updated_probation_elections, + 6 + ); + } +} diff --git a/aptos-move/framework/supra-stdlib/doc/class_groups.md b/aptos-move/framework/supra-stdlib/doc/class_groups.md new file mode 100644 index 00000000000..fb1f8c1c884 --- /dev/null +++ b/aptos-move/framework/supra-stdlib/doc/class_groups.md @@ -0,0 +1,125 @@ + + + +# Module `0x1::class_groups` + + + +- [Struct `CGPublicKey`](#0x1_class_groups_CGPublicKey) +- [Function `public_key_from_bytes`](#0x1_class_groups_public_key_from_bytes) +- [Function `public_key_to_bytes`](#0x1_class_groups_public_key_to_bytes) +- [Function `validate_pubkey_internal`](#0x1_class_groups_validate_pubkey_internal) + + +
use 0x1::option;
+
+ + + + + +## Struct `CGPublicKey` + + + +
struct CGPublicKey has copy, drop, store
+
+ + + +
+Fields + + +
+
+bytes: vector<u8> +
+
+ +
+
+ + +
+ + + +## Function `public_key_from_bytes` + +Creates a new public key from a sequence of bytes. + + +
public fun public_key_from_bytes(bytes: vector<u8>): option::Option<class_groups::CGPublicKey>
+
+ + + +
+Implementation + + +
public fun public_key_from_bytes(bytes: vector<u8>): Option<CGPublicKey> {
+    if (validate_pubkey_internal(bytes)) {
+        option::some(CGPublicKey {
+            bytes
+        })
+    } else {
+        option::none<CGPublicKey>()
+    }
+}
+
+ + + +
+ + + +## Function `public_key_to_bytes` + +Serializes a public key to a sequence of bytes. + + +
public fun public_key_to_bytes(pk: &class_groups::CGPublicKey): vector<u8>
+
+ + + +
+Implementation + + +
public fun public_key_to_bytes(pk: &CGPublicKey): vector<u8> {
+    pk.bytes
+}
+
+ + + +
+ + + +## Function `validate_pubkey_internal` + + + +
fun validate_pubkey_internal(public_key: vector<u8>): bool
+
+ + + +
+Implementation + + +
native fun validate_pubkey_internal(public_key: vector<u8>): bool;
+
+ + + +
+ + +[move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/supra-stdlib/doc/consensus_key.md b/aptos-move/framework/supra-stdlib/doc/consensus_key.md new file mode 100644 index 00000000000..1476c49c921 --- /dev/null +++ b/aptos-move/framework/supra-stdlib/doc/consensus_key.md @@ -0,0 +1,285 @@ + + + +# Module `0x1::consensus_key` + + + +- [Struct `ConsensusPublicKey`](#0x1_consensus_key_ConsensusPublicKey) +- [Constants](#@Constants_0) +- [Function `consensus_public_key_from_bytes`](#0x1_consensus_key_consensus_public_key_from_bytes) +- [Function `public_key_to_bytes`](#0x1_consensus_key_public_key_to_bytes) +- [Function `get_bls_pub_key`](#0x1_consensus_key_get_bls_pub_key) +- [Function `get_ed_key`](#0x1_consensus_key_get_ed_key) +- [Function `get_cg_key`](#0x1_consensus_key_get_cg_key) + + +
use 0x1::bls12381;
+use 0x1::class_groups;
+use 0x1::ed25519;
+use 0x1::error;
+use 0x1::option;
+use 0x1::vector;
+
+ + + + + +## Struct `ConsensusPublicKey` + +Consensus public key consists of: +1. Ed25519 key +2. Bls12381 G1 key +3. Class group encryption key + + +
struct ConsensusPublicKey has copy, drop, store
+
+ + + +
+Fields + + +
+
+ed_key: ed25519::ValidatedPublicKey +
+
+ +
+
+bls_key: option::Option<bls12381::PublicKey> +
+
+ +
+
+cg_key: option::Option<class_groups::CGPublicKey> +
+
+ +
+
+ + +
+ + + +## Constants + + + + +Wrong number of bytes were given as input when deserializing an consensus public key. + + +
const E_WRONG_PUBKEY_SIZE: u64 = 1;
+
+ + + + + +The size of a serialized bls12381 G1 public key, in bytes. + + +
const BLS12381_G1_PUBLIC_KEY_NUM_BYTES: u64 = 48;
+
+ + + + + +The size of a serialized ed25519 public key, in bytes. + + +
const ED25519_PUBLIC_KEY_NUM_BYTES: u64 = 32;
+
+ + + + + +Invalid consensus public key + + +
const EINVALID_PUBLIC_KEY: u64 = 2;
+
+ + + + + +## Function `consensus_public_key_from_bytes` + + + +
public fun consensus_public_key_from_bytes(bytes: vector<u8>): option::Option<consensus_key::ConsensusPublicKey>
+
+ + + +
+Implementation + + +
public fun consensus_public_key_from_bytes(bytes: vector<u8>): Option<ConsensusPublicKey>{
+    //todo: pop for ed and bls
+    if (vector::length(&bytes) == ED25519_PUBLIC_KEY_NUM_BYTES){
+        let ed_key_bytes = vector::slice(&bytes, 0, ED25519_PUBLIC_KEY_NUM_BYTES);
+        let valid_ed_public_key = ed25519::new_validated_public_key_from_bytes(ed_key_bytes);
+        assert!(option::is_some(&valid_ed_public_key), error::invalid_argument(EINVALID_PUBLIC_KEY));
+        option::some(ConsensusPublicKey {
+            ed_key: option::extract(&mut valid_ed_public_key),
+            bls_key: option::none<bls12381::PublicKey>(),
+            cg_key: option::none<class_groups::CGPublicKey>()
+        })
+    }
+    else if (vector::length(&bytes) > ED25519_PUBLIC_KEY_NUM_BYTES + BLS12381_G1_PUBLIC_KEY_NUM_BYTES){
+
+        let ed_key_bytes = vector::slice(&bytes, 0, ED25519_PUBLIC_KEY_NUM_BYTES);
+        let bls_key_bytes = vector::slice(&bytes, ED25519_PUBLIC_KEY_NUM_BYTES, ED25519_PUBLIC_KEY_NUM_BYTES + BLS12381_G1_PUBLIC_KEY_NUM_BYTES);
+        let cg_key_bytes = vector::slice(&bytes, ED25519_PUBLIC_KEY_NUM_BYTES + BLS12381_G1_PUBLIC_KEY_NUM_BYTES, vector::length(&bytes));
+
+        let valid_ed_public_key = ed25519::new_validated_public_key_from_bytes(ed_key_bytes);
+        assert!(option::is_some(&valid_ed_public_key), error::invalid_argument(EINVALID_PUBLIC_KEY));
+
+        let valid_bls_public_key = bls12381::public_key_from_bytes(bls_key_bytes);
+        assert!(option::is_some(&valid_bls_public_key), error::invalid_argument(EINVALID_PUBLIC_KEY));
+
+        let valid_cg_public_key = class_groups::public_key_from_bytes(cg_key_bytes);
+        assert!(option::is_some(&valid_cg_public_key), error::invalid_argument(EINVALID_PUBLIC_KEY));
+
+        option::some(ConsensusPublicKey {
+            ed_key: option::extract(&mut valid_ed_public_key),
+            bls_key: valid_bls_public_key,
+            cg_key: valid_cg_public_key
+        })
+
+    }
+    else {
+        option::none<ConsensusPublicKey>()
+    }
+}
+
+ + + +
+ + + +## Function `public_key_to_bytes` + + + +
public fun public_key_to_bytes(pk: consensus_key::ConsensusPublicKey): vector<u8>
+
+ + + +
+Implementation + + +
public fun public_key_to_bytes(pk: ConsensusPublicKey): vector<u8>{
+
+    let out = vector::empty<u8>();
+    let ed_bytes  = ed25519::validated_public_key_to_bytes(&pk.ed_key);
+    vector::append(&mut out, ed_bytes);
+
+    if(option::is_some(&pk.bls_key) && option::is_some(&pk.cg_key)){
+        let bls_key = option::extract(&mut pk.bls_key);
+        let bls_bytes = bls12381::public_key_to_bytes(&bls_key);
+        vector::append(&mut out, bls_bytes);
+
+        let cg_key = option::extract(&mut pk.cg_key);
+        let cg_bytes  = class_groups::public_key_to_bytes(&cg_key);
+        vector::append(&mut out, cg_bytes);
+    };
+    out
+}
+
+ + + +
+ + + +## Function `get_bls_pub_key` + + + +
public fun get_bls_pub_key(pk: &consensus_key::ConsensusPublicKey): option::Option<bls12381::PublicKey>
+
+ + + +
+Implementation + + +
public fun get_bls_pub_key(pk: &ConsensusPublicKey): option::Option<bls12381::PublicKey>{
+    pk.bls_key
+}
+
+ + + +
+ + + +## Function `get_ed_key` + + + +
public fun get_ed_key(pk: &consensus_key::ConsensusPublicKey): ed25519::ValidatedPublicKey
+
+ + + +
+Implementation + + +
public fun get_ed_key(pk: &ConsensusPublicKey): ed25519::ValidatedPublicKey{
+    pk.ed_key
+}
+
+ + + +
+ + + +## Function `get_cg_key` + + + +
public fun get_cg_key(pk: &consensus_key::ConsensusPublicKey): option::Option<class_groups::CGPublicKey>
+
+ + + +
+Implementation + + +
public fun get_cg_key(pk: &ConsensusPublicKey): option::Option<class_groups::CGPublicKey>{
+    pk.cg_key
+}
+
+ + + +
+ + +[move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/supra-stdlib/doc/decode_bcs.md b/aptos-move/framework/supra-stdlib/doc/decode_bcs.md new file mode 100644 index 00000000000..42393b8d8d4 --- /dev/null +++ b/aptos-move/framework/supra-stdlib/doc/decode_bcs.md @@ -0,0 +1,729 @@ + + + +# Module `0x1::decode_bcs` + +This module implements BCS (de)serialization in Move. +Full specification can be found here: https://github.com/diem/bcs + + +- [Struct `BCS`](#0x1_decode_bcs_BCS) +- [Constants](#@Constants_0) +- [Function `to_bytes`](#0x1_decode_bcs_to_bytes) +- [Function `new`](#0x1_decode_bcs_new) +- [Function `into_remainder_bytes`](#0x1_decode_bcs_into_remainder_bytes) +- [Function `peel_bool`](#0x1_decode_bcs_peel_bool) +- [Function `peel_u8`](#0x1_decode_bcs_peel_u8) +- [Function `peel_u16`](#0x1_decode_bcs_peel_u16) +- [Function `peel_u32`](#0x1_decode_bcs_peel_u32) +- [Function `peel_u64`](#0x1_decode_bcs_peel_u64) +- [Function `peel_u128`](#0x1_decode_bcs_peel_u128) +- [Function `peel_u256`](#0x1_decode_bcs_peel_u256) +- [Function `peel_vec_length`](#0x1_decode_bcs_peel_vec_length) +- [Function `peel_vec_bool`](#0x1_decode_bcs_peel_vec_bool) +- [Function `peel_vec_u8`](#0x1_decode_bcs_peel_vec_u8) +- [Function `peel_vec_u16`](#0x1_decode_bcs_peel_vec_u16) +- [Function `peel_vec_u32`](#0x1_decode_bcs_peel_vec_u32) +- [Function `peel_vec_u64`](#0x1_decode_bcs_peel_vec_u64) +- [Function `peel_vec_u128`](#0x1_decode_bcs_peel_vec_u128) +- [Function `peel_vec_u256`](#0x1_decode_bcs_peel_vec_u256) +- [Function `peel_vec_vec_u8`](#0x1_decode_bcs_peel_vec_vec_u8) +- [Function `peel_vec_vec_vec_u8`](#0x1_decode_bcs_peel_vec_vec_vec_u8) +- [Specification](#@Specification_1) + + +
use 0x1::bcs;
+use 0x1::vector;
+
+ + + + + +## Struct `BCS` + +A helper struct that saves resources on operations. For better +vector performance, it stores reversed bytes of the BCS and +enables use of vector::pop_back. + + +
struct BCS has copy, drop, store
+
+ + + +
+Fields + + +
+
+bytes: vector<u8> +
+
+ +
+
+ + +
+ + + +## Constants + + + + +For when ULEB byte is out of range (or not found). + + +
const ELenOutOfRange: u64 = 2;
+
+ + + + + +For when the boolean value different than 0 or 1. + + +
const ENotBool: u64 = 1;
+
+ + + + + +For when bytes length is less than required for deserialization. + + +
const EOutOfRange: u64 = 0;
+
+ + + + + +## Function `to_bytes` + +Get BCS serialized bytes for any value. +Re-exports stdlib bcs::to_bytes. + + +
public fun to_bytes<T>(value: &T): vector<u8>
+
+ + + +
+Implementation + + +
public fun to_bytes<T>(value: &T): vector<u8> {
+    bcs::to_bytes(value)
+}
+
+ + + +
+ + + +## Function `new` + +Creates a new instance of BCS wrapper that holds inversed +bytes for better performance. + + +
public fun new(bytes: vector<u8>): decode_bcs::BCS
+
+ + + +
+Implementation + + +
public fun new(bytes: vector<u8>): BCS {
+    v::reverse(&mut bytes);
+    BCS { bytes }
+}
+
+ + + +
+ + + +## Function `into_remainder_bytes` + +Unpack the BCS struct returning the leftover bytes. +Useful for passing the data further after partial deserialization. + + +
public fun into_remainder_bytes(bcs: decode_bcs::BCS): vector<u8>
+
+ + + +
+Implementation + + +
public fun into_remainder_bytes(bcs: BCS): vector<u8> {
+    let BCS { bytes } = bcs;
+    v::reverse(&mut bytes);
+    bytes
+}
+
+ + + +
+ + + +## Function `peel_bool` + +Read a bool value from bcs-serialized bytes. + + +
public fun peel_bool(bcs: &mut decode_bcs::BCS): bool
+
+ + + +
+Implementation + + +
public fun peel_bool(bcs: &mut BCS): bool {
+    let value = peel_u8(bcs);
+    if (value == 0) {
+        false
+    } else if (value == 1) {
+        true
+    } else {
+        abort ENotBool
+    }
+}
+
+ + + +
+ + + +## Function `peel_u8` + +Read u8 value from bcs-serialized bytes. + + +
public fun peel_u8(bcs: &mut decode_bcs::BCS): u8
+
+ + + +
+Implementation + + +
public fun peel_u8(bcs: &mut BCS): u8 {
+    assert!(v::length(&bcs.bytes) >= 1, EOutOfRange);
+    v::pop_back(&mut bcs.bytes)
+}
+
+ + + +
+ + + +## Function `peel_u16` + +Read u16 value from bcs-serialized bytes. + + +
public fun peel_u16(bcs: &mut decode_bcs::BCS): u16
+
+ + + +
+Implementation + + +
public fun peel_u16(bcs: &mut BCS): u16 {
+    assert!(v::length(&bcs.bytes) >= 2, EOutOfRange);
+    let (value, i) = (0u16, 0u8);
+    while (i < 16) {
+        let byte = (v::pop_back(&mut bcs.bytes) as u16);
+        value = value | (byte << i);
+        i = i + 8;
+    };
+    value
+}
+
+ + + +
+ + + +## Function `peel_u32` + +Read u32 value from bcs-serialized bytes. + + +
public fun peel_u32(bcs: &mut decode_bcs::BCS): u32
+
+ + + +
+Implementation + + +
public fun peel_u32(bcs: &mut BCS): u32 {
+    assert!(v::length(&bcs.bytes) >= 4, EOutOfRange);
+    let (value, i) = (0u32, 0u8);
+    while (i < 32) {
+        let byte = (v::pop_back(&mut bcs.bytes) as u32);
+        value = value | (byte << i);
+        i = i + 8;
+    };
+    value
+}
+
+ + + +
+ + + +## Function `peel_u64` + +Read u64 value from bcs-serialized bytes. + + +
public fun peel_u64(bcs: &mut decode_bcs::BCS): u64
+
+ + + +
+Implementation + + +
public fun peel_u64(bcs: &mut BCS): u64 {
+    assert!(v::length(&bcs.bytes) >= 8, EOutOfRange);
+    let (value, i) = (0u64, 0u8);
+    while (i < 64) {
+        let byte = (v::pop_back(&mut bcs.bytes) as u64);
+        value = value | (byte << i);
+        i = i + 8;
+    };
+    value
+}
+
+ + + +
+ + + +## Function `peel_u128` + +Read u128 value from bcs-serialized bytes. + + +
public fun peel_u128(bcs: &mut decode_bcs::BCS): u128
+
+ + + +
+Implementation + + +
public fun peel_u128(bcs: &mut BCS): u128 {
+    assert!(v::length(&bcs.bytes) >= 16, EOutOfRange);
+
+    let (value, i) = (0u128, 0u8);
+    while (i < 128) {
+        let byte = (v::pop_back(&mut bcs.bytes) as u128);
+        value = value | (byte << i);
+        i = i + 8;
+    };
+
+    value
+}
+
+ + + +
+ + + +## Function `peel_u256` + +Read u256 value from bcs-serialized bytes. + + +
public fun peel_u256(bcs: &mut decode_bcs::BCS): u256
+
+ + + +
+Implementation + + +
public fun peel_u256(bcs: &mut BCS): u256 {
+    assert!(v::length(&bcs.bytes) >= 16, EOutOfRange);
+
+    let (value, i) = (0u256, 0u8);
+    while (i < 255) {
+        let byte = (v::pop_back(&mut bcs.bytes) as u256);
+        value = value | (byte << i);
+        i = i + 8;
+    };
+
+    value
+}
+
+ + + +
+ + + +## Function `peel_vec_length` + +Read ULEB bytes expecting a vector length. Result should +then be used to perform peel_* operation LEN times. + +In BCS vector length is implemented with ULEB128; +See more here: https://en.wikipedia.org/wiki/LEB128 + + +
public fun peel_vec_length(bcs: &mut decode_bcs::BCS): u64
+
+ + + +
+Implementation + + +
public fun peel_vec_length(bcs: &mut BCS): u64 {
+    let (total, shift, len) = (0u64, 0, 0);
+    while (true) {
+        assert!(len <= 4, ELenOutOfRange);
+        let byte = (v::pop_back(&mut bcs.bytes) as u64);
+        len = len + 1;
+        total = total | ((byte & 0x7f) << shift);
+        if ((byte & 0x80) == 0) {
+            break
+        };
+        shift = shift + 7;
+    };
+    total
+}
+
+ + + +
+ + + +## Function `peel_vec_bool` + +Peel a vector of bool from serialized bytes. + + +
public fun peel_vec_bool(bcs: &mut decode_bcs::BCS): vector<bool>
+
+ + + +
+Implementation + + +
public fun peel_vec_bool(bcs: &mut BCS): vector<bool> {
+    let (len, i, res) = (peel_vec_length(bcs), 0, vector[]);
+    while (i < len) {
+        v::push_back(&mut res, peel_bool(bcs));
+        i = i + 1;
+    };
+    res
+}
+
+ + + +
+ + + +## Function `peel_vec_u8` + +Peel a vector of u8 (eg string) from serialized bytes. + + +
public fun peel_vec_u8(bcs: &mut decode_bcs::BCS): vector<u8>
+
+ + + +
+Implementation + + +
public fun peel_vec_u8(bcs: &mut BCS): vector<u8> {
+    let (len, i, res) = (peel_vec_length(bcs), 0, vector[]);
+    while (i < len) {
+        v::push_back(&mut res, peel_u8(bcs));
+        i = i + 1;
+    };
+    res
+}
+
+ + + +
+ + + +## Function `peel_vec_u16` + +Peel a vector of u16 (eg string) from serialized bytes. + + +
public fun peel_vec_u16(bcs: &mut decode_bcs::BCS): vector<u16>
+
+ + + +
+Implementation + + +
public fun peel_vec_u16(bcs: &mut BCS): vector<u16> {
+    let (len, i, res) = (peel_vec_length(bcs), 0, vector[]);
+    while (i < len) {
+        v::push_back(&mut res, peel_u16(bcs));
+        i = i + 1;
+    };
+    res
+}
+
+ + + +
+ + + +## Function `peel_vec_u32` + +Peel a vector of u32 (eg string) from serialized bytes. + + +
public fun peel_vec_u32(bcs: &mut decode_bcs::BCS): vector<u32>
+
+ + + +
+Implementation + + +
public fun peel_vec_u32(bcs: &mut BCS): vector<u32> {
+    let (len, i, res) = (peel_vec_length(bcs), 0, vector[]);
+    while (i < len) {
+        v::push_back(&mut res, peel_u32(bcs));
+        i = i + 1;
+    };
+    res
+}
+
+ + + +
+ + + +## Function `peel_vec_u64` + +Peel a vector of u64 from serialized bytes. + + +
public fun peel_vec_u64(bcs: &mut decode_bcs::BCS): vector<u64>
+
+ + + +
+Implementation + + +
public fun peel_vec_u64(bcs: &mut BCS): vector<u64> {
+    let (len, i, res) = (peel_vec_length(bcs), 0, vector[]);
+    while (i < len) {
+        v::push_back(&mut res, peel_u64(bcs));
+        i = i + 1;
+    };
+    res
+}
+
+ + + +
+ + + +## Function `peel_vec_u128` + +Peel a vector of u128 from serialized bytes. + + +
public fun peel_vec_u128(bcs: &mut decode_bcs::BCS): vector<u128>
+
+ + + +
+Implementation + + +
public fun peel_vec_u128(bcs: &mut BCS): vector<u128> {
+    let (len, i, res) = (peel_vec_length(bcs), 0, vector[]);
+    while (i < len) {
+        v::push_back(&mut res, peel_u128(bcs));
+        i = i + 1;
+    };
+    res
+}
+
+ + + +
+ + + +## Function `peel_vec_u256` + +Peel a vector of u256 from serialized bytes. + + +
public fun peel_vec_u256(bcs: &mut decode_bcs::BCS): vector<u256>
+
+ + + +
+Implementation + + +
public fun peel_vec_u256(bcs: &mut BCS): vector<u256> {
+    let (len, i, res) = (peel_vec_length(bcs), 0, vector[]);
+    while (i < len) {
+        v::push_back(&mut res, peel_u256(bcs));
+        i = i + 1;
+    };
+    res
+}
+
+ + + +
+ + + +## Function `peel_vec_vec_u8` + +Peel a vector<vector<u8>> (eg vec of string) from serialized bytes. + + +
public fun peel_vec_vec_u8(bcs: &mut decode_bcs::BCS): vector<vector<u8>>
+
+ + + +
+Implementation + + +
public fun peel_vec_vec_u8(bcs: &mut BCS): vector<vector<u8>> {
+    let (len, i, res) = (peel_vec_length(bcs), 0, vector[]);
+    while (i < len) {
+        v::push_back(&mut res, peel_vec_u8(bcs));
+        i = i + 1;
+    };
+    res
+}
+
+ + + +
+ + + +## Function `peel_vec_vec_vec_u8` + +Peel a vector<vector<vector<u8>>> (eg vec of string) from serialized bytes. + + +
public fun peel_vec_vec_vec_u8(bcs: &mut decode_bcs::BCS): vector<vector<vector<u8>>>
+
+ + + +
+Implementation + + +
public fun peel_vec_vec_vec_u8(bcs: &mut BCS): vector<vector<vector<u8>>> {
+    let (len, i, res) = (peel_vec_length(bcs), 0, vector[]);
+    while (i < len) {
+        v::push_back(&mut res, peel_vec_vec_u8(bcs));
+        i = i + 1;
+    };
+    res
+}
+
+ + + +
+ + + +## Specification + + + +
pragma verify = false;
+
+ + +[move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/supra-stdlib/doc/overview.md b/aptos-move/framework/supra-stdlib/doc/overview.md index 08a5aa31ff6..a8230be46ba 100644 --- a/aptos-move/framework/supra-stdlib/doc/overview.md +++ b/aptos-move/framework/supra-stdlib/doc/overview.md @@ -15,6 +15,8 @@ This is the reference documentation of the Supra standard library extension. - [`0x1::bls12381_bulletproofs`](bls12381_bulletproofs.md#0x1_bls12381_bulletproofs) - [`0x1::bls12381_pedersen`](bls12381_pedersen.md#0x1_bls12381_pedersen) - [`0x1::bls12381_scalar`](bls12381_scalar.md#0x1_bls12381_scalar) +- [`0x1::class_groups`](class_groups.md#0x1_class_groups) +- [`0x1::decode_bcs`](decode_bcs.md#0x1_decode_bcs) - [`0x1::enumerable_map`](enumerable_map.md#0x1_enumerable_map) - [`0x1::eth_trie`](eth_trie.md#0x1_eth_trie) - [`0x1::rlp`](rlp.md#0x1_rlp) diff --git a/aptos-move/framework/supra-stdlib/sources/class_groups.move b/aptos-move/framework/supra-stdlib/sources/class_groups.move new file mode 100644 index 00000000000..d508fb531ca --- /dev/null +++ b/aptos-move/framework/supra-stdlib/sources/class_groups.move @@ -0,0 +1,48 @@ +// Copyright (c) 2025 Supra. +module supra_std::class_groups { + + use std::option; + use std::option::Option; + + struct CGPublicKey has copy, drop, store { + bytes: vector + } + + #[test_only] + struct SecretKey has copy, drop { + bytes: vector, + } + + /// Creates a new public key from a sequence of bytes. + public fun public_key_from_bytes(bytes: vector): Option { + if (validate_pubkey_internal(bytes)) { + option::some(CGPublicKey { + bytes + }) + } else { + option::none() + } + } + + /// Serializes a public key to a sequence of bytes. + public fun public_key_to_bytes(pk: &CGPublicKey): vector { + pk.bytes + } + + #[test_only] + /// Generates a class group key-pair: a secret key with its corresponding public key. + public fun generate_keys(): (SecretKey, CGPublicKey) { + let (sk_bytes, pk_bytes) = generate_keys_internal(); + let sk = SecretKey { + bytes: sk_bytes + }; + let pk = CGPublicKey { + bytes: pk_bytes + }; + (sk, pk) + } + + native fun validate_pubkey_internal(public_key: vector): bool; + #[test_only] + native fun generate_keys_internal(): (vector, vector); +} diff --git a/aptos-move/framework/supra-stdlib/sources/decode_bcs.move b/aptos-move/framework/supra-stdlib/sources/decode_bcs.move new file mode 100644 index 00000000000..5bf4aaca7df --- /dev/null +++ b/aptos-move/framework/supra-stdlib/sources/decode_bcs.move @@ -0,0 +1,370 @@ +/// This module implements BCS (de)serialization in Move. +/// Full specification can be found here: https://github.com/diem/bcs +module supra_std::decode_bcs { + use std::vector as v; + use std::bcs; + + /// For when bytes length is less than required for deserialization. + const EOutOfRange: u64 = 0; + + /// For when the boolean value different than `0` or `1`. + const ENotBool: u64 = 1; + + /// For when ULEB byte is out of range (or not found). + const ELenOutOfRange: u64 = 2; + + /// A helper struct that saves resources on operations. For better + /// vector performance, it stores reversed bytes of the BCS and + /// enables use of `vector::pop_back`. + struct BCS has store, copy, drop { + bytes: vector + } + + /// Get BCS serialized bytes for any value. + /// Re-exports stdlib `bcs::to_bytes`. + public fun to_bytes(value: &T): vector { + bcs::to_bytes(value) + } + + /// Creates a new instance of BCS wrapper that holds inversed + /// bytes for better performance. + public fun new(bytes: vector): BCS { + v::reverse(&mut bytes); + BCS { bytes } + } + + /// Unpack the `BCS` struct returning the leftover bytes. + /// Useful for passing the data further after partial deserialization. + public fun into_remainder_bytes(bcs: BCS): vector { + let BCS { bytes } = bcs; + v::reverse(&mut bytes); + bytes + } + + /// Read a `bool` value from bcs-serialized bytes. + public fun peel_bool(bcs: &mut BCS): bool { + let value = peel_u8(bcs); + if (value == 0) { + false + } else if (value == 1) { + true + } else { + abort ENotBool + } + } + + /// Read `u8` value from bcs-serialized bytes. + public fun peel_u8(bcs: &mut BCS): u8 { + assert!(v::length(&bcs.bytes) >= 1, EOutOfRange); + v::pop_back(&mut bcs.bytes) + } + + /// Read `u16` value from bcs-serialized bytes. + public fun peel_u16(bcs: &mut BCS): u16 { + assert!(v::length(&bcs.bytes) >= 2, EOutOfRange); + let (value, i) = (0u16, 0u8); + while (i < 16) { + let byte = (v::pop_back(&mut bcs.bytes) as u16); + value = value | (byte << i); + i = i + 8; + }; + value + } + + /// Read `u32` value from bcs-serialized bytes. + public fun peel_u32(bcs: &mut BCS): u32 { + assert!(v::length(&bcs.bytes) >= 4, EOutOfRange); + let (value, i) = (0u32, 0u8); + while (i < 32) { + let byte = (v::pop_back(&mut bcs.bytes) as u32); + value = value | (byte << i); + i = i + 8; + }; + value + } + + /// Read `u64` value from bcs-serialized bytes. + public fun peel_u64(bcs: &mut BCS): u64 { + assert!(v::length(&bcs.bytes) >= 8, EOutOfRange); + let (value, i) = (0u64, 0u8); + while (i < 64) { + let byte = (v::pop_back(&mut bcs.bytes) as u64); + value = value | (byte << i); + i = i + 8; + }; + value + } + + /// Read `u128` value from bcs-serialized bytes. + public fun peel_u128(bcs: &mut BCS): u128 { + assert!(v::length(&bcs.bytes) >= 16, EOutOfRange); + + let (value, i) = (0u128, 0u8); + while (i < 128) { + let byte = (v::pop_back(&mut bcs.bytes) as u128); + value = value | (byte << i); + i = i + 8; + }; + + value + } + + /// Read `u256` value from bcs-serialized bytes. + public fun peel_u256(bcs: &mut BCS): u256 { + assert!(v::length(&bcs.bytes) >= 16, EOutOfRange); + + let (value, i) = (0u256, 0u8); + while (i < 255) { + let byte = (v::pop_back(&mut bcs.bytes) as u256); + value = value | (byte << i); + i = i + 8; + }; + + value + } + + // === Vector === + + /// Read ULEB bytes expecting a vector length. Result should + /// then be used to perform `peel_*` operation LEN times. + /// + /// In BCS `vector` length is implemented with ULEB128; + /// See more here: https://en.wikipedia.org/wiki/LEB128 + public fun peel_vec_length(bcs: &mut BCS): u64 { + let (total, shift, len) = (0u64, 0, 0); + while (true) { + assert!(len <= 4, ELenOutOfRange); + let byte = (v::pop_back(&mut bcs.bytes) as u64); + len = len + 1; + total = total | ((byte & 0x7f) << shift); + if ((byte & 0x80) == 0) { + break + }; + shift = shift + 7; + }; + total + } + + /// Peel a vector of `bool` from serialized bytes. + public fun peel_vec_bool(bcs: &mut BCS): vector { + let (len, i, res) = (peel_vec_length(bcs), 0, vector[]); + while (i < len) { + v::push_back(&mut res, peel_bool(bcs)); + i = i + 1; + }; + res + } + + /// Peel a vector of `u8` (eg string) from serialized bytes. + public fun peel_vec_u8(bcs: &mut BCS): vector { + let (len, i, res) = (peel_vec_length(bcs), 0, vector[]); + while (i < len) { + v::push_back(&mut res, peel_u8(bcs)); + i = i + 1; + }; + res + } + + /// Peel a vector of `u16` (eg string) from serialized bytes. + public fun peel_vec_u16(bcs: &mut BCS): vector { + let (len, i, res) = (peel_vec_length(bcs), 0, vector[]); + while (i < len) { + v::push_back(&mut res, peel_u16(bcs)); + i = i + 1; + }; + res + } + + /// Peel a vector of `u32` (eg string) from serialized bytes. + public fun peel_vec_u32(bcs: &mut BCS): vector { + let (len, i, res) = (peel_vec_length(bcs), 0, vector[]); + while (i < len) { + v::push_back(&mut res, peel_u32(bcs)); + i = i + 1; + }; + res + } + + /// Peel a vector of `u64` from serialized bytes. + public fun peel_vec_u64(bcs: &mut BCS): vector { + let (len, i, res) = (peel_vec_length(bcs), 0, vector[]); + while (i < len) { + v::push_back(&mut res, peel_u64(bcs)); + i = i + 1; + }; + res + } + + /// Peel a vector of `u128` from serialized bytes. + public fun peel_vec_u128(bcs: &mut BCS): vector { + let (len, i, res) = (peel_vec_length(bcs), 0, vector[]); + while (i < len) { + v::push_back(&mut res, peel_u128(bcs)); + i = i + 1; + }; + res + } + + /// Peel a vector of `u256` from serialized bytes. + public fun peel_vec_u256(bcs: &mut BCS): vector { + let (len, i, res) = (peel_vec_length(bcs), 0, vector[]); + while (i < len) { + v::push_back(&mut res, peel_u256(bcs)); + i = i + 1; + }; + res + } + + /// Peel a `vector>` (eg vec of string) from serialized bytes. + public fun peel_vec_vec_u8(bcs: &mut BCS): vector> { + let (len, i, res) = (peel_vec_length(bcs), 0, vector[]); + while (i < len) { + v::push_back(&mut res, peel_vec_u8(bcs)); + i = i + 1; + }; + res + } + + /// Peel a `vector>>` (eg vec of string) from serialized bytes. + public fun peel_vec_vec_vec_u8(bcs: &mut BCS): vector>> { + let (len, i, res) = (peel_vec_length(bcs), 0, vector[]); + while (i < len) { + v::push_back(&mut res, peel_vec_vec_u8(bcs)); + i = i + 1; + }; + res + } + // TODO: re-enable once bit-wise operators in peel_vec_length are supported in the prover + spec module { pragma verify = false; } + + // === Tests === + + #[test_only] + struct Info has drop { a: bool, b: u8, c: u64, d: u128, k: vector, s: address } + + #[test] + #[expected_failure(abort_code = ELenOutOfRange)] + fun test_uleb_len_fail() { + let value = vector[0xff, 0xff, 0xff, 0xff, 0xff]; + let bytes = new(to_bytes(&value)); + let _fail = peel_vec_length(&mut bytes); + abort 2 // TODO: make this test fail + } + + #[test] + #[expected_failure(abort_code = ENotBool)] + fun test_bool_fail() { + let bytes = new(to_bytes(&10u8)); + let _fail = peel_bool(&mut bytes); + } + + #[test] + fun test_bcs() { + + { // boolean: true + let value = true; + let bytes = new(to_bytes(&value)); + assert!(value == peel_bool(&mut bytes), 0); + }; + + { // boolean: false + let value = false; + let bytes = new(to_bytes(&value)); + assert!(value == peel_bool(&mut bytes), 0); + }; + + { // u8 + let value = 100u8; + let bytes = new(to_bytes(&value)); + assert!(value == peel_u8(&mut bytes), 0); + }; + + { // u64 (4 bytes) + let value = 1000100u64; + let bytes = new(to_bytes(&value)); + assert!(value == peel_u64(&mut bytes), 0); + }; + + { // u64 (8 bytes) + let value = 100000000000000u64; + let bytes = new(to_bytes(&value)); + assert!(value == peel_u64(&mut bytes), 0); + }; + + { // u128 (16 bytes) + let value = 100000000000000000000000000u128; + let bytes = new(to_bytes(&value)); + assert!(value == peel_u128(&mut bytes), 0); + }; + + { // vector length + let value = vector[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; + let bytes = new(to_bytes(&value)); + assert!(v::length(&value) == peel_vec_length(&mut bytes), 0); + }; + + { // vector length (more data) + let value = vector[ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ]; + + let bytes = new(to_bytes(&value)); + assert!(v::length(&value) == peel_vec_length(&mut bytes), 0); + }; + + { // full deserialization test (ordering) + let info = Info { a: true, b: 100, c: 9999, d: 112333, k: vector[true, false, true, false], s: @0xAAAAAAAAAAA }; + let bytes = new(to_bytes(&info)); + + assert!(info.a == peel_bool(&mut bytes), 0); + assert!(info.b == peel_u8(&mut bytes), 0); + assert!(info.c == peel_u64(&mut bytes), 0); + assert!(info.d == peel_u128(&mut bytes), 0); + + let len = peel_vec_length(&mut bytes); + + assert!(v::length(&info.k) == len, 0); + + }; + + { // read vector of bytes directly + let value = vector[ + vector[1,2,3,4,5], + vector[1,2,3,4,5], + vector[1,2,3,4,5] + ]; + let bytes = new(to_bytes(&value)); + assert!(value == peel_vec_vec_u8(&mut bytes), 0); + }; + + { // read vector of bytes directly + let value = vector[1,2,3,4,5]; + let bytes = new(to_bytes(&value)); + assert!(value == peel_vec_u8(&mut bytes), 0); + }; + + { // read vector of bytes directly + let value = vector[1,2,3,4,5]; + let bytes = new(to_bytes(&value)); + assert!(value == peel_vec_u64(&mut bytes), 0); + }; + + { // read vector of bytes directly + let value = vector[1,2,3,4,5]; + let bytes = new(to_bytes(&value)); + assert!(value == peel_vec_u128(&mut bytes), 0); + }; + + { // read vector of bytes directly + let value = vector[true, false, true, false]; + let bytes = new(to_bytes(&value)); + assert!(value == peel_vec_bool(&mut bytes), 0); + }; + + } +} \ No newline at end of file diff --git a/aptos-move/framework/tests/move_unit_test.rs b/aptos-move/framework/tests/move_unit_test.rs index e2b25f27310..032c89f025d 100644 --- a/aptos-move/framework/tests/move_unit_test.rs +++ b/aptos-move/framework/tests/move_unit_test.rs @@ -66,8 +66,8 @@ pub fn aptos_test_natives() -> NativeFunctionTable { natives::configure_for_unit_test(); extended_checks::configure_extended_checks_for_unit_test(); // move_stdlib has the testing feature enabled to include debug native functions - let mut f = Features::default(); - f.enable(aptos_types::on_chain_config::FeatureFlag::DELEGATION_POOLS); + let mut f = Features::default(); + f.enable(aptos_types::on_chain_config::FeatureFlag::DELEGATION_POOLS); natives::aptos_natives( LATEST_GAS_FEATURE_VERSION, NativeGasParameters::zeros(), diff --git a/aptos-move/move-examples/Cargo.toml b/aptos-move/move-examples/Cargo.toml index 7eb718b6a16..dbabb539b42 100644 --- a/aptos-move/move-examples/Cargo.toml +++ b/aptos-move/move-examples/Cargo.toml @@ -16,7 +16,7 @@ rust-version = { workspace = true } aptos-framework = { workspace = true } aptos-gas-schedule = { workspace = true } aptos-types = { workspace = true } -aptos-vm ={ workspace = true, features = ["testing"] } +aptos-vm = { workspace = true, features = ["testing"] } clap = { workspace = true } move-cli = { workspace = true } move-model = { workspace = true } diff --git a/aptos-move/move-examples/cli_args/Move.toml b/aptos-move/move-examples/cli_args/Move.toml index 5549eba33d9..5cd9bd5b839 100644 --- a/aptos-move/move-examples/cli_args/Move.toml +++ b/aptos-move/move-examples/cli_args/Move.toml @@ -7,4 +7,4 @@ upgrade_policy = "compatible" test_account = "_" [dependencies.SupraFramework] -local = "../../framework/supra-framework" \ No newline at end of file +local = "../../framework/supra-framework" diff --git a/aptos-move/move-examples/event/Move.toml b/aptos-move/move-examples/event/Move.toml index b252d7280d2..c0ab3113a84 100644 --- a/aptos-move/move-examples/event/Move.toml +++ b/aptos-move/move-examples/event/Move.toml @@ -9,4 +9,3 @@ event = "_" [dependencies] SupraFramework = { local = "../../framework/supra-framework" } - diff --git a/aptos-move/move-examples/fungible_asset/stablecoin/Move.toml b/aptos-move/move-examples/fungible_asset/stablecoin/Move.toml index aa5e0c0736b..40cadbbb26f 100644 --- a/aptos-move/move-examples/fungible_asset/stablecoin/Move.toml +++ b/aptos-move/move-examples/fungible_asset/stablecoin/Move.toml @@ -6,7 +6,7 @@ version = "0.0.0" [addresses] stablecoin = "_" master_minter = "_" -minter = "_" +minter = "_" pauser = "_" denylister = "_" diff --git a/aptos-move/move-examples/hello_prover/Move.toml b/aptos-move/move-examples/hello_prover/Move.toml index 3e2ac565d7b..958b8dc1f03 100644 --- a/aptos-move/move-examples/hello_prover/Move.toml +++ b/aptos-move/move-examples/hello_prover/Move.toml @@ -6,5 +6,3 @@ version = "0.0.0" SupraFramework = { local = "../../../framework/supra-framework" } [addresses] - - diff --git a/aptos-move/move-examples/mint_nft/3-Adding-Admin/Move.toml b/aptos-move/move-examples/mint_nft/3-Adding-Admin/Move.toml index c0ffbc9aee2..c1a9c071062 100644 --- a/aptos-move/move-examples/mint_nft/3-Adding-Admin/Move.toml +++ b/aptos-move/move-examples/mint_nft/3-Adding-Admin/Move.toml @@ -9,4 +9,4 @@ AptosToken = { local = "../../../framework/aptos-token" } [addresses] supra_framework = "0x1" # replace the admin_addr with the actual admin address we created using CLI -admin_addr = "0xbeef" \ No newline at end of file +admin_addr = "0xbeef" diff --git a/aptos-move/move-examples/mint_nft/4-Getting-Production-Ready/Move.toml b/aptos-move/move-examples/mint_nft/4-Getting-Production-Ready/Move.toml index c0ffbc9aee2..c1a9c071062 100644 --- a/aptos-move/move-examples/mint_nft/4-Getting-Production-Ready/Move.toml +++ b/aptos-move/move-examples/mint_nft/4-Getting-Production-Ready/Move.toml @@ -9,4 +9,4 @@ AptosToken = { local = "../../../framework/aptos-token" } [addresses] supra_framework = "0x1" # replace the admin_addr with the actual admin address we created using CLI -admin_addr = "0xbeef" \ No newline at end of file +admin_addr = "0xbeef" diff --git a/aptos-move/move-examples/my_first_dapp/move/Move.toml b/aptos-move/move-examples/my_first_dapp/move/Move.toml index 10167e3b2e9..fd0cc79ccd4 100644 --- a/aptos-move/move-examples/my_first_dapp/move/Move.toml +++ b/aptos-move/move-examples/my_first_dapp/move/Move.toml @@ -7,4 +7,4 @@ SupraFramework = {local = "../../../framework/supra-framework"} [addresses] -todolist_addr='_' \ No newline at end of file +todolist_addr = '_' diff --git a/aptos-move/move-examples/raffle/Move.toml b/aptos-move/move-examples/raffle/Move.toml index 91d7786ad6e..8ef41021ce8 100644 --- a/aptos-move/move-examples/raffle/Move.toml +++ b/aptos-move/move-examples/raffle/Move.toml @@ -8,4 +8,4 @@ AptosStdlib = { local = "../../framework/aptos-std" } [addresses] -raffle = "_" \ No newline at end of file +raffle = "_" diff --git a/aptos-move/move-examples/tic-tac-toe/Move.toml b/aptos-move/move-examples/tic-tac-toe/Move.toml index 8944127a473..69ae7976390 100644 --- a/aptos-move/move-examples/tic-tac-toe/Move.toml +++ b/aptos-move/move-examples/tic-tac-toe/Move.toml @@ -7,4 +7,3 @@ tic_tac_toe = "_" [dependencies] SupraFramework = { local = "../../framework/supra-framework" } - diff --git a/aptos-move/move-examples/upgrade_and_govern/upgrade/Move.toml b/aptos-move/move-examples/upgrade_and_govern/upgrade/Move.toml index 22fc1fd2eef..af213eebc93 100644 --- a/aptos-move/move-examples/upgrade_and_govern/upgrade/Move.toml +++ b/aptos-move/move-examples/upgrade_and_govern/upgrade/Move.toml @@ -7,4 +7,4 @@ version = '1.1.0' upgrade_and_govern = '_' [dependencies.SupraFramework] -local = '../../../framework/supra-framework' # <:!:manifest \ No newline at end of file +local = '../../../framework/supra-framework' # <:!:manifest diff --git a/aptos-move/vm-genesis/Cargo.toml b/aptos-move/vm-genesis/Cargo.toml index c0d1338cdb1..d461a5268a0 100644 --- a/aptos-move/vm-genesis/Cargo.toml +++ b/aptos-move/vm-genesis/Cargo.toml @@ -13,10 +13,11 @@ repository = { workspace = true } rust-version = { workspace = true } [dependencies] -aptos-cached-packages = { workspace = true } +aptos-cached-packages = { workspace = true } aptos-crypto = { workspace = true } -aptos-framework = { workspace = true } -aptos-gas-schedule = { workspace = true } +crypto = { workspace = true } +aptos-framework = { workspace = true } +aptos-gas-schedule = { workspace = true } aptos-types = { workspace = true } aptos-vm = { workspace = true } aptos-vm-types = { workspace = true } @@ -39,4 +40,8 @@ proptest-derive = { workspace = true } [features] default = [] -fuzzing = ["aptos-types/fuzzing", "move-core-types/fuzzing", "move-vm-types/fuzzing"] +fuzzing = [ + "aptos-types/fuzzing", + "move-core-types/fuzzing", + "move-vm-types/fuzzing", +] diff --git a/aptos-move/vm-genesis/src/lib.rs b/aptos-move/vm-genesis/src/lib.rs index 4c01185205a..9a9745f73cf 100644 --- a/aptos-move/vm-genesis/src/lib.rs +++ b/aptos-move/vm-genesis/src/lib.rs @@ -8,7 +8,7 @@ mod genesis_context; use crate::genesis_context::GenesisStateView; use aptos_crypto::{ - ed25519, + bls12381, ed25519, ed25519::{Ed25519PrivateKey, Ed25519PublicKey}, HashValue, PrivateKey, Uniform, }; @@ -36,12 +36,14 @@ use aptos_types::{ move_utils::as_move_value::AsMoveValue, on_chain_config::{ randomness_api_v0_config::{AllowCustomMaxGasFlag, RequiredGasDeposit}, - AutomationRegistryConfig, FeatureFlag, Features, GasScheduleV2, OnChainConsensusConfig, + AutomationRegistryConfig, BanRegistryParameters, FeatureFlag, Features, GasScheduleV2, + OnChainConsensusConfig, OnChainEvmConfig, OnChainEvmContractsDetails, OnChainEvmGenesisConfig, OnChainExecutionConfig, OnChainJWKConsensusConfig, OnChainRandomnessConfig, RandomnessConfigMoveStruct, APTOS_MAX_KNOWN_VERSION, }, state_store::state_key::StateKey, transaction::{authenticator::AuthenticationKey, ChangeSet, Transaction, WriteSetPayload}, + validator_public_keys::ValidatorPublicKeys, write_set::{TransactionWrite, WriteOp, WriteSet}, }; use aptos_vm::{ @@ -74,10 +76,9 @@ use once_cell::sync::Lazy; use rand::prelude::*; use serde::{Deserialize, Serialize}; use std::{ - collections::BTreeSet, + collections::{BTreeMap, BTreeSet}, hash::{Hash, Hasher}, }; -use std::collections::BTreeMap; // The seed is arbitrarily picked to produce a consistent key. XXX make this more formal? const GENESIS_SEED: [u8; 32] = [42; 32]; @@ -90,7 +91,7 @@ const VERSION_MODULE_NAME: &str = "version"; const JWK_CONSENSUS_CONFIG_MODULE_NAME: &str = "jwk_consensus_config"; const JWKS_MODULE_NAME: &str = "jwks"; const CONFIG_BUFFER_MODULE_NAME: &str = "config_buffer"; -const DKG_MODULE_NAME: &str = "dkg"; +const DKG_MODULE_NAME: &str = "supra_dkg"; const RANDOMNESS_API_V0_CONFIG_MODULE_NAME: &str = "randomness_api_v0_config"; const RANDOMNESS_CONFIG_SEQNUM_MODULE_NAME: &str = "randomness_config_seqnum"; const RANDOMNESS_CONFIG_MODULE_NAME: &str = "randomness_config"; @@ -129,6 +130,7 @@ pub struct GenesisConfiguration { pub randomness_config_override: Option, pub jwk_consensus_config_override: Option, pub automation_registry_config: Option, + pub leader_ban_registry_config: Option, pub initial_jwks: Vec, pub keyless_groth16_vk: Option, } @@ -208,26 +210,72 @@ pub fn encode_supra_mainnet_genesis_transaction( .map(Features::into_flag_vec), ); initialize_supra_coin(&mut session, &module_storage, &mut traversal_context); - initialize_supra_native_automation(&mut session, &module_storage, &mut traversal_context, genesis_config); - initialize_on_chain_governance(&mut session, &module_storage, &mut traversal_context, genesis_config); - create_accounts(&mut session, &module_storage, &mut traversal_context, accounts); + initialize_supra_native_automation( + &mut session, + &module_storage, + &mut traversal_context, + genesis_config, + ); + initialize_on_chain_governance( + &mut session, + &module_storage, + &mut traversal_context, + genesis_config, + ); + create_accounts( + &mut session, + &module_storage, + &mut traversal_context, + accounts, + ); if let Some(owner_group) = owner_group { - create_multiple_multisig_accounts_with_schema(&mut session, &module_storage, &mut traversal_context, owner_group); + create_multiple_multisig_accounts_with_schema( + &mut session, + &module_storage, + &mut traversal_context, + owner_group, + ); } - create_multisig_accounts_with_balance(&mut session, &module_storage, &mut traversal_context, multisig_accounts); + create_multisig_accounts_with_balance( + &mut session, + &module_storage, + &mut traversal_context, + multisig_accounts, + ); // All PBO delegated validators are initialized here - create_pbo_delegation_pools(&mut session, &module_storage, &mut traversal_context, delegation_pools); + create_pbo_delegation_pools( + &mut session, + &module_storage, + &mut traversal_context, + delegation_pools, + ); - add_owner_stakes_for_delegation_pools(&mut session, &module_storage, &mut traversal_context, delegation_pools, owner_stake_for_pbo_pool); + add_owner_stakes_for_delegation_pools( + &mut session, + &module_storage, + &mut traversal_context, + delegation_pools, + owner_stake_for_pbo_pool, + ); // PBO vesting accounts, employees, investors etc. are placed in their vesting pools - create_vesting_without_staking_pools(&mut session, &module_storage, &mut traversal_context, vesting_pools); + create_vesting_without_staking_pools( + &mut session, + &module_storage, + &mut traversal_context, + vesting_pools, + ); // Lock up the remaining available balances of the accounts for TGE - create_vesting_without_staking_pools(&mut session, &module_storage, &mut traversal_context, initial_unlock_vesting_pools); + create_vesting_without_staking_pools( + &mut session, + &module_storage, + &mut traversal_context, + initial_unlock_vesting_pools, + ); set_genesis_end(&mut session, &module_storage, &mut traversal_context); @@ -272,6 +320,8 @@ pub fn encode_genesis_transaction_for_testnet( gas_schedule: &GasScheduleV2, supra_config_bytes: Vec, evm_genesis_config: Option, + evm_contracts_details: Option, + evm_scalar_config: Option, ) -> Transaction { Transaction::GenesisTransaction(WriteSetPayload::Direct( encode_genesis_change_set_for_testnet( @@ -292,6 +342,8 @@ pub fn encode_genesis_transaction_for_testnet( gas_schedule, supra_config_bytes, evm_genesis_config, + evm_contracts_details, + evm_scalar_config, ), )) } @@ -314,6 +366,8 @@ pub fn encode_genesis_change_set_for_testnet( gas_schedule: &GasScheduleV2, supra_config_bytes: Vec, evm_genesis_config: Option, + evm_contracts_details: Option, + evm_scalar_config: Option, ) -> ChangeSet { validate_genesis_config(genesis_config); // Create a Move VM session so we can invoke on-chain genesis initializations. @@ -366,7 +420,12 @@ pub fn encode_genesis_change_set_for_testnet( } else { initialize_supra_coin(&mut session, &module_storage, &mut traversal_context); } - initialize_supra_native_automation(&mut session, &module_storage, &mut traversal_context, genesis_config); + initialize_supra_native_automation( + &mut session, + &module_storage, + &mut traversal_context, + genesis_config, + ); initialize_config_buffer(&mut session, &module_storage, &mut traversal_context); initialize_dkg(&mut session, &module_storage, &mut traversal_context); initialize_reconfiguration_state(&mut session, &module_storage, &mut traversal_context); @@ -389,18 +448,56 @@ pub fn encode_genesis_change_set_for_testnet( &mut traversal_context, genesis_config, ); + initialize_leader_ban_config( + &mut session, + &module_storage, + &mut traversal_context, + genesis_config, + ); if let Some(evm_genesis_config) = evm_genesis_config { - initialize_evm_genesis_config(&mut session, &module_storage, &mut traversal_context, &evm_genesis_config); + initialize_evm_genesis_config( + &mut session, + &module_storage, + &mut traversal_context, + &evm_genesis_config, + ); + } + + if let (Some(evm_contracts_details), Some(evm_scalar_config)) = + (evm_contracts_details, evm_scalar_config) + { + initialize_evm_config( + &mut session, + &module_storage, + &mut traversal_context, + evm_contracts_details, + evm_scalar_config, + ); } - create_accounts(&mut session, &module_storage, &mut traversal_context, accounts); + create_accounts( + &mut session, + &module_storage, + &mut traversal_context, + accounts, + ); if let Some(owner_group) = owner_group { - create_multiple_multisig_accounts_with_schema(&mut session, &module_storage, &mut traversal_context, owner_group); + create_multiple_multisig_accounts_with_schema( + &mut session, + &module_storage, + &mut traversal_context, + owner_group, + ); } - create_multisig_accounts_with_balance(&mut session, &module_storage, &mut traversal_context, multisig_account); + create_multisig_accounts_with_balance( + &mut session, + &module_storage, + &mut traversal_context, + multisig_account, + ); initialize_account_abstraction(&mut session, &module_storage, &mut traversal_context); if validators.len() > 0 { @@ -412,7 +509,12 @@ pub fn encode_genesis_change_set_for_testnet( ); } else { // All PBO delegated validators are initialized here - create_pbo_delegation_pools(&mut session, &module_storage, &mut traversal_context, delegation_pools); + create_pbo_delegation_pools( + &mut session, + &module_storage, + &mut traversal_context, + delegation_pools, + ); add_owner_stakes_for_delegation_pools( &mut session, @@ -423,10 +525,20 @@ pub fn encode_genesis_change_set_for_testnet( ); // PBO vesting accounts, employees, investors etc. are placed in their vesting pools - create_vesting_without_staking_pools(&mut session, &module_storage, &mut traversal_context, vesting_pools); + create_vesting_without_staking_pools( + &mut session, + &module_storage, + &mut traversal_context, + vesting_pools, + ); // Lock up the remaining available balances of the accounts for TGE - create_vesting_without_staking_pools(&mut session, &module_storage, &mut traversal_context, initial_unlock_vesting_pools); + create_vesting_without_staking_pools( + &mut session, + &module_storage, + &mut traversal_context, + initial_unlock_vesting_pools, + ); } if genesis_config.is_test { @@ -716,6 +828,26 @@ fn initialize_supra_native_automation( ); } +fn initialize_leader_ban_config( + session: &mut SessionExt, + module_storage: &impl AptosModuleStorage, + traversal_context: &mut TraversalContext, + genesis_config: &GenesisConfiguration, +) { + let Some(config) = &genesis_config.leader_ban_registry_config else { + return; + }; + exec_function( + session, + module_storage, + traversal_context, + GENESIS_MODULE_NAME, + "initialize_leader_ban_registry_config", + vec![], + config.serialize_into_move_values_with_signer(CORE_CODE_ADDRESS), + ); +} + fn initialize_evm_genesis_config( session: &mut SessionExt, module_storage: &impl AptosModuleStorage, @@ -739,6 +871,33 @@ fn initialize_evm_genesis_config( ); } +fn initialize_evm_config( + session: &mut SessionExt, + module_storage: &impl AptosModuleStorage, + traversal_context: &mut TraversalContext, + evm_contracts_details: OnChainEvmContractsDetails, + evm_scalar_config: OnChainEvmConfig, +) { + let (contract_names, contract_addresses) = evm_contracts_details.to_move_values(); + let (config_keys, config_values) = evm_scalar_config.to_move_values(); + + exec_function( + session, + module_storage, + traversal_context, + GENESIS_MODULE_NAME, + "initialize_evm_config", + vec![], + serialize_values(&vec![ + MoveValue::Signer(CORE_CODE_ADDRESS), + contract_names, + contract_addresses, + config_keys, + config_values, + ]), + ); +} + fn initialize_config_buffer( session: &mut SessionExt, module_storage: &impl AptosModuleStorage, @@ -1124,8 +1283,8 @@ fn create_accounts( exec_function( session, module_storage, - traversal_context, - GENESIS_MODULE_NAME, + traversal_context, + GENESIS_MODULE_NAME, "create_accounts", vec![], serialized_values, @@ -1137,7 +1296,7 @@ fn create_accounts( /// the required accounts, sets the validator operators for each validator owner, and sets the /// validator config on-chain. fn create_and_initialize_validators( - session: &mut SessionExt, + session: &mut SessionExt, module_storage: &impl ModuleStorage, traversal_context: &mut TraversalContext, validators: &[Validator], @@ -1213,7 +1372,6 @@ fn create_multiple_multisig_accounts_with_schema( } fn create_multisig_accounts_with_balance( - session: &mut SessionExt, module_storage: &impl AptosModuleStorage, traversal_context: &mut TraversalContext, @@ -1628,7 +1786,35 @@ impl TestValidator { let auth_key = AuthenticationKey::ed25519(&key.public_key()); let owner_address = auth_key.account_address(); let consensus_key = ed25519::PrivateKey::generate(rng); - let consensus_pubkey = consensus_key.public_key().to_bytes().to_vec(); + let network_pubkey_bytes = consensus_key.public_key().to_bytes().to_vec(); + let bls_key = bls12381::PrivateKey::generate(rng); + let bls_pubkey_bytes = bls12381::PublicKey::from(&bls_key).to_bytes().to_vec(); + let cg_pubkey_bytes = { + let mut cg_rng = crypto::bls12381::cl_utils::rng(); + crypto::bls12381::cg_encryption::keygen(&mut cg_rng, &[]) + .expect("CG keygen must succeed") + .1 + .to_vec() + }; + let supra_ed_key = ed25519::PrivateKey::generate(rng); + let supra_ed_pubkey_bytes = supra_ed_key.public_key().to_bytes().to_vec(); + // When SUPRA_BLS_KEYS feature is enabled (default), the genesis validator key must be + // BCS-encoded ValidatorPublicKeys, not a plain ed25519 key. + let validator_public_keys = ValidatorPublicKeys::new( + network_pubkey_bytes, + bls_pubkey_bytes, + None, + None, + None, + None, + None, + None, + None, + cg_pubkey_bytes, + supra_ed_pubkey_bytes, + ); + let consensus_pubkey = + bcs::to_bytes(&validator_public_keys).expect("ValidatorPublicKeys must serialize"); let network_address = [0u8; 0].to_vec(); let full_node_network_address = [0u8; 0].to_vec(); @@ -1695,6 +1881,7 @@ pub fn generate_test_genesis( randomness_config_override: None, jwk_consensus_config_override: None, automation_registry_config: Some(AutomationRegistryConfig::default()), + leader_ban_registry_config: Some(BanRegistryParameters::default()), initial_jwks: vec![], keyless_groth16_vk: None, }, @@ -1703,6 +1890,8 @@ pub fn generate_test_genesis( &default_gas_schedule(), b"test".to_vec(), None, + None, + None, ); (genesis, test_validators) } @@ -1734,6 +1923,8 @@ pub fn generate_mainnet_genesis( &default_gas_schedule(), b"test".to_vec(), None, + None, + None, ); (genesis, test_validators) } @@ -1765,6 +1956,7 @@ fn mainnet_genesis_config() -> GenesisConfiguration { randomness_config_override: None, jwk_consensus_config_override: None, automation_registry_config: Some(AutomationRegistryConfig::default()), + leader_ban_registry_config: Some(BanRegistryParameters::default()), initial_jwks: vec![], keyless_groth16_vk: None, } @@ -1922,8 +2114,10 @@ pub fn test_mainnet_end_to_end() { TOTAL_SUPPLY - (21 * pbo_balance) - (7 * operator_balance) - (9 * employee_balance); use aptos_types::{ - account_address, on_chain_config::ValidatorSet, state_store::state_key::StateKey, - write_set::TransactionWrite, write_set::WriteSet + account_address, + on_chain_config::ValidatorSet, + state_store::state_key::StateKey, + write_set::{TransactionWrite, WriteSet}, }; let balance = 10_000_000 * APTOS_COINS_BASE_WITH_DECIMALS; diff --git a/aptos-node/Cargo.toml b/aptos-node/Cargo.toml index 40f9929b5c7..bd1f5b748b6 100644 --- a/aptos-node/Cargo.toml +++ b/aptos-node/Cargo.toml @@ -91,11 +91,24 @@ jemallocator = { version = "0.5.0", features = [ rstack-self = { workspace = true } [features] -assert-private-keys-not-cloneable = ["aptos-crypto/assert-private-keys-not-cloneable"] +assert-private-keys-not-cloneable = [ + "aptos-crypto/assert-private-keys-not-cloneable", +] check-vm-features = [] -consensus-only-perf-test = ["aptos-executor/consensus-only-perf-test", "aptos-mempool/consensus-only-perf-test", "aptos-db/consensus-only-perf-test"] +consensus-only-perf-test = [ + "aptos-executor/consensus-only-perf-test", + "aptos-mempool/consensus-only-perf-test", + "aptos-db/consensus-only-perf-test", +] default = [] -failpoints = ["fail/failpoints", "aptos-consensus/failpoints", "aptos-executor/failpoints", "aptos-mempool/failpoints", "aptos-api/failpoints", "aptos-config/failpoints"] +failpoints = [ + "fail/failpoints", + "aptos-consensus/failpoints", + "aptos-executor/failpoints", + "aptos-mempool/failpoints", + "aptos-api/failpoints", + "aptos-config/failpoints", +] indexer = ["aptos-indexer"] tokio-console = ["aptos-logger/tokio-console", "aptos-config/tokio-console"] smoke-test = ["aptos-jwk-consensus/smoke-test", "aptos-dkg-runtime/smoke-test"] diff --git a/config/global-constants/src/lib.rs b/config/global-constants/src/lib.rs index 8cde7eeabed..f7545840997 100644 --- a/config/global-constants/src/lib.rs +++ b/config/global-constants/src/lib.rs @@ -23,13 +23,15 @@ pub const GENESIS_WAYPOINT: &str = "genesis-waypoint"; #[cfg(any(test, feature = "testing"))] pub const GAS_UNIT_PRICE: u64 = 0; + +/// Increased from 100 to 100_000 in accordance with the outcome of https://vote.supra.com/proposal/3. #[cfg(not(any(test, feature = "testing")))] -pub const GAS_UNIT_PRICE: u64 = 100; +pub const GAS_UNIT_PRICE: u64 = 100_000; #[cfg(any(test, feature = "testing"))] -pub const MAX_GAS_AMOUNT: u64 = 100_000_000; +pub const MAX_GAS_AMOUNT: u64 = 100_000_000_000; #[cfg(not(any(test, feature = "testing")))] -pub const MAX_GAS_AMOUNT: u64 = 2_000_000; +pub const MAX_GAS_AMOUNT: u64 = 2_000_000_000; pub const GAS_HEADROOM_NUMERATOR: u64 = 3; pub const GAS_HEADROOM_DENOMINATOR: u64 = 2; diff --git a/config/src/config/api_config.rs b/config/src/config/api_config.rs index d736dad227e..1c8e89a5c9d 100644 --- a/config/src/config/api_config.rs +++ b/config/src/config/api_config.rs @@ -98,7 +98,7 @@ pub const DEFAULT_MAX_SUBMIT_TRANSACTION_BATCH_SIZE: usize = 10; pub const DEFAULT_MAX_PAGE_SIZE: u16 = 100; const DEFAULT_MAX_ACCOUNT_RESOURCES_PAGE_SIZE: u16 = 9999; const DEFAULT_MAX_ACCOUNT_MODULES_PAGE_SIZE: u16 = 9999; -const DEFAULT_MAX_VIEW_GAS: u64 = 2_000_000; // We keep this value the same as the max number of gas allowed for one single transaction defined in aptos-gas. +const DEFAULT_MAX_VIEW_GAS: u64 = 2_000_000_000; // We keep this value the same as the max number of gas allowed for one single transaction defined in aptos-gas. fn default_enabled() -> bool { true diff --git a/consensus/Cargo.toml b/consensus/Cargo.toml index 4c0fcf6204c..6ca1102e505 100644 --- a/consensus/Cargo.toml +++ b/consensus/Cargo.toml @@ -110,12 +110,12 @@ tempfile = { workspace = true } [features] default = [] fuzzing = [ - "aptos-consensus-types/fuzzing", - "aptos-config/fuzzing", - "aptos-crypto/fuzzing", - "aptos-mempool/fuzzing", - "aptos-types/fuzzing", - "aptos-safety-rules/testing", + "aptos-consensus-types/fuzzing", + "aptos-config/fuzzing", + "aptos-crypto/fuzzing", + "aptos-mempool/fuzzing", + "aptos-types/fuzzing", + "aptos-safety-rules/testing", ] failpoints = ["fail/failpoints"] diff --git a/consensus/consensus-types/src/round_timeout.rs b/consensus/consensus-types/src/round_timeout.rs index bbe96751861..3f662501371 100644 --- a/consensus/consensus-types/src/round_timeout.rs +++ b/consensus/consensus-types/src/round_timeout.rs @@ -101,7 +101,7 @@ impl RoundTimeout { self.author(), &self.timeout.signing_format(), // &self.signature, - &aptos_crypto::ed25519::Signature::dummy_signature() + &aptos_crypto::ed25519::Signature::dummy_signature(), ) .context("Failed to verify 2-chain timeout signature")?; Ok(()) diff --git a/consensus/safety-rules/src/persistent_safety_storage.rs b/consensus/safety-rules/src/persistent_safety_storage.rs index c74ebd7ecf6..c22f8bda01d 100644 --- a/consensus/safety-rules/src/persistent_safety_storage.rs +++ b/consensus/safety-rules/src/persistent_safety_storage.rs @@ -96,9 +96,7 @@ impl PersistentSafetyStorage { Ok(self.internal_store.get(OWNER_ACCOUNT).map(|v| v.value)?) } - pub fn default_consensus_sk( - &self, - ) -> Result { + pub fn default_consensus_sk(&self) -> Result { self.internal_store .get::(CONSENSUS_KEY) .map(|v| v.value) diff --git a/consensus/src/epoch_manager.rs b/consensus/src/epoch_manager.rs index 90b2f23f59d..900fa975c2d 100644 --- a/consensus/src/epoch_manager.rs +++ b/consensus/src/epoch_manager.rs @@ -1936,8 +1936,7 @@ impl EpochManager

{ fn load_consensus_key(&self, vv: &ValidatorVerifier) -> anyhow::Result { match vv.get_public_key(&self.author) { - Some(pk) => - self + Some(pk) => self .key_storage .consensus_sk_by_pk(pk) .map_err(|e| anyhow!("could not find sk by pk: {:?}", e)), diff --git a/consensus/src/payload_client/mixed.rs b/consensus/src/payload_client/mixed.rs index bb9c38c80cc..e0fa87a789b 100644 --- a/consensus/src/payload_client/mixed.rs +++ b/consensus/src/payload_client/mixed.rs @@ -38,15 +38,15 @@ impl MixedPayloadClient { /// When enabled in smoke tests, generate 2 random validator transactions, 1 valid, 1 invalid. fn extra_test_only_vtxns(&self) -> Vec { fail_point!("mixed_payload_client::extra_test_only_vtxns", |_| { - use aptos_types::dkg::{DKGTranscript, DKGTranscriptMetadata}; + use aptos_types::dkg::{DKGTransactionData, DKGTransactionMetadata}; use move_core_types::account_address::AccountAddress; - vec![ValidatorTransaction::DKGResult(DKGTranscript { - metadata: DKGTranscriptMetadata { + vec![ValidatorTransaction::DKG(DKGTransactionData { + metadata: DKGTransactionMetadata { epoch: 999, author: AccountAddress::ZERO, }, - transcript_bytes: vec![], + data_bytes: vec![], })] }); vec![] diff --git a/consensus/src/quorum_store/counters.rs b/consensus/src/quorum_store/counters.rs index 7ba529e4b9f..73f77a0f9e0 100644 --- a/consensus/src/quorum_store/counters.rs +++ b/consensus/src/quorum_store/counters.rs @@ -93,7 +93,6 @@ pub static PROOF_MANAGER_MAIN_LOOP: Lazy = Lazy::new(|| { ) }); - pub static PROOF_QUEUE_ADD_BATCH_SUMMARIES_DURATION: Lazy = Lazy::new(|| { DurationHistogram::new( register_histogram!( diff --git a/consensus/src/util/mod.rs b/consensus/src/util/mod.rs index 49759b4bc82..9f015a4dffd 100644 --- a/consensus/src/util/mod.rs +++ b/consensus/src/util/mod.rs @@ -19,6 +19,7 @@ pub fn is_vtxn_expected( vtxn: &ValidatorTransaction, ) -> bool { match vtxn { + ValidatorTransaction::DKG(_) => randomness_config.randomness_enabled(), ValidatorTransaction::DKGResult(_) => randomness_config.randomness_enabled(), ValidatorTransaction::ObservedJWKUpdate(_) => jwk_consensus_config.jwk_consensus_enabled(), } diff --git a/crates/aptos-collections/Cargo.toml b/crates/aptos-collections/Cargo.toml index 69c953a35c6..ee1d4db9107 100644 --- a/crates/aptos-collections/Cargo.toml +++ b/crates/aptos-collections/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aptos-collections" -description = "Aptos Collections Library" +description = "Aptos Collections Library" version = "0.1.0" # Workspace inherited keys diff --git a/crates/aptos-crypto/Cargo.toml b/crates/aptos-crypto/Cargo.toml index 5437518b8ee..5e1ab257600 100644 --- a/crates/aptos-crypto/Cargo.toml +++ b/crates/aptos-crypto/Cargo.toml @@ -59,6 +59,11 @@ static_assertions = { workspace = true } thiserror = { workspace = true } tiny-keccak = { workspace = true } typenum = { workspace = true } +utoipa = { features = [ + "non_strict_integers", + "preserve_order", + "uuid", +], optional = true, workspace = true } x25519-dalek = { workspace = true } [dev-dependencies] @@ -82,6 +87,7 @@ default = [] assert-private-keys-not-cloneable = [] cloneable-private-keys = [] fuzzing = ["proptest", "proptest-derive", "cloneable-private-keys", "arbitrary"] +rest_api_schema = ["utoipa"] testing = [] [[bench]] diff --git a/crates/aptos-crypto/src/hash.rs b/crates/aptos-crypto/src/hash.rs index 2f6af1f086a..910ebe19e48 100644 --- a/crates/aptos-crypto/src/hash.rs +++ b/crates/aptos-crypto/src/hash.rs @@ -113,7 +113,7 @@ use std::{ fmt, str::FromStr, }; -use tiny_keccak::{Hasher, Sha3, Keccak}; +use tiny_keccak::{Hasher, Keccak, Sha3}; /// A prefix used to begin the salt of every hashable structure. The salt /// consists in this global prefix, concatenated with the specified @@ -123,6 +123,8 @@ pub(crate) const HASH_PREFIX: &[u8] = b"SUPRA::"; /// Output value of our hash function. Intentionally opaque for safety and modularity. #[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)] #[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(feature = "rest_api_schema", derive(utoipa::ToSchema))] +#[cfg_attr(feature = "rest_api_schema",schema(as = String))] pub struct HashValue { hash: [u8; HashValue::LENGTH], } @@ -190,6 +192,7 @@ impl HashValue { /// Convenience function that sha3_256 the set of buffers #[cfg(test)] + #[allow(missing_docs)] pub fn from_iter_sha3<'a, I>(buffers: I) -> Self where I: IntoIterator, diff --git a/crates/aptos-dkg/Cargo.toml b/crates/aptos-dkg/Cargo.toml index e6463336d18..2cc7a50c461 100644 --- a/crates/aptos-dkg/Cargo.toml +++ b/crates/aptos-dkg/Cargo.toml @@ -9,7 +9,7 @@ anyhow = { workspace = true } aptos-crypto = { workspace = true } aptos-crypto-derive = { workspace = true } aptos-runtimes = { workspace = true } -bcs = { workspace = true } +bcs = { workspace = true } blst = { workspace = true } blstrs = { workspace = true } criterion = { workspace = true } diff --git a/crates/aptos-faucet/cli/Cargo.toml b/crates/aptos-faucet/cli/Cargo.toml index f68cf9a2984..630ebae285c 100644 --- a/crates/aptos-faucet/cli/Cargo.toml +++ b/crates/aptos-faucet/cli/Cargo.toml @@ -19,4 +19,3 @@ aptos-logger = { workspace = true } aptos-sdk = { workspace = true } clap = { workspace = true } tokio = { workspace = true } - diff --git a/crates/aptos-faucet/core/Cargo.toml b/crates/aptos-faucet/core/Cargo.toml index a921c24750b..080e7eadbc3 100644 --- a/crates/aptos-faucet/core/Cargo.toml +++ b/crates/aptos-faucet/core/Cargo.toml @@ -17,12 +17,14 @@ anyhow = { workspace = true } aptos-config = { workspace = true } aptos-faucet-metrics-server = { workspace = true } aptos-logger = { workspace = true } -aptos-metrics-core = { workspace = true } +aptos-metrics-core = { workspace = true } aptos-sdk = { workspace = true } async-trait = { workspace = true } captcha = { version = "0.0.9" } clap = { workspace = true } -deadpool-redis = { version = "0.11.1", features = ["rt_tokio_1"], default-features = false } +deadpool-redis = { version = "0.11.1", features = [ + "rt_tokio_1", +], default-features = false } enum_dispatch = { workspace = true } firebase-token = { workspace = true } futures = { workspace = true } @@ -34,7 +36,11 @@ once_cell = { workspace = true } poem = { workspace = true } poem-openapi = { workspace = true } rand = { workspace = true } -redis = { workspace = true, features = ["aio", "tokio-comp", "connection-manager"] } +redis = { workspace = true, features = [ + "aio", + "tokio-comp", + "connection-manager", +] } reqwest = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } diff --git a/crates/aptos-faucet/metrics-server/Cargo.toml b/crates/aptos-faucet/metrics-server/Cargo.toml index 3b779539d43..f427e211160 100644 --- a/crates/aptos-faucet/metrics-server/Cargo.toml +++ b/crates/aptos-faucet/metrics-server/Cargo.toml @@ -15,7 +15,7 @@ rust-version = { workspace = true } [dependencies] anyhow = { workspace = true } aptos-logger = { workspace = true } -aptos-metrics-core = { workspace = true } +aptos-metrics-core = { workspace = true } once_cell = { workspace = true } poem = { workspace = true } prometheus = { workspace = true } diff --git a/crates/aptos-genesis/src/builder.rs b/crates/aptos-genesis/src/builder.rs index 275a69557d8..f94d9eb975a 100644 --- a/crates/aptos-genesis/src/builder.rs +++ b/crates/aptos-genesis/src/builder.rs @@ -30,8 +30,9 @@ use aptos_types::{ jwks::patch::IssuerJWK, keyless::Groth16VerificationKey, on_chain_config::{ - Features, GasScheduleV2, OnChainConsensusConfig, OnChainExecutionConfig, - OnChainJWKConsensusConfig, OnChainRandomnessConfig, + AutomationRegistryConfig, BanRegistryParameters, Features, GasScheduleV2, + OnChainConsensusConfig, OnChainExecutionConfig, OnChainJWKConsensusConfig, + OnChainRandomnessConfig, }, transaction::Transaction, waypoint::Waypoint, @@ -47,7 +48,6 @@ use std::{ path::{Path, PathBuf}, sync::Arc, }; -use aptos_types::on_chain_config::AutomationRegistryConfig; const VALIDATOR_IDENTITY: &str = "validator-identity.yaml"; const VFN_IDENTITY: &str = "vfn-identity.yaml"; @@ -444,6 +444,7 @@ pub struct GenesisConfiguration { pub randomness_config_override: Option, pub jwk_consensus_config_override: Option, pub automation_registry_config: Option, + pub leader_ban_registry_config: Option, pub initial_jwks: Vec, pub keyless_groth16_vk: Option, } @@ -670,6 +671,7 @@ impl Builder { randomness_config_override: None, jwk_consensus_config_override: None, automation_registry_config: Some(AutomationRegistryConfig::default()), + leader_ban_registry_config: Some(BanRegistryParameters::default()), initial_jwks: vec![], keyless_groth16_vk: None, }; diff --git a/crates/aptos-genesis/src/config.rs b/crates/aptos-genesis/src/config.rs index 268b7e0a70b..160351500ee 100644 --- a/crates/aptos-genesis/src/config.rs +++ b/crates/aptos-genesis/src/config.rs @@ -9,7 +9,10 @@ use aptos_types::{ jwks::patch::IssuerJWK, keyless::Groth16VerificationKey, network_address::{DnsName, NetworkAddress, Protocol}, - on_chain_config::{OnChainConsensusConfig, OnChainExecutionConfig, OnChainJWKConsensusConfig}, + on_chain_config::{ + AutomationRegistryConfig, BanRegistryParameters, OnChainConsensusConfig, + OnChainExecutionConfig, OnChainJWKConsensusConfig, + }, transaction::authenticator::AuthenticationKey, }; use aptos_vm_genesis::{AccountBalance, EmployeePool, Validator, ValidatorWithCommissionRate}; @@ -23,7 +26,6 @@ use std::{ path::Path, str::FromStr, }; -use aptos_types::on_chain_config::AutomationRegistryConfig; /// Template for setting up Github for Genesis /// @@ -86,6 +88,8 @@ pub struct Layout { pub jwk_consensus_config_override: Option, /// An optional supra native automation config. pub automation_registry_config: Option, + /// An optional supra leader ban config. + pub leader_ban_registry_config: Option, /// JWKs to patch in genesis. #[serde(default)] @@ -137,6 +141,7 @@ impl Default for Layout { on_chain_execution_config: OnChainExecutionConfig::default_for_genesis(), jwk_consensus_config_override: None, automation_registry_config: Some(AutomationRegistryConfig::default()), + leader_ban_registry_config: Some(BanRegistryParameters::default()), initial_jwks: vec![], keyless_groth16_vk_override: None, } diff --git a/crates/aptos-genesis/src/lib.rs b/crates/aptos-genesis/src/lib.rs index 7d7851b53b4..419736400f0 100644 --- a/crates/aptos-genesis/src/lib.rs +++ b/crates/aptos-genesis/src/lib.rs @@ -27,7 +27,9 @@ use aptos_types::{ jwks::patch::IssuerJWK, keyless::Groth16VerificationKey, on_chain_config::{ - Features, GasScheduleV2, OnChainConsensusConfig, OnChainExecutionConfig, OnChainJWKConsensusConfig, OnChainRandomnessConfig + AutomationRegistryConfig, BanRegistryParameters, Features, GasScheduleV2, + OnChainConsensusConfig, OnChainExecutionConfig, OnChainJWKConsensusConfig, + OnChainRandomnessConfig, }, transaction::Transaction, waypoint::Waypoint, @@ -35,7 +37,6 @@ use aptos_types::{ use aptos_vm::aptos_vm::AptosVMBlockExecutor; use aptos_vm_genesis::Validator; use std::convert::TryInto; -use aptos_types::on_chain_config::AutomationRegistryConfig; /// Holder object for all pieces needed to generate a genesis transaction #[derive(Clone)] @@ -84,6 +85,7 @@ pub struct GenesisInfo { pub randomness_config_override: Option, pub jwk_consensus_config_override: Option, pub automation_registry_config: Option, + pub leader_ban_registry_config: Option, pub initial_jwks: Vec, pub keyless_groth16_vk: Option, } @@ -128,6 +130,7 @@ impl GenesisInfo { randomness_config_override: genesis_config.randomness_config_override.clone(), jwk_consensus_config_override: genesis_config.jwk_consensus_config_override.clone(), automation_registry_config: genesis_config.automation_registry_config.clone(), + leader_ban_registry_config: genesis_config.leader_ban_registry_config.clone(), initial_jwks: genesis_config.initial_jwks.clone(), keyless_groth16_vk: genesis_config.keyless_groth16_vk.clone(), }) @@ -173,6 +176,7 @@ impl GenesisInfo { jwk_consensus_config_override: self.jwk_consensus_config_override.clone(), genesis_timestamp_in_microseconds: self.genesis_timestamp_in_microseconds, automation_registry_config: self.automation_registry_config.clone(), + leader_ban_registry_config: self.leader_ban_registry_config.clone(), initial_jwks: self.initial_jwks.clone(), keyless_groth16_vk: self.keyless_groth16_vk.clone(), }, @@ -181,6 +185,8 @@ impl GenesisInfo { &self.gas_schedule, b"test".to_vec(), None, + None, + None, ) } diff --git a/crates/aptos-genesis/src/mainnet.rs b/crates/aptos-genesis/src/mainnet.rs index b9d10ea9976..8bd8595033d 100644 --- a/crates/aptos-genesis/src/mainnet.rs +++ b/crates/aptos-genesis/src/mainnet.rs @@ -13,11 +13,13 @@ use aptos_temppath::TempPath; use aptos_types::{ account_address::AccountAddress, chain_id::ChainId, - on_chain_config::{Features, OnChainJWKConsensusConfig, OnChainRandomnessConfig}, + on_chain_config::{ + AutomationRegistryConfig, BanRegistryParameters, Features, OnChainJWKConsensusConfig, + OnChainRandomnessConfig, + }, transaction::Transaction, waypoint::Waypoint, }; -use aptos_types::on_chain_config::AutomationRegistryConfig; use aptos_vm::aptos_vm::AptosVMBlockExecutor; use aptos_vm_genesis::{AccountBalance, EmployeePool, ValidatorWithCommissionRate}; @@ -72,6 +74,8 @@ pub struct MainnetGenesisInfo { jwk_consensus_config_override: Option, /// Supra native automation feature configuration parameters automation_registry_config: Option, + /// Supra native consensus leader ban registry configuration parameters + leader_ban_registry_config: Option, } impl MainnetGenesisInfo { @@ -117,6 +121,7 @@ impl MainnetGenesisInfo { randomness_config_override: genesis_config.randomness_config_override.clone(), jwk_consensus_config_override: genesis_config.jwk_consensus_config_override.clone(), automation_registry_config: genesis_config.automation_registry_config.clone(), + leader_ban_registry_config: genesis_config.leader_ban_registry_config.clone(), }) } @@ -161,6 +166,7 @@ impl MainnetGenesisInfo { randomness_config_override: self.randomness_config_override.clone(), jwk_consensus_config_override: self.jwk_consensus_config_override.clone(), automation_registry_config: self.automation_registry_config.clone(), + leader_ban_registry_config: self.leader_ban_registry_config.clone(), initial_jwks: vec![], keyless_groth16_vk: None, }, diff --git a/crates/aptos-id-generator/Cargo.toml b/crates/aptos-id-generator/Cargo.toml index 89eb2315b9e..332cbb108c7 100644 --- a/crates/aptos-id-generator/Cargo.toml +++ b/crates/aptos-id-generator/Cargo.toml @@ -13,4 +13,3 @@ repository = { workspace = true } rust-version = { workspace = true } [dependencies] - diff --git a/crates/aptos-infallible/Cargo.toml b/crates/aptos-infallible/Cargo.toml index 822c9b1c376..ea7cc093ce8 100644 --- a/crates/aptos-infallible/Cargo.toml +++ b/crates/aptos-infallible/Cargo.toml @@ -13,4 +13,3 @@ repository = { workspace = true } rust-version = { workspace = true } [dependencies] - diff --git a/crates/aptos-keygen/Cargo.toml b/crates/aptos-keygen/Cargo.toml index f58044df02a..abea0439347 100644 --- a/crates/aptos-keygen/Cargo.toml +++ b/crates/aptos-keygen/Cargo.toml @@ -16,4 +16,3 @@ rust-version = { workspace = true } aptos-crypto = { workspace = true } aptos-types = { workspace = true } rand = { workspace = true } - diff --git a/crates/aptos-log-derive/Cargo.toml b/crates/aptos-log-derive/Cargo.toml index 65ba47e3e65..4ada1edf6a8 100644 --- a/crates/aptos-log-derive/Cargo.toml +++ b/crates/aptos-log-derive/Cargo.toml @@ -19,5 +19,3 @@ proc-macro = true proc-macro2 = { workspace = true } quote = { workspace = true } syn = { workspace = true } - - diff --git a/crates/aptos-network-checker/Cargo.toml b/crates/aptos-network-checker/Cargo.toml index b8941edb57c..361eae8246b 100644 --- a/crates/aptos-network-checker/Cargo.toml +++ b/crates/aptos-network-checker/Cargo.toml @@ -23,4 +23,3 @@ clap = { workspace = true } futures = { workspace = true } serde = { workspace = true } tokio = { workspace = true } - diff --git a/crates/aptos-profiler/Cargo.toml b/crates/aptos-profiler/Cargo.toml index 653ca7e7741..5e15644e89a 100644 --- a/crates/aptos-profiler/Cargo.toml +++ b/crates/aptos-profiler/Cargo.toml @@ -23,4 +23,3 @@ jemallocator = { version = "0.5.0", features = [ "unprefixed_malloc_on_supported_platforms", ] } jemalloc-sys = "0.5.4" - diff --git a/crates/aptos-proptest-helpers/Cargo.toml b/crates/aptos-proptest-helpers/Cargo.toml index 4e1bc94c076..584d9c3bbca 100644 --- a/crates/aptos-proptest-helpers/Cargo.toml +++ b/crates/aptos-proptest-helpers/Cargo.toml @@ -16,5 +16,3 @@ rust-version = { workspace = true } crossbeam = { workspace = true } proptest = { workspace = true } proptest-derive = { workspace = true } - - diff --git a/crates/aptos-rate-limiter/Cargo.toml b/crates/aptos-rate-limiter/Cargo.toml index 3de9cdfca4f..c277d90e4c7 100644 --- a/crates/aptos-rate-limiter/Cargo.toml +++ b/crates/aptos-rate-limiter/Cargo.toml @@ -20,4 +20,3 @@ futures = { workspace = true } pin-project = { workspace = true } tokio = { workspace = true } tokio-util = { workspace = true } - diff --git a/crates/aptos-retrier/Cargo.toml b/crates/aptos-retrier/Cargo.toml index 8eccb8ac672..a7c809a2e03 100644 --- a/crates/aptos-retrier/Cargo.toml +++ b/crates/aptos-retrier/Cargo.toml @@ -15,4 +15,3 @@ rust-version = { workspace = true } [dependencies] aptos-logger = { workspace = true } tokio = { workspace = true } - diff --git a/crates/aptos-rosetta-cli/Cargo.toml b/crates/aptos-rosetta-cli/Cargo.toml index ff37ec922ae..e9bf998b7b3 100644 --- a/crates/aptos-rosetta-cli/Cargo.toml +++ b/crates/aptos-rosetta-cli/Cargo.toml @@ -23,4 +23,3 @@ serde = { workspace = true } serde_json = { workspace = true } tokio = { workspace = true } url = { workspace = true } - diff --git a/crates/aptos-rosetta/src/types/objects.rs b/crates/aptos-rosetta/src/types/objects.rs index 1620dfb7b93..ab23704afe7 100644 --- a/crates/aptos-rosetta/src/types/objects.rs +++ b/crates/aptos-rosetta/src/types/objects.rs @@ -957,8 +957,7 @@ impl Transaction { (TransactionType::Validator, None, None, txn.info, txn.events) }, BlockEpilogue(_) => (TransactionType::BlockEpilogue, None, None, txn.info, vec![]), - AutomatedTransaction(automated_txn) - | SystemAutomatedTransaction(automated_txn)=> ( + AutomatedTransaction(automated_txn) | SystemAutomatedTransaction(automated_txn) => ( TransactionType::Automated, None, Some(automated_txn), @@ -971,7 +970,7 @@ impl Transaction { None, txn.info, txn.events, - ) + ), }; // Operations must be sequential and operation index must always be in the same order diff --git a/crates/aptos-telemetry-service/src/validator_cache.rs b/crates/aptos-telemetry-service/src/validator_cache.rs index 53afae31d1a..a4fbcd7dc4d 100644 --- a/crates/aptos-telemetry-service/src/validator_cache.rs +++ b/crates/aptos-telemetry-service/src/validator_cache.rs @@ -199,7 +199,7 @@ mod tests { let validator_info = ValidatorInfo::new( PeerId::random(), 10, - ValidatorConfig::new(keypair.public_key, vec![0, 0], vec![0, 0], 2), + ValidatorConfig::legacy_new_do_not_use(keypair.public_key, vec![0, 0], vec![0, 0], 2), ); let validator_set = ValidatorSet::new(vec![validator_info]); @@ -242,7 +242,7 @@ mod tests { let validator_info = ValidatorInfo::new( PeerId::random(), 10, - ValidatorConfig::new( + ValidatorConfig::legacy_new_do_not_use( keypair.public_key, bcs::to_bytes(&vec![NetworkAddress::from_str("/dns/a5f3d921730874389bb2f66275f163a5-8f14ad5b5e992c1c.elb.ap-southeast-1.amazonaws.com/tcp/6180/noise-ik/0xc5edf62233096df793b554e1013b07c83d01b3cf50c14ac83a0a7e0cfe340426/handshake/0").unwrap()]).unwrap(), bcs::to_bytes(&vec![NetworkAddress::from_str("/dns/fullnode0.testnet.aptoslabs.com/tcp/6182/noise-ik/0xea19ab47ed9191865f15d85d751ed0663205c0b2f0f465714b1947c023715973/handshake/0").unwrap()]).unwrap(), diff --git a/crates/aptos-temppath/Cargo.toml b/crates/aptos-temppath/Cargo.toml index 39341318abf..20aa81dcbc6 100644 --- a/crates/aptos-temppath/Cargo.toml +++ b/crates/aptos-temppath/Cargo.toml @@ -15,5 +15,3 @@ rust-version = { workspace = true } [dependencies] hex = { workspace = true } rand = { workspace = true } - - diff --git a/crates/aptos/Cargo.toml b/crates/aptos/Cargo.toml index ee6c57f41e5..893dcc293ce 100644 --- a/crates/aptos/Cargo.toml +++ b/crates/aptos/Cargo.toml @@ -61,7 +61,9 @@ clap = { workspace = true, features = ["env", "unstable-styles", "wrap_help"] } clap_complete = { workspace = true } colored = { workspace = true } dashmap = { workspace = true } -diesel = { workspace = true, features = ["postgres_backend"] } +diesel = { workspace = true, features = [ + "postgres_backend", +] } diesel-async = { workspace = true } dirs = { workspace = true } futures = { workspace = true } diff --git a/crates/aptos/src/account/balance.rs b/crates/aptos/src/account/balance.rs index 4ef7980a43b..d065dc3469d 100644 --- a/crates/aptos/src/account/balance.rs +++ b/crates/aptos/src/account/balance.rs @@ -5,7 +5,7 @@ use crate::common::types::{ CliCommand, CliConfig, CliError, CliTypedResult, ConfigSearchMode, ProfileOptions, RestOptions, }; use aptos_api_types::ViewFunction; -use aptos_types::{account_address::AccountAddress, SupraCoinType, CoinType}; +use aptos_types::{account_address::AccountAddress, CoinType, SupraCoinType}; use async_trait::async_trait; use clap::Parser; use move_core_types::{ diff --git a/crates/aptos/src/account/multisig_account.rs b/crates/aptos/src/account/multisig_account.rs index f0dbd455662..93a90e6b5ce 100644 --- a/crates/aptos/src/account/multisig_account.rs +++ b/crates/aptos/src/account/multisig_account.rs @@ -16,10 +16,11 @@ use aptos_rest_client::{ aptos_api_types::{HexEncodedBytes, WriteResource, WriteSetChange}, Transaction, }; -use aptos_types::transaction::automation::RegistrationParams; use aptos_types::{ account_address::AccountAddress, - transaction::{Multisig, MultisigTransactionPayload, TransactionPayload}, + transaction::{ + automation::RegistrationParams, Multisig, MultisigTransactionPayload, TransactionPayload, + }, }; use async_trait::async_trait; use bcs::to_bytes; @@ -170,7 +171,7 @@ impl TryFrom for MultisigTransactionPayload { match value { MultisigPayloadVariants::EntryFunction(e) => e.try_into(), MultisigPayloadVariants::GaslessAutomationTask(r) => r.try_into(), - MultisigPayloadVariants::AutomationTask(r) => r.try_into() + MultisigPayloadVariants::AutomationTask(r) => r.try_into(), } } } @@ -234,7 +235,7 @@ impl TryFrom for MultisigTransactionPayload type Error = CliError; fn try_from( - value: AutomationTaskRegistrationArguments + value: AutomationTaskRegistrationArguments, ) -> Result { let automation_function = value.automation_function.try_into()?; let registration_params = RegistrationParams::new_user_automation_task_v2( @@ -252,7 +253,6 @@ impl TryFrom for MultisigTransactionPayload } } - /// Propose a new multisig transaction. /// /// As one of the owners of the multisig, propose a new transaction. This also implicitly approves @@ -271,7 +271,6 @@ pub struct CreateTransaction { pub(crate) store_hash_only: bool, } - #[async_trait] impl CliCommand for CreateTransaction { fn command_name(&self) -> &'static str { @@ -325,8 +324,6 @@ impl SupraCommand for CreateTransaction { } } - - /// Verify entry function matches on-chain transaction proposal. #[derive(Debug, Parser)] pub struct VerifyProposal { diff --git a/crates/aptos/src/common/types.rs b/crates/aptos/src/common/types.rs index 66d9f530cc5..85103254ee2 100644 --- a/crates/aptos/src/common/types.rs +++ b/crates/aptos/src/common/types.rs @@ -26,6 +26,7 @@ use aptos_api_types::ViewFunction; use aptos_crypto::{ ed25519::{Ed25519PrivateKey, Ed25519PublicKey, Ed25519Signature}, encoding_type::{EncodingError, EncodingType}, + hash::HashValueParseError, x25519, PrivateKey, ValidCryptoMaterialStringExt, }; use aptos_framework::chunked_publish::{ @@ -79,9 +80,8 @@ use std::{ str::FromStr, time::{Duration, Instant, SystemTime, UNIX_EPOCH}, }; -use thiserror::Error; -use aptos_crypto::hash::HashValueParseError; use supra_aptos::ApiVersion; +use thiserror::Error; pub const USER_AGENT: &str = concat!("aptos-cli/", env!("CARGO_PKG_VERSION")); pub const US_IN_SECS: u64 = 1_000_000; @@ -1110,7 +1110,7 @@ pub struct RestOptions { /// environment variable. #[clap(long, env)] pub node_api_key: Option, - #[clap(long, default_value_t = ApiVersion::V3)] + #[clap(long, default_value_t = ApiVersion::V3)] pub(crate) api_version: ApiVersion, } @@ -1120,7 +1120,7 @@ impl Default for RestOptions { rpc_url: None, connection_timeout_secs: DEFAULT_EXPIRATION_SECS, node_api_key: None, - api_version: Default::default() + api_version: Default::default(), } } } @@ -2112,7 +2112,7 @@ impl TransactionOptions { // Fetch the chain states required for the simulation // TODO(Gas): get the following from the chain const DEFAULT_GAS_UNIT_PRICE: u64 = 100; - const DEFAULT_MAX_GAS: u64 = 2_000_000; + const DEFAULT_MAX_GAS: u64 = 2_000_000_000; let (sender_key, sender_address) = self.get_key_and_address()?; let gas_unit_price = self @@ -2282,9 +2282,10 @@ impl MultisigAccountWithSequenceNumber { #[derive(Clone, Debug, Default, Parser)] pub struct TypeArgVec { - /// TypeTag arguments separated by spaces. + /// Type arguments for generic type parameters in Move functions, separated by spaces. + /// Commonly used to specify coin types, resource types, or other struct types. /// - /// Example: `u8 u16 u32 u64 u128 u256 bool address vector signer` + /// Example: `0x1::supra_coin::SupraCoin` #[clap(long, num_args = 0..)] pub(crate) type_args: Vec, } diff --git a/crates/aptos/src/genesis/mod.rs b/crates/aptos/src/genesis/mod.rs index 7cfd244452f..8e0d76d0949 100644 --- a/crates/aptos/src/genesis/mod.rs +++ b/crates/aptos/src/genesis/mod.rs @@ -262,6 +262,7 @@ pub fn fetch_mainnet_genesis_info(git_options: GitOptions) -> CliTypedResult CliTypedResult> for SubmitVote { summaries.push( self.args .txn_options - .submit_transaction(aptos_stdlib::supra_governance_supra_vote( - proposal_id, - vote, - )) + .submit_transaction(aptos_stdlib::supra_governance_supra_vote(proposal_id, vote)) .await .map(TransactionSummary::from)?, ); @@ -751,14 +751,13 @@ impl SupraCommand for SubmitVote { let vote = self.args.yes; let proposal_id = self.args.proposal_id; - let payload = aptos_stdlib::supra_governance_supra_vote( - proposal_id, - vote, - ); + let payload = aptos_stdlib::supra_governance_supra_vote(proposal_id, vote); Ok(SupraCommandArguments { payload, sender_account: self.args.txn_options.sender_account, - profile_options: supra_aptos::ProfileOptions::from(self.args.txn_options.profile_options), + profile_options: supra_aptos::ProfileOptions::from( + self.args.txn_options.profile_options, + ), rest_options: supra_aptos::RestOptions::from(self.args.txn_options.rest_options), gas_options: supra_aptos::GasOptions::from(self.args.txn_options.gas_options), }) @@ -787,7 +786,9 @@ impl CliCommand for ApproveExecutionHash { Ok(self .txn_options .submit_transaction( - aptos_stdlib::supra_governance_add_supra_approved_script_hash_script(self.proposal_id), + aptos_stdlib::supra_governance_add_supra_approved_script_hash_script( + self.proposal_id, + ), ) .await .map(TransactionSummary::from)?) @@ -797,8 +798,9 @@ impl CliCommand for ApproveExecutionHash { #[async_trait] impl SupraCommand for ApproveExecutionHash { async fn supra_command_arguments(self) -> anyhow::Result { - let payload = aptos_stdlib::supra_governance_add_supra_approved_script_hash_script(self.proposal_id); - Ok(SupraCommandArguments{ + let payload = + aptos_stdlib::supra_governance_add_supra_approved_script_hash_script(self.proposal_id); + Ok(SupraCommandArguments { payload, sender_account: self.txn_options.sender_account, profile_options: supra_aptos::ProfileOptions::from(self.txn_options.profile_options), @@ -960,7 +962,7 @@ impl SupraCommand for ExecuteProposal { let args = vec![TransactionArgument::U64(self.proposal_id)]; let payload = TransactionPayload::Script(Script::new(bytecode, vec![], args)); - Ok(SupraCommandArguments{ + Ok(SupraCommandArguments { payload, sender_account: self.txn_options.sender_account, profile_options: supra_aptos::ProfileOptions::from(self.txn_options.profile_options), @@ -1117,7 +1119,7 @@ impl CliCommand<()> for GenerateUpgradeProposal { output, testnet, next_execution_hash, - proposal_type + proposal_type, } = self; let package_path = move_options.get_package_path()?; let options = included_artifacts.build_options(&move_options)?; diff --git a/crates/aptos/src/lib.rs b/crates/aptos/src/lib.rs index c4ed1e27084..aec2f8e97dd 100644 --- a/crates/aptos/src/lib.rs +++ b/crates/aptos/src/lib.rs @@ -12,11 +12,11 @@ pub mod move_tool; pub mod node; pub mod op; pub mod stake; +pub mod supra_specific; #[cfg(any(test, feature = "fuzzing"))] pub mod test; pub mod update; pub mod workspace; -pub mod supra_specific; use crate::common::{ types::{CliCommand, CliResult, CliTypedResult}, diff --git a/crates/aptos/src/move_tool/coverage.rs b/crates/aptos/src/move_tool/coverage.rs index c370ca2e429..9dd5b86e598 100644 --- a/crates/aptos/src/move_tool/coverage.rs +++ b/crates/aptos/src/move_tool/coverage.rs @@ -209,7 +209,7 @@ fn compile_coverage( /// Computes coverage for a package /// /// Computes coverage on a previous unit test run for a package. Coverage input must -/// first be built with `aptos move test --coverage` +/// first be built with `supra move tool test --coverage` #[derive(Subcommand)] pub enum CoveragePackage { Summary(SummaryCoverage), diff --git a/crates/aptos/src/move_tool/mod.rs b/crates/aptos/src/move_tool/mod.rs index 84d362b3ed0..159b4059aaa 100644 --- a/crates/aptos/src/move_tool/mod.rs +++ b/crates/aptos/src/move_tool/mod.rs @@ -76,8 +76,8 @@ use std::{ str::FromStr, }; pub use stored_package::*; -use tokio::task; use supra_aptos::{SupraCommand, SupraCommandArguments}; +use tokio::task; use url::Url; pub mod aptos_debug_natives; @@ -210,7 +210,8 @@ impl FrameworkPackageArgs { prompt_options: PromptOptions, ) -> CliTypedResult<()> { const SUPRA_FRAMEWORK: &str = "SupraFramework"; - const SUPRA_FRAMEWORK_GIT_PATH: &str = "https://github.com/Entropy-Foundation/aptos-core.git"; + const SUPRA_FRAMEWORK_GIT_PATH: &str = + "https://github.com/Entropy-Foundation/aptos-core.git"; const SUBDIR_PATH: &str = "aptos-move/framework/supra-framework"; const DEFAULT_BRANCH: &str = "dev"; @@ -441,7 +442,7 @@ impl CliCommand> for CompilePackage { /// Compiles a Move script into bytecode /// /// Compiles a script into bytecode and provides a hash of the bytecode. -/// This can then be run with `aptos move run-script` +/// This can then be run with `supra move tool run-script` #[derive(Parser)] pub struct CompileScript { #[clap(long, value_parser)] @@ -532,7 +533,7 @@ pub struct TestPackage { )] pub instruction_execution_bound: u64, - /// Collect coverage information for later use with the various `aptos move coverage` subcommands + /// Collect coverage information for later use with the various `supra move tool coverage` subcommands #[clap(long = "coverage")] pub compute_coverage: bool, @@ -638,7 +639,7 @@ impl CliCommand<&'static str> for TestPackage { }; summary.coverage()?; - println!("Please use `aptos move coverage -h` for more detailed source or bytecode test coverage of this package"); + println!("Please use `supra move tool coverage -h` for more detailed source or bytecode test coverage of this package"); } match result { @@ -894,10 +895,7 @@ impl FromStr for IncludedArtifacts { } impl IncludedArtifacts { - pub fn build_options( - self, - move_options: &MovePackageOptions, - ) -> CliTypedResult { + pub fn build_options(self, move_options: &MovePackageOptions) -> CliTypedResult { self.build_options_with_experiments(move_options, vec![], false) } @@ -2775,6 +2773,13 @@ impl ArgWithType { match self._ty { FunctionArgType::Address => self.bcs_value_to_json::(), FunctionArgType::Bool => self.bcs_value_to_json::(), + // The Supra RPC view endpoint expects a `vector` argument as a hex string, not a JSON array of bytes. + FunctionArgType::Hex if self._vector_depth == 0 => { + let bytes = bcs::from_bytes::>(&self.arg) + .map_err(|err| CliError::UnexpectedError(err.to_string()))?; + serde_json::to_value(HexEncodedBytes(bytes).to_string()) + .map_err(|err| CliError::UnexpectedError(err.to_string())) + }, FunctionArgType::Hex => self.bcs_value_to_json::>(), FunctionArgType::String => self.bcs_value_to_json::(), FunctionArgType::U8 => self.bcs_value_to_json::(), diff --git a/crates/aptos/src/move_tool/stored_package.rs b/crates/aptos/src/move_tool/stored_package.rs index 381dffc925d..67289508674 100644 --- a/crates/aptos/src/move_tool/stored_package.rs +++ b/crates/aptos/src/move_tool/stored_package.rs @@ -40,10 +40,7 @@ impl fmt::Display for CachedPackageMetadata<'_> { impl CachedPackageRegistry { pub fn new(inner: PackageRegistry, bytecode: BTreeMap>) -> Self { - Self { - inner, - bytecode, - } + Self { inner, bytecode } } /// Creates a new registry. diff --git a/crates/aptos/src/node/mod.rs b/crates/aptos/src/node/mod.rs index a931e864655..ca986b765b6 100644 --- a/crates/aptos/src/node/mod.rs +++ b/crates/aptos/src/node/mod.rs @@ -902,7 +902,10 @@ impl TryFrom<&ValidatorInfo> for ValidatorInfoSummary { fn try_from(info: &ValidatorInfo) -> Result { let config = info.config(); let config = ValidatorConfig { - consensus_public_key: config.consensus_public_key.to_bytes().to_vec(), + consensus_public_key: config + .legacy_consensus_public_key_do_not_use() + .to_bytes() + .to_vec(), validator_network_addresses: config.validator_network_addresses.clone(), fullnode_network_addresses: config.fullnode_network_addresses.clone(), validator_index: config.validator_index, @@ -921,7 +924,7 @@ impl From<&ValidatorInfoSummary> for ValidatorInfo { ValidatorInfo::new( summary.account_address, summary.consensus_voting_power, - aptos_types::validator_config::ValidatorConfig::new( + aptos_types::validator_config::ValidatorConfig::legacy_new_do_not_use( PublicKey::from_encoded_string(&config.consensus_public_key).unwrap(), bcs::to_bytes(&config.validator_network_addresses).unwrap(), bcs::to_bytes(&config.fullnode_network_addresses).unwrap(), diff --git a/crates/aptos/src/op/key.rs b/crates/aptos/src/op/key.rs index 78961738bb1..85a24dc7dbb 100644 --- a/crates/aptos/src/op/key.rs +++ b/crates/aptos/src/op/key.rs @@ -15,7 +15,9 @@ use crate::{ CliCommand, CliResult, }; use aptos_config::config::{Peer, PeerRole}; -use aptos_crypto::{bls12381, ed25519, encoding_type::EncodingType, x25519, PrivateKey, ValidCryptoMaterial}; +use aptos_crypto::{ + bls12381, ed25519, encoding_type::EncodingType, x25519, PrivateKey, ValidCryptoMaterial, +}; use aptos_genesis::config::HostAndPort; use aptos_types::account_address::{ create_multisig_account_address, from_identity_public_key, AccountAddress, @@ -344,7 +346,10 @@ impl CliCommand> for ExtractPublicKey { .save_params .encoding_options .encoding - .decode_key::("ed25519 private key", private_key_bytes)?; + .decode_key::( + "ed25519 private key", + private_key_bytes, + )?; vec![self.save_params.save_material( &key.public_key(), "ed25519 public key", diff --git a/crates/aptos/src/supra_specific.rs b/crates/aptos/src/supra_specific.rs index 023bca4ff9d..327209fdf9b 100644 --- a/crates/aptos/src/supra_specific.rs +++ b/crates/aptos/src/supra_specific.rs @@ -1,10 +1,15 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + // Copyright © Entropy Foundation use crate::common::types::{GasOptions, ProfileOptions, RestOptions}; impl From for supra_aptos::ProfileOptions { fn from(value: ProfileOptions) -> Self { - Self { profile: value.profile } + Self { + profile: value.profile, + } } } diff --git a/crates/aptos/src/update/tool.rs b/crates/aptos/src/update/tool.rs index 1489efcbbd7..d8848f962e7 100644 --- a/crates/aptos/src/update/tool.rs +++ b/crates/aptos/src/update/tool.rs @@ -3,9 +3,7 @@ // use super::{aptos::AptosUpdateTool, revela::RevelaUpdateTool}; use crate::{ - { - common::types::{CliCommand, CliResult}, - }, + common::types::{CliCommand, CliResult}, update::{ move_mutation_test::MutationTestUpdaterTool, movefmt::FormatterUpdateTool, prover_dependencies::ProverDependencyInstaller, diff --git a/crates/fallible/Cargo.toml b/crates/fallible/Cargo.toml index 6563764a437..7d5b2a7525e 100644 --- a/crates/fallible/Cargo.toml +++ b/crates/fallible/Cargo.toml @@ -14,5 +14,3 @@ rust-version = { workspace = true } [dependencies] thiserror = { workspace = true } - - diff --git a/crates/indexer/Cargo.toml b/crates/indexer/Cargo.toml index 77799b37096..ee12ca227e6 100644 --- a/crates/indexer/Cargo.toml +++ b/crates/indexer/Cargo.toml @@ -29,11 +29,11 @@ bcs = { workspace = true } bigdecimal = { workspace = true } chrono = { workspace = true } diesel = { workspace = true, features = [ - "chrono", - "postgres", - "r2d2", - "numeric", - "serde_json", + "chrono", + "postgres", + "r2d2", + "numeric", + "serde_json", ] } diesel_migrations = { workspace = true } field_count = { workspace = true } diff --git a/crates/indexer/src/indexer/fetcher.rs b/crates/indexer/src/indexer/fetcher.rs index 26418d1e207..4f34674cfc9 100644 --- a/crates/indexer/src/indexer/fetcher.rs +++ b/crates/indexer/src/indexer/fetcher.rs @@ -296,6 +296,9 @@ async fn fetch_nexts( info.block_height = Some(block_height_bcs); info.epoch = Some(epoch_bcs); }, + Transaction::AutomatedTransaction(_) => { + unimplemented!() + }, }; txn }); diff --git a/crates/indexer/src/models/coin_models/account_transactions.rs b/crates/indexer/src/models/coin_models/account_transactions.rs index cea220f9263..a400881bc39 100644 --- a/crates/indexer/src/models/coin_models/account_transactions.rs +++ b/crates/indexer/src/models/coin_models/account_transactions.rs @@ -12,7 +12,7 @@ use crate::{ schema::account_transactions, util::standardize_address, }; -use aptos_api_types::{DeleteResource, Event, Transaction, WriteResource, WriteSetChange}; +use aptos_api_types::{DeleteResource, EventV1, Transaction, WriteResource, WriteSetChange}; use field_count::FieldCount; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -87,7 +87,7 @@ impl AccountTransaction { /// Base case, record event account address. We don't really have to worry about /// objects here because it'll be taken care of in the resource section - fn from_event(event: &Event, txn_version: i64) -> HashMap { + fn from_event(event: &EventV1, txn_version: i64) -> HashMap { let account_address = standardize_address(&event.guid.account_address.to_string()); HashMap::from([((account_address.clone(), txn_version), Self { transaction_version: txn_version, diff --git a/crates/indexer/src/models/coin_models/coin_activities.rs b/crates/indexer/src/models/coin_models/coin_activities.rs index ce5fce1eaa5..82b1bd96aeb 100644 --- a/crates/indexer/src/models/coin_models/coin_activities.rs +++ b/crates/indexer/src/models/coin_models/coin_activities.rs @@ -16,7 +16,7 @@ use crate::{ util::{parse_timestamp, standardize_address, truncate_str}, }; use aptos_api_types::{ - Event as APIEvent, Transaction as APITransaction, TransactionInfo as APITransactionInfo, + EventV1 as APIEvent, Transaction as APITransaction, TransactionInfo as APITransactionInfo, TransactionPayload, UserTransactionRequest, WriteSetChange as APIWriteSetChange, }; use aptos_types::{AptosCoinType, CoinType as CoinTypeTrait}; diff --git a/crates/indexer/src/models/events.rs b/crates/indexer/src/models/events.rs index 6c58e5ba78d..f7fce13875f 100644 --- a/crates/indexer/src/models/events.rs +++ b/crates/indexer/src/models/events.rs @@ -3,7 +3,7 @@ #![allow(clippy::extra_unused_lifetimes)] use super::transactions::TransactionQuery; use crate::{models::transactions::Transaction, schema::events, util::standardize_address}; -use aptos_api_types::Event as APIEvent; +use aptos_api_types::EventV1 as APIEvent; use field_count::FieldCount; use serde::{Deserialize, Serialize}; diff --git a/crates/indexer/src/models/token_models/token_activities.rs b/crates/indexer/src/models/token_models/token_activities.rs index 21da21e3861..297aac61721 100644 --- a/crates/indexer/src/models/token_models/token_activities.rs +++ b/crates/indexer/src/models/token_models/token_activities.rs @@ -10,7 +10,7 @@ use crate::{ schema::token_activities, util::{parse_timestamp, standardize_address}, }; -use aptos_api_types::{Event as APIEvent, Transaction as APITransaction}; +use aptos_api_types::{EventV1 as APIEvent, Transaction as APITransaction}; use bigdecimal::{BigDecimal, Zero}; use field_count::FieldCount; use serde::{Deserialize, Serialize}; diff --git a/crates/indexer/src/models/token_models/v2_token_activities.rs b/crates/indexer/src/models/token_models/v2_token_activities.rs index 7554f0651e1..a4af8c8a8b5 100644 --- a/crates/indexer/src/models/token_models/v2_token_activities.rs +++ b/crates/indexer/src/models/token_models/v2_token_activities.rs @@ -14,7 +14,7 @@ use crate::{ database::PgPoolConnection, models::coin_models::v2_fungible_asset_utils::FungibleAssetEvent, schema::token_activities_v2, util::standardize_address, }; -use aptos_api_types::Event as APIEvent; +use aptos_api_types::EventV1 as APIEvent; use bigdecimal::{BigDecimal, One, Zero}; use field_count::FieldCount; use serde::{Deserialize, Serialize}; diff --git a/crates/indexer/src/models/token_models/v2_token_utils.rs b/crates/indexer/src/models/token_models/v2_token_utils.rs index aa525d20a5b..bf890765162 100644 --- a/crates/indexer/src/models/token_models/v2_token_utils.rs +++ b/crates/indexer/src/models/token_models/v2_token_utils.rs @@ -18,7 +18,7 @@ use crate::{ }, }; use anyhow::{Context, Result}; -use aptos_api_types::{deserialize_from_string, Event, WriteResource}; +use aptos_api_types::{deserialize_from_string, EventV1, WriteResource}; use bigdecimal::BigDecimal; use serde::{Deserialize, Serialize}; use std::{ @@ -352,7 +352,7 @@ pub struct BurnEvent { } impl BurnEvent { - pub fn from_event(event: &Event, txn_version: i64) -> anyhow::Result> { + pub fn from_event(event: &EventV1, txn_version: i64) -> anyhow::Result> { let event_type = event.typ.to_string(); if let Some(V2TokenEvent::BurnEvent(inner)) = V2TokenEvent::from_event(event_type.as_str(), &event.data, txn_version).unwrap() @@ -376,7 +376,7 @@ pub struct TransferEvent { } impl TransferEvent { - pub fn from_event(event: &Event, txn_version: i64) -> anyhow::Result> { + pub fn from_event(event: &EventV1, txn_version: i64) -> anyhow::Result> { let event_type = event.typ.to_string(); if let Some(V2TokenEvent::TransferEvent(inner)) = V2TokenEvent::from_event(event_type.as_str(), &event.data, txn_version).unwrap() diff --git a/crates/indexer/src/models/transactions.rs b/crates/indexer/src/models/transactions.rs index a4db22b704a..a8476104367 100644 --- a/crates/indexer/src/models/transactions.rs +++ b/crates/indexer/src/models/transactions.rs @@ -247,6 +247,7 @@ impl Transaction { vec![], vec![], ), + APITransaction::AutomatedTransaction(_) => (unimplemented!()), } } diff --git a/crates/proxy/Cargo.toml b/crates/proxy/Cargo.toml index bd1266c3491..330c5adf0b6 100644 --- a/crates/proxy/Cargo.toml +++ b/crates/proxy/Cargo.toml @@ -14,5 +14,3 @@ rust-version = { workspace = true } [dependencies] ipnet = { workspace = true } - - diff --git a/crates/supra/src/lib.rs b/crates/supra/src/lib.rs index 0b8f0ed0481..28d297b74e1 100644 --- a/crates/supra/src/lib.rs +++ b/crates/supra/src/lib.rs @@ -4,8 +4,7 @@ // Copyright © Entropy Foundation use anyhow::Result; -use aptos_types::account_address::AccountAddress; -use aptos_types::transaction::TransactionPayload; +use aptos_types::{account_address::AccountAddress, transaction::TransactionPayload}; use async_trait::async_trait; use clap::ValueEnum; use std::fmt::{Display, Formatter}; diff --git a/crates/validator-transaction-pool/src/tests.rs b/crates/validator-transaction-pool/src/tests.rs index 62a7bbca11b..b837794ebc9 100644 --- a/crates/validator-transaction-pool/src/tests.rs +++ b/crates/validator-transaction-pool/src/tests.rs @@ -5,7 +5,7 @@ use crate::{TransactionFilter, VTxnPoolState}; use aptos_channels::{aptos_channel, message_queues::QueueStyle}; use aptos_crypto::hash::CryptoHash; use aptos_types::{ - dkg::DKGTranscript, + dkg::DKGTransactionData, jwks::{dummy_issuer, QuorumCertifiedUpdate}, validator_txn::{Topic, ValidatorTransaction}, }; @@ -21,9 +21,9 @@ use tokio::time::timeout; #[test] fn txn_pull_order_should_be_fifo_except_in_topic_overwriting() { let pool = VTxnPoolState::default(); - let txn_0 = ValidatorTransaction::DKGResult(DKGTranscript::dummy()); + let txn_0 = ValidatorTransaction::DKG(DKGTransactionData::dummy()); let txn_1 = ValidatorTransaction::ObservedJWKUpdate(QuorumCertifiedUpdate::dummy()); - let txn_2 = ValidatorTransaction::DKGResult(DKGTranscript::dummy()); + let txn_2 = ValidatorTransaction::DKG(DKGTransactionData::dummy()); let _guard_0 = pool.put( Topic::JWK_CONSENSUS(dummy_issuer()), Arc::new(txn_0.clone()), @@ -48,7 +48,7 @@ fn txn_pull_order_should_be_fifo_except_in_topic_overwriting() { fn delete_by_seq_num() { let pool = VTxnPoolState::default(); let txn_0 = ValidatorTransaction::ObservedJWKUpdate(QuorumCertifiedUpdate::dummy()); - let txn_1 = ValidatorTransaction::DKGResult(DKGTranscript::dummy()); + let txn_1 = ValidatorTransaction::DKG(DKGTransactionData::dummy()); let guard_0 = pool.put( Topic::JWK_CONSENSUS(dummy_issuer()), Arc::new(txn_0.clone()), @@ -69,7 +69,7 @@ fn delete_by_seq_num() { fn txn_should_be_dropped_if_guard_is_dropped() { let pool = VTxnPoolState::default(); let txn_0 = ValidatorTransaction::ObservedJWKUpdate(QuorumCertifiedUpdate::dummy()); - let txn_1 = ValidatorTransaction::DKGResult(DKGTranscript::dummy()); + let txn_1 = ValidatorTransaction::DKG(DKGTransactionData::dummy()); let guard_0 = pool.put( Topic::JWK_CONSENSUS(dummy_issuer()), Arc::new(txn_0.clone()), @@ -91,7 +91,7 @@ fn txn_should_be_dropped_if_guard_is_dropped() { async fn per_txn_pull_notification() { let pool = VTxnPoolState::default(); let txn_0 = ValidatorTransaction::ObservedJWKUpdate(QuorumCertifiedUpdate::dummy()); - let txn_1 = ValidatorTransaction::DKGResult(DKGTranscript::dummy()); + let txn_1 = ValidatorTransaction::DKG(DKGTransactionData::dummy()); let (tx, mut rx) = aptos_channel::new(QueueStyle::KLAST, 1, None); let _guard_0 = pool.put( Topic::JWK_CONSENSUS(dummy_issuer()), @@ -116,7 +116,7 @@ async fn per_txn_pull_notification() { fn pull_item_limit_should_be_respected() { let pool = VTxnPoolState::default(); let txn_0 = ValidatorTransaction::ObservedJWKUpdate(QuorumCertifiedUpdate::dummy()); - let txn_1 = ValidatorTransaction::DKGResult(DKGTranscript::dummy()); + let txn_1 = ValidatorTransaction::DKG(DKGTransactionData::dummy()); let guard_0 = pool.put( Topic::JWK_CONSENSUS(dummy_issuer()), Arc::new(txn_0.clone()), diff --git a/devtools/assets/license_header.txt b/devtools/assets/license_header.txt index ebc846ed74b..47bc4ada806 100644 --- a/devtools/assets/license_header.txt +++ b/devtools/assets/license_header.txt @@ -1,2 +1,2 @@ -Copyright (c) Aptos Foundation +Copyright (c) Supra. SPDX-License-Identifier: Apache-2.0 diff --git a/devtools/assets/license_header_utf8.txt b/devtools/assets/license_header_utf8.txt index 5f8d7b55e16..c0cb30e1214 100644 --- a/devtools/assets/license_header_utf8.txt +++ b/devtools/assets/license_header_utf8.txt @@ -1,2 +1,2 @@ -Copyright © Aptos Foundation +Copyright © Supra. SPDX-License-Identifier: Apache-2.0 diff --git a/devtools/assets/shared_license_header.txt b/devtools/assets/shared_license_header.txt index 18a8743e5f4..a279050a3ae 100644 --- a/devtools/assets/shared_license_header.txt +++ b/devtools/assets/shared_license_header.txt @@ -1,3 +1,4 @@ +Copyright © Supra. Copyright (c) Aptos Foundation Parts of the project are originally copyright (c) Meta Platforms, Inc. SPDX-License-Identifier: Apache-2.0 diff --git a/devtools/assets/shared_license_header_utf8.txt b/devtools/assets/shared_license_header_utf8.txt index e5b2ef62fc0..78c2c2b1913 100644 --- a/devtools/assets/shared_license_header_utf8.txt +++ b/devtools/assets/shared_license_header_utf8.txt @@ -1,3 +1,4 @@ +Copyright © Supra. Copyright © Aptos Foundation Parts of the project are originally copyright © Meta Platforms, Inc. SPDX-License-Identifier: Apache-2.0 diff --git a/dkg/src/counters.rs b/dkg/src/counters.rs index a62e5bd67d8..7e1d904fae3 100644 --- a/dkg/src/counters.rs +++ b/dkg/src/counters.rs @@ -7,7 +7,7 @@ use once_cell::sync::Lazy; /// Count of the pending messages sent to itself in the channel pub static PENDING_SELF_MESSAGES: Lazy = Lazy::new(|| { register_int_gauge!( - "aptos_dkg_pending_self_messages", + "dkg_pending_self_messages", "Count of the pending messages sent to itself in the channel" ) .unwrap() @@ -15,7 +15,7 @@ pub static PENDING_SELF_MESSAGES: Lazy = Lazy::new(|| { pub static DKG_STAGE_SECONDS: Lazy = Lazy::new(|| { register_histogram_vec!( - "aptos_dkg_session_stage_seconds", + "dkg_session_stage_seconds", "How long it takes to reach different DKG stages", &["dealer", "stage"] ) @@ -24,7 +24,7 @@ pub static DKG_STAGE_SECONDS: Lazy = Lazy::new(|| { pub static ROUNDING_SECONDS: Lazy = Lazy::new(|| { register_histogram_vec!( - "aptos_dkg_rounding_seconds", + "dkg_rounding_seconds", "Rounding seconds and counts by method", &["method"] ) diff --git a/dkg/src/dkg_manager/tests.rs b/dkg/src/dkg_manager/tests.rs index 0bc38694c4f..627976281b5 100644 --- a/dkg/src/dkg_manager/tests.rs +++ b/dkg/src/dkg_manager/tests.rs @@ -14,7 +14,7 @@ use aptos_crypto::{ }; use aptos_infallible::RwLock; use aptos_types::{ - dkg::{ + aptos_dkg::{ dummy_dkg::DummyDKG, DKGSessionMetadata, DKGStartEvent, DKGTrait, DKGTranscript, DKGTranscriptMetadata, }, diff --git a/dkg/src/lib.rs b/dkg/src/lib.rs index 3fd39eb80ad..774cfd0e6b9 100644 --- a/dkg/src/lib.rs +++ b/dkg/src/lib.rs @@ -18,6 +18,7 @@ use aptos_event_notifications::{ DbBackedOnChainConfig, EventNotificationListener, ReconfigNotificationListener, }; use aptos_network::application::interface::{NetworkClient, NetworkServiceEvents}; +use aptos_types::dkg::{DKGTrait, DefaultDKG}; use aptos_validator_transaction_pool::VTxnPoolState; use move_core_types::account_address::AccountAddress; use tokio::runtime::Runtime; diff --git a/dkg/src/transcript_aggregation/tests.rs b/dkg/src/transcript_aggregation/tests.rs index fc1438a43e6..3e32a9a239a 100644 --- a/dkg/src/transcript_aggregation/tests.rs +++ b/dkg/src/transcript_aggregation/tests.rs @@ -6,7 +6,9 @@ use aptos_crypto::{ed25519, Uniform}; use aptos_infallible::duration_since_epoch; use aptos_reliable_broadcast::BroadcastStatus; use aptos_types::{ - dkg::{real_dkg::RealDKG, DKGSessionMetadata, DKGTrait, DKGTranscript, DKGTranscriptMetadata}, + aptos_dkg::{ + real_dkg::RealDKG, DKGSessionMetadata, DKGTrait, DKGTranscript, DKGTranscriptMetadata, + }, epoch_state::EpochState, on_chain_config::OnChainRandomnessConfig, validator_verifier::{ diff --git a/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/convert.rs b/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/convert.rs index 61952d44e5d..4d57d5aa18f 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/convert.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/convert.rs @@ -2,22 +2,24 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use aptos_api_types::transaction::{AutomationRegistrationParams, AutomationTaskType}; use aptos_api_types::{ - transaction::ValidatorTransaction as ApiValidatorTransactionEnum, AccountSignature, - DeleteModule, DeleteResource, Ed25519Signature, EntryFunctionId, EntryFunctionPayload, Event, - GenesisPayload, MoveAbility, MoveFunction, MoveFunctionGenericTypeParam, - MoveFunctionVisibility, MoveModule, MoveModuleBytecode, MoveModuleId, MoveScriptBytecode, - MoveStruct, MoveStructField, MoveStructTag, MoveType, MultiEd25519Signature, MultiKeySignature, - MultisigPayload, MultisigTransactionPayload, PublicKey, ScriptPayload, Signature, - SingleKeySignature, Transaction, TransactionInfo, TransactionPayload, TransactionSignature, - WriteSet, WriteSetChange, + transaction::{ + AutomationRegistrationParams, AutomationTaskType, + ValidatorTransaction as ApiValidatorTransactionEnum, + }, + AccountSignature, DeleteModule, DeleteResource, Ed25519Signature, EntryFunctionId, + EntryFunctionPayload, EventV1, GenesisPayload, MoveAbility, MoveFunction, + MoveFunctionGenericTypeParam, MoveFunctionVisibility, MoveModule, MoveModuleBytecode, + MoveModuleId, MoveScriptBytecode, MoveStruct, MoveStructField, MoveStructTag, MoveType, + MultiEd25519Signature, MultiKeySignature, MultisigPayload, MultisigTransactionPayload, + PublicKey, ScriptPayload, Signature, SingleKeySignature, Transaction, TransactionInfo, + TransactionPayload, TransactionSignature, WriteSet, WriteSetChange, }; use aptos_bitvec::BitVec; use aptos_logger::warn; use aptos_protos::{ transaction::v1::{ - self as transaction, any_signature, + self as transaction, any_signature, automation_payload_extensions, validator_transaction::{ self, observed_jwk_update::exported_provider_jw_ks::{ @@ -25,7 +27,8 @@ use aptos_protos::{ Jwk as ProtoJwk, }, }, - Ed25519, Keyless, Secp256k1Ecdsa, TransactionSizeInfo, WebAuthn, + AutomationPayloadExtensions, Ed25519, Keyless, Secp256k1Ecdsa, TransactionSizeInfo, + WebAuthn, }, util::timestamp, }; @@ -33,8 +36,6 @@ use aptos_types::jwks::jwk::JWK; use hex; use move_core_types::ability::Ability; use std::time::Duration; -use aptos_protos::transaction::v1::automation_payload_extensions; -use aptos_protos::transaction::v1::AutomationPayloadExtensions; pub fn convert_move_module_id(move_module_id: &MoveModuleId) -> transaction::MoveModuleId { transaction::MoveModuleId { @@ -234,7 +235,7 @@ pub fn convert_transaction_payload( } #[inline] -pub fn convert_events(events: &[Event]) -> Vec { +pub fn convert_events(events: &[EventV1]) -> Vec { events.iter().map(convert_event).collect() } @@ -547,7 +548,7 @@ pub fn convert_multisig_payload( ), ), } - } + }, }); transaction::MultisigPayload { multisig_address: multisig_payload.multisig_address.to_string(), @@ -555,11 +556,12 @@ pub fn convert_multisig_payload( } } -pub fn convert_automation_task_type(automation_task_type: &AutomationTaskType) -> transaction::AutomationTaskType { +pub fn convert_automation_task_type( + automation_task_type: &AutomationTaskType, +) -> transaction::AutomationTaskType { match automation_task_type { AutomationTaskType::User => transaction::AutomationTaskType::User, - AutomationTaskType::System => transaction::AutomationTaskType::System - + AutomationTaskType::System => transaction::AutomationTaskType::System, } } @@ -569,7 +571,9 @@ pub fn convert_automation_payload( match auto_payload { AutomationRegistrationParams::V1(params_v1) => { let v1 = transaction::AutomationPayload { - automated_function: Some(convert_entry_function_payload(¶ms_v1.automated_function)), + automated_function: Some(convert_entry_function_payload( + ¶ms_v1.automated_function, + )), expiration_timestamp_secs: params_v1.expiration_timestamp_secs, max_gas_amount: params_v1.max_gas_amount, gas_price_cap: params_v1.gas_price_cap, @@ -577,12 +581,14 @@ pub fn convert_automation_payload( aux_data: params_v1.aux_data.clone(), }; AutomationPayloadExtensions { - variant: Some(automation_payload_extensions::Variant::V1(v1)) + variant: Some(automation_payload_extensions::Variant::V1(v1)), } - } + }, AutomationRegistrationParams::V2(params_v2) => { let v2 = transaction::AutomationPayloadV2 { - automated_function: Some(convert_entry_function_payload(¶ms_v2.automated_function)), + automated_function: Some(convert_entry_function_payload( + ¶ms_v2.automated_function, + )), expiration_timestamp_secs: params_v2.expiration_timestamp_secs, max_gas_amount: params_v2.max_gas_amount, gas_price_cap: params_v2.gas_price_cap, @@ -592,14 +598,13 @@ pub fn convert_automation_payload( priority: params_v2.task_priority.clone(), }; AutomationPayloadExtensions { - variant: Some(automation_payload_extensions::Variant::V2(v2)) + variant: Some(automation_payload_extensions::Variant::V2(v2)), } - - } + }, } } -pub fn convert_event(event: &Event) -> transaction::Event { +pub fn convert_event(event: &EventV1) -> transaction::Event { let event_key: aptos_types::event::EventKey = event.guid.into(); transaction::Event { key: Some(transaction::EventKey { @@ -984,7 +989,10 @@ pub fn convert_transaction( max_gas_amount: at.meta.max_gas_amount.0, gas_unit_price: at.meta.gas_unit_price.0, expiration_timestamp_secs, - payload: Some(convert_transaction_payload(&at.meta.payload,Some(at.meta.index.0))), + payload: Some(convert_transaction_payload( + &at.meta.payload, + Some(at.meta.index.0), + )), registration_hash: at.meta.registration_hash.0.to_vec(), }), events: convert_events(&at.events), @@ -1023,19 +1031,35 @@ fn convert_validator_transaction( ) -> transaction::transaction::TxnData { transaction::transaction::TxnData::Validator(transaction::ValidatorTransaction { validator_transaction_type: match api_validator_txn { - ApiValidatorTransactionEnum::DkgResult(dgk_result) => { + ApiValidatorTransactionEnum::Dkg(dkg_transaction) => { + Some( + validator_transaction::ValidatorTransactionType::Dkg( + validator_transaction::DkgTransactionData { + dkg_data: Some(validator_transaction::dkg_data::DkgTransactionData{ + epoch: dkg_transaction.dkg_transaction_data.epoch.0, + author: dkg_transaction.dkg_transaction_data.author.to_string(), + bls_aggregate_signature: dkg_transaction.dkg_transaction_data.bls_aggregate_signature.clone(), + signer_indices_clan_committee: dkg_transaction.dkg_transaction_data.signer_indices_clan_committee.clone(), + transaction_type: dkg_transaction.dkg_transaction_data.transaction_type as u32, + payload: dkg_transaction.dkg_transaction_data.payload.0.clone(), + }), + }, + ) + ) + } + ApiValidatorTransactionEnum::DkgResult(dkg_result) => { Some( validator_transaction::ValidatorTransactionType::DkgUpdate( validator_transaction::DkgUpdate { dkg_transcript: Some(validator_transaction::dkg_update::DkgTranscript { - author: dgk_result.dkg_transcript.author.to_string(), - epoch: dgk_result.dkg_transcript.epoch.0, - payload: dgk_result.dkg_transcript.payload.0.clone(), + author: dkg_result.dkg_transcript.author.to_string(), + epoch: dkg_result.dkg_transcript.epoch.0, + payload: dkg_result.dkg_transcript.payload.0.clone(), }), }, ) ) - }, + } ApiValidatorTransactionEnum::ObservedJwkUpdate(observed_jwk_update) => { Some( validator_transaction::ValidatorTransactionType::ObservedJwkUpdate( diff --git a/ecosystem/indexer-grpc/indexer-grpc-table-info/Cargo.toml b/ecosystem/indexer-grpc/indexer-grpc-table-info/Cargo.toml index c8ff7258a4e..a3c4a7ce6f2 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-table-info/Cargo.toml +++ b/ecosystem/indexer-grpc/indexer-grpc-table-info/Cargo.toml @@ -16,7 +16,7 @@ anyhow = { workspace = true } aptos-api = { workspace = true } aptos-api-types = { workspace = true } aptos-config = { workspace = true } -aptos-db-indexer = { workspace = true } +aptos-db-indexer = { workspace = true } aptos-indexer-grpc-fullnode = { workspace = true } aptos-indexer-grpc-utils = { workspace = true } aptos-logger = { workspace = true } diff --git a/ecosystem/indexer-grpc/indexer-grpc-utils/src/cache_operator.rs b/ecosystem/indexer-grpc/indexer-grpc-utils/src/cache_operator.rs index 3445a4a38fd..308b88ef241 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-utils/src/cache_operator.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-utils/src/cache_operator.rs @@ -264,7 +264,10 @@ impl CacheOperator { for transaction in transactions { let version = transaction.version; let cache_key = CacheEntry::build_key(version, self.storage_format).to_string(); - let timestamp_in_seconds = transaction.timestamp.as_ref().map_or(0, |t| t.seconds as u64); + let timestamp_in_seconds = transaction + .timestamp + .as_ref() + .map_or(0, |t| t.seconds as u64); let cache_entry: CacheEntry = CacheEntry::from_transaction(transaction, self.storage_format); let bytes = cache_entry.into_inner(); diff --git a/ecosystem/indexer-grpc/transaction-filter/src/boolean_transaction_filter.rs b/ecosystem/indexer-grpc/transaction-filter/src/boolean_transaction_filter.rs index a37d2097680..5055c82bbe8 100644 --- a/ecosystem/indexer-grpc/transaction-filter/src/boolean_transaction_filter.rs +++ b/ecosystem/indexer-grpc/transaction-filter/src/boolean_transaction_filter.rs @@ -473,7 +473,7 @@ impl Filterable for APIFilter { TxnData::User(u) => &u.events, TxnData::Validator(_) => return false, TxnData::BlockEpilogue(_) => return false, - TxnData::Automated(a) => &a.events, + TxnData::Automated(automated_transaction) => &automated_transaction.events, }; events_filter.matches_vec(events) } else { diff --git a/ecosystem/indexer-grpc/transaction-filter/src/filters/user_transaction.rs b/ecosystem/indexer-grpc/transaction-filter/src/filters/user_transaction.rs index aa801ca1a26..de595845bf8 100644 --- a/ecosystem/indexer-grpc/transaction-filter/src/filters/user_transaction.rs +++ b/ecosystem/indexer-grpc/transaction-filter/src/filters/user_transaction.rs @@ -4,12 +4,11 @@ use crate::{errors::FilterError, traits::Filterable, utils::standardize_address}; use anyhow::{anyhow, Error}; use aptos_protos::transaction::v1::{ - multisig_transaction_payload, transaction::TxnData, transaction_payload, EntryFunctionId, - EntryFunctionPayload, Transaction, TransactionPayload, + multisig_transaction_payload, multisig_transaction_payload::Payload, transaction::TxnData, + transaction_payload, EntryFunctionId, EntryFunctionPayload, Transaction, TransactionPayload, }; use once_cell::sync::OnceCell; use serde::{Deserialize, Serialize}; -use aptos_protos::transaction::v1::multisig_transaction_payload::Payload; /// We use this for UserTransactions. /// We support UserPayload and MultisigPayload @@ -287,7 +286,7 @@ fn get_entry_function_payload_from_transaction_payload( multisig_transaction_payload::Payload::EntryFunctionPayload(ef_payload) => { Some(ef_payload) }, - Payload::AutomationPayload(_) => None + Payload::AutomationPayload(_) => None, }), _ => None, } diff --git a/ecosystem/nft-metadata-crawler/Cargo.toml b/ecosystem/nft-metadata-crawler/Cargo.toml index c7d9c9d776a..f29d0bf3247 100644 --- a/ecosystem/nft-metadata-crawler/Cargo.toml +++ b/ecosystem/nft-metadata-crawler/Cargo.toml @@ -24,11 +24,11 @@ bytes = { workspace = true } chrono = { workspace = true } clap = { workspace = true } diesel = { workspace = true, features = [ - "chrono", - "postgres", - "r2d2", - "numeric", - "serde_json", + "chrono", + "postgres", + "r2d2", + "numeric", + "serde_json", ] } diesel_migrations = { workspace = true } enum_dispatch = { workspace = true } diff --git a/execution/block-partitioner/Cargo.toml b/execution/block-partitioner/Cargo.toml index 422f2b0a07f..5eaec649142 100644 --- a/execution/block-partitioner/Cargo.toml +++ b/execution/block-partitioner/Cargo.toml @@ -43,4 +43,3 @@ default = [] [[bench]] name = "v2" harness = false - diff --git a/execution/block-partitioner/src/test_utils.rs b/execution/block-partitioner/src/test_utils.rs index 7b083915415..85689bb14f0 100644 --- a/execution/block-partitioner/src/test_utils.rs +++ b/execution/block-partitioner/src/test_utils.rs @@ -30,7 +30,7 @@ use aptos_types::{ analyzed_transaction::AnalyzedTransaction, EntryFunction, RawTransaction, SignedTransaction, Transaction, TransactionPayload, }, - SupraCoinType, CoinType, + CoinType, SupraCoinType, }; use move_core_types::{ account_address::AccountAddress, identifier::Identifier, language_storage::ModuleId, diff --git a/execution/executor-benchmark/Cargo.toml b/execution/executor-benchmark/Cargo.toml index 54d9e02b121..ad328e61d75 100644 --- a/execution/executor-benchmark/Cargo.toml +++ b/execution/executor-benchmark/Cargo.toml @@ -32,7 +32,7 @@ aptos-logger = { workspace = true } aptos-metrics-core = { workspace = true } aptos-mvhashmap = { workspace = true } aptos-node-resource-metrics = { workspace = true } -aptos-push-metrics = { workspace = true } +aptos-push-metrics = { workspace = true } aptos-sdk = { workspace = true } aptos-storage-interface = { workspace = true } aptos-transaction-generator-lib = { workspace = true } @@ -74,4 +74,8 @@ aptos-temppath = { workspace = true } [features] default = [] -fuzzing = ["aptos-config/fuzzing", "aptos-crypto/fuzzing", "aptos-types/fuzzing"] +fuzzing = [ + "aptos-config/fuzzing", + "aptos-crypto/fuzzing", + "aptos-types/fuzzing", +] diff --git a/execution/executor-service/Cargo.toml b/execution/executor-service/Cargo.toml index 01486b49c47..2756f49d0f5 100644 --- a/execution/executor-service/Cargo.toml +++ b/execution/executor-service/Cargo.toml @@ -22,7 +22,7 @@ aptos-language-e2e-tests = { workspace = true } aptos-logger = { workspace = true } aptos-metrics-core = { workspace = true } aptos-node-resource-metrics = { workspace = true } -aptos-push-metrics = { workspace = true } +aptos-push-metrics = { workspace = true } aptos-secure-net = { workspace = true } aptos-storage-interface = { workspace = true } aptos-transaction-simulation = { workspace = true } diff --git a/execution/executor/Cargo.toml b/execution/executor/Cargo.toml index d77ed487281..320e9ee2413 100644 --- a/execution/executor/Cargo.toml +++ b/execution/executor/Cargo.toml @@ -56,7 +56,12 @@ rand = { workspace = true } [features] default = [] -fuzzing = ["aptos-consensus-types/fuzzing", "aptos-crypto/fuzzing", "aptos-types/fuzzing", "aptos-storage-interface/fuzzing"] +fuzzing = [ + "aptos-consensus-types/fuzzing", + "aptos-crypto/fuzzing", + "aptos-types/fuzzing", + "aptos-storage-interface/fuzzing", +] failpoints = ["fail/failpoints", "aptos-vm/failpoints"] consensus-only-perf-test = [] diff --git a/execution/executor/src/metrics.rs b/execution/executor/src/metrics.rs index 57c7b641766..1626fc060f8 100644 --- a/execution/executor/src/metrics.rs +++ b/execution/executor/src/metrics.rs @@ -358,7 +358,9 @@ pub fn update_counters_for_processed_chunk( Some(Transaction::BlockEpilogue(_)) => "block_epilogue", Some(Transaction::ValidatorTransaction(_)) => "validator_transaction", Some(Transaction::AutomatedTransaction(_)) => "automation_transaction", - Some(Transaction::AutomationRegistryTransaction(_)) => "automation_registry_transaction", + Some(Transaction::AutomationRegistryTransaction(_)) => { + "automation_registry_transaction" + }, Some(Transaction::SystemAutomatedTransaction(_)) => "system_automated_transaction", None => "unknown", }; diff --git a/execution/executor/tests/storage_integration_test.rs b/execution/executor/tests/storage_integration_test.rs index 2bf6d1d6334..130b0e19107 100644 --- a/execution/executor/tests/storage_integration_test.rs +++ b/execution/executor/tests/storage_integration_test.rs @@ -98,11 +98,11 @@ fn test_reconfiguration() { .payload() .next() .unwrap() - .consensus_public_key(), - &ValidatorConfig::fetch_move_resource(&db_state_view, &validator_account) + .legacy_consensus_public_key_do_not_use(), + ValidatorConfig::fetch_move_resource(&db_state_view, &validator_account) .unwrap() .unwrap() - .consensus_public_key + .legacy_consensus_public_key_do_not_use() ); // txn1 = give the validator some money so they can send a tx diff --git a/mempool/Cargo.toml b/mempool/Cargo.toml index 43c5894badf..d244ece2467 100644 --- a/mempool/Cargo.toml +++ b/mempool/Cargo.toml @@ -63,5 +63,10 @@ proptest = { workspace = true } [features] default = [] failpoints = ["fail/failpoints", "aptos-vm-validator/failpoints"] -fuzzing = ["proptest", "aptos-types/fuzzing", "aptos-storage-interface/fuzzing", "aptos-config/fuzzing"] +fuzzing = [ + "proptest", + "aptos-types/fuzzing", + "aptos-storage-interface/fuzzing", + "aptos-config/fuzzing", +] consensus-only-perf-test = [] diff --git a/network/discovery/src/validator_set.rs b/network/discovery/src/validator_set.rs index 6f8305950ae..31507209bea 100644 --- a/network/discovery/src/validator_set.rs +++ b/network/discovery/src/validator_set.rs @@ -252,7 +252,7 @@ mod tests { let validator = ValidatorInfo::new( peer_id, 0, - ValidatorConfig::new( + ValidatorConfig::legacy_new_do_not_use( consensus_pubkey, validator_encoded_addresses, fullnode_encoded_addresses, diff --git a/network/framework/Cargo.toml b/network/framework/Cargo.toml index fc9ede7291c..b4ba67bdd4a 100644 --- a/network/framework/Cargo.toml +++ b/network/framework/Cargo.toml @@ -73,8 +73,25 @@ rand_core = { workspace = true } [features] default = [] -fuzzing = ["aptos-bitvec/fuzzing", "aptos-config/fuzzing", "aptos-crypto/fuzzing", "aptos-types/fuzzing", "aptos-proptest-helpers", "aptos-time-service/testing", "aptos-types/fuzzing", "aptos-memsocket/testing", "aptos-netcore/fuzzing", "proptest", "proptest-derive"] -testing = ["aptos-config/testing", "aptos-time-service/testing", "aptos-memsocket/testing", "aptos-netcore/testing"] +fuzzing = [ + "aptos-bitvec/fuzzing", + "aptos-config/fuzzing", + "aptos-crypto/fuzzing", + "aptos-types/fuzzing", + "aptos-proptest-helpers", + "aptos-time-service/testing", + "aptos-types/fuzzing", + "aptos-memsocket/testing", + "aptos-netcore/fuzzing", + "proptest", + "proptest-derive", +] +testing = [ + "aptos-config/testing", + "aptos-time-service/testing", + "aptos-memsocket/testing", + "aptos-netcore/testing", +] [package.metadata.cargo-machete] ignored = ["serde_bytes"] diff --git a/protos/python/pyproject.toml b/protos/python/pyproject.toml index 2faea9a7c7b..ead7782045d 100644 --- a/protos/python/pyproject.toml +++ b/protos/python/pyproject.toml @@ -8,7 +8,7 @@ readme = "README.md" repository = "https://github.com/aptos-labs/aptos-core" homepage = "https://github.com/aptos-labs/aptos-core/tree/main/protos/python" keywords = ["web3", "aptos", "blockchain", "indexer"] -packages = [{include = "aptos_protos"}] +packages = [{ include = "aptos_protos" }] [tool.poe.tasks] generate = "./generate.sh" diff --git a/protos/rust/src/pb/aptos.transaction.v1.rs b/protos/rust/src/pb/aptos.transaction.v1.rs index cf530149fb6..ce216bcae33 100644 --- a/protos/rust/src/pb/aptos.transaction.v1.rs +++ b/protos/rust/src/pb/aptos.transaction.v1.rs @@ -102,7 +102,7 @@ pub mod transaction { } } #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] + #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum TxnData { #[prost(message, tag="7")] BlockMetadata(super::BlockMetadataTransaction), @@ -162,7 +162,7 @@ pub struct ValidatorTransaction { /// Nested message and enum types in `ValidatorTransaction`. pub mod validator_transaction { #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] + #[derive(Clone, PartialEq, ::prost::Message)] pub struct ObservedJwkUpdate { #[prost(message, optional, tag="1")] pub quorum_certified_update: ::core::option::Option, @@ -170,7 +170,7 @@ pub mod validator_transaction { /// Nested message and enum types in `ObservedJwkUpdate`. pub mod observed_jwk_update { #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] + #[derive(Clone, PartialEq, ::prost::Message)] pub struct ExportedProviderJwKs { #[prost(string, tag="1")] pub issuer: ::prost::alloc::string::String, @@ -182,7 +182,7 @@ pub mod validator_transaction { /// Nested message and enum types in `ExportedProviderJWKs`. pub mod exported_provider_jw_ks { #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] + #[derive(Clone, PartialEq, ::prost::Message)] pub struct Jwk { #[prost(oneof="jwk::JwkType", tags="1, 2")] pub jwk_type: ::core::option::Option, @@ -190,7 +190,7 @@ pub mod validator_transaction { /// Nested message and enum types in `JWK`. pub mod jwk { #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] + #[derive(Clone, PartialEq, ::prost::Message)] pub struct Rsa { #[prost(string, tag="1")] pub kid: ::prost::alloc::string::String, @@ -204,7 +204,7 @@ pub mod validator_transaction { pub n: ::prost::alloc::string::String, } #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] + #[derive(Clone, PartialEq, ::prost::Message)] pub struct UnsupportedJwk { #[prost(bytes="vec", tag="1")] pub id: ::prost::alloc::vec::Vec, @@ -212,7 +212,7 @@ pub mod validator_transaction { pub payload: ::prost::alloc::vec::Vec, } #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] + #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum JwkType { #[prost(message, tag="1")] UnsupportedJwk(UnsupportedJwk), @@ -222,7 +222,7 @@ pub mod validator_transaction { } } #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] + #[derive(Clone, PartialEq, ::prost::Message)] pub struct ExportedAggregateSignature { #[prost(uint64, repeated, tag="1")] pub signer_indices: ::prost::alloc::vec::Vec, @@ -231,7 +231,7 @@ pub mod validator_transaction { pub sig: ::prost::alloc::vec::Vec, } #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] + #[derive(Clone, PartialEq, ::prost::Message)] pub struct QuorumCertifiedUpdate { #[prost(message, optional, tag="1")] pub update: ::core::option::Option, @@ -240,7 +240,7 @@ pub mod validator_transaction { } } #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] + #[derive(Clone, PartialEq, ::prost::Message)] pub struct DkgUpdate { #[prost(message, optional, tag="1")] pub dkg_transcript: ::core::option::Option, @@ -248,7 +248,7 @@ pub mod validator_transaction { /// Nested message and enum types in `DkgUpdate`. pub mod dkg_update { #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] + #[derive(Clone, PartialEq, ::prost::Message)] pub struct DkgTranscript { #[prost(uint64, tag="1")] pub epoch: u64, @@ -258,13 +258,43 @@ pub mod validator_transaction { pub payload: ::prost::alloc::vec::Vec, } } + #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct DkgTransactionData { + #[prost(message, optional, tag="1")] + pub dkg_data: ::core::option::Option, + } + + /// Nested message and enum types in `DkgTransactionData`. + pub mod dkg_data { + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct DkgTransactionData { + #[prost(uint64, tag="1")] + pub epoch: u64, + #[prost(string, tag="2")] + pub author: ::prost::alloc::string::String, + #[prost(bytes="vec", tag="3")] + pub bls_aggregate_signature: ::prost::alloc::vec::Vec, + #[prost(uint32, repeated, tag="4")] + pub signer_indices_clan_committee: ::prost::alloc::vec::Vec, + #[prost(uint32, tag="5")] + pub transaction_type: u32, + #[prost(bytes="vec", tag="6")] + pub payload: ::prost::alloc::vec::Vec, + } + } + + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum ValidatorTransactionType { #[prost(message, tag="1")] ObservedJwkUpdate(ObservedJwkUpdate), #[prost(message, tag="2")] DkgUpdate(DkgUpdate), + #[prost(message, tag="3")] + Dkg(DkgTransactionData), } } #[allow(clippy::derive_partial_eq_without_eq)] @@ -421,7 +451,7 @@ pub mod write_set { } } #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] + #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum WriteSet { #[prost(message, tag="2")] ScriptWriteSet(super::ScriptWriteSet), @@ -497,7 +527,7 @@ pub mod write_set_change { } } #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] + #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Change { #[prost(message, tag="2")] DeleteModule(super::DeleteModule), @@ -659,7 +689,7 @@ pub mod transaction_payload { } } #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] + #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Payload { #[prost(message, tag="2")] EntryFunctionPayload(super::EntryFunctionPayload), @@ -767,7 +797,7 @@ pub mod multisig_transaction_payload { } } #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] + #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Payload { #[prost(message, tag="2")] EntryFunctionPayload(super::EntryFunctionPayload), @@ -950,7 +980,7 @@ pub struct MoveType { /// Nested message and enum types in `MoveType`. pub mod move_type { #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] + #[derive(Clone, PartialEq, ::prost::Message)] pub struct ReferenceType { #[prost(bool, tag="1")] pub mutable: bool, @@ -958,7 +988,7 @@ pub mod move_type { pub to: ::core::option::Option<::prost::alloc::boxed::Box>, } #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] + #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Content { #[prost(message, tag="3")] Vector(::prost::alloc::boxed::Box), @@ -1055,7 +1085,7 @@ pub mod signature { } } #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] + #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Signature { #[prost(message, tag="2")] Ed25519(super::Ed25519Signature), @@ -1216,7 +1246,7 @@ pub mod any_signature { } /// Support: >= 1.10. #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] + #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum SignatureVariant { #[prost(message, tag="3")] Ed25519(super::Ed25519), @@ -1341,7 +1371,7 @@ pub mod account_signature { } } #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] + #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Signature { #[prost(message, tag="2")] Ed25519(super::Ed25519Signature), @@ -4362,4 +4392,4 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x6f, 0x33, ]; include!("aptos.transaction.v1.serde.rs"); -// @@protoc_insertion_point(module) +// @@protoc_insertion_point(module) \ No newline at end of file diff --git a/protos/rust/src/pb/aptos.transaction.v1.serde.rs b/protos/rust/src/pb/aptos.transaction.v1.serde.rs index db8ca2ee2c4..f063af6c191 100644 --- a/protos/rust/src/pb/aptos.transaction.v1.serde.rs +++ b/protos/rust/src/pb/aptos.transaction.v1.serde.rs @@ -224,8 +224,8 @@ impl<'de> serde::Deserialize<'de> for AccountSignature { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut r#type__ = None; let mut signature__ = None; @@ -242,28 +242,28 @@ impl<'de> serde::Deserialize<'de> for AccountSignature { return Err(serde::de::Error::duplicate_field("ed25519")); } signature__ = map.next_value::<::std::option::Option<_>>()?.map(account_signature::Signature::Ed25519) -; + ; } GeneratedField::MultiEd25519 => { if signature__.is_some() { return Err(serde::de::Error::duplicate_field("multiEd25519")); } signature__ = map.next_value::<::std::option::Option<_>>()?.map(account_signature::Signature::MultiEd25519) -; + ; } GeneratedField::SingleKeySignature => { if signature__.is_some() { return Err(serde::de::Error::duplicate_field("singleKeySignature")); } signature__ = map.next_value::<::std::option::Option<_>>()?.map(account_signature::Signature::SingleKeySignature) -; + ; } GeneratedField::MultiKeySignature => { if signature__.is_some() { return Err(serde::de::Error::duplicate_field("multiKeySignature")); } signature__ = map.next_value::<::std::option::Option<_>>()?.map(account_signature::Signature::MultiKeySignature) -; + ; } GeneratedField::Abstraction => { if signature__.is_some() { @@ -449,8 +449,8 @@ impl<'de> serde::Deserialize<'de> for AnyPublicKey { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut r#type__ = None; let mut public_key__ = None; @@ -678,8 +678,8 @@ impl<'de> serde::Deserialize<'de> for AnySignature { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut r#type__ = None; let mut signature__ = None; @@ -705,28 +705,28 @@ impl<'de> serde::Deserialize<'de> for AnySignature { return Err(serde::de::Error::duplicate_field("ed25519")); } signature_variant__ = map.next_value::<::std::option::Option<_>>()?.map(any_signature::SignatureVariant::Ed25519) -; + ; } GeneratedField::Secp256k1Ecdsa => { if signature_variant__.is_some() { return Err(serde::de::Error::duplicate_field("secp256k1Ecdsa")); } signature_variant__ = map.next_value::<::std::option::Option<_>>()?.map(any_signature::SignatureVariant::Secp256k1Ecdsa) -; + ; } GeneratedField::Webauthn => { if signature_variant__.is_some() { return Err(serde::de::Error::duplicate_field("webauthn")); } signature_variant__ = map.next_value::<::std::option::Option<_>>()?.map(any_signature::SignatureVariant::Webauthn) -; + ; } GeneratedField::Keyless => { if signature_variant__.is_some() { return Err(serde::de::Error::duplicate_field("keyless")); } signature_variant__ = map.next_value::<::std::option::Option<_>>()?.map(any_signature::SignatureVariant::Keyless) -; + ; } } } @@ -949,8 +949,8 @@ impl<'de> serde::Deserialize<'de> for AutomatedTaskMeta { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut sender__ = None; let mut index__ = None; @@ -1105,8 +1105,8 @@ impl<'de> serde::Deserialize<'de> for AutomatedTransaction { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut meta__ = None; let mut events__ = None; @@ -1255,8 +1255,8 @@ impl<'de> serde::Deserialize<'de> for AutomationPayload { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut automated_function__ = None; let mut expiration_timestamp_secs__ = None; @@ -1839,8 +1839,8 @@ impl<'de> serde::Deserialize<'de> for Block { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut timestamp__ = None; let mut height__ = None; @@ -1989,8 +1989,8 @@ impl<'de> serde::Deserialize<'de> for BlockEndInfo { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut block_gas_limit_reached__ = None; let mut block_output_limit_reached__ = None; @@ -2109,8 +2109,8 @@ impl<'de> serde::Deserialize<'de> for BlockEpilogueTransaction { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut block_end_info__ = None; while let Some(k) = map.next_key()? { @@ -2247,8 +2247,8 @@ impl<'de> serde::Deserialize<'de> for BlockMetadataTransaction { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut id__ = None; let mut round__ = None; @@ -2404,8 +2404,8 @@ impl<'de> serde::Deserialize<'de> for DeleteModule { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut address__ = None; let mut state_key_hash__ = None; @@ -2542,8 +2542,8 @@ impl<'de> serde::Deserialize<'de> for DeleteResource { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut address__ = None; let mut state_key_hash__ = None; @@ -2669,8 +2669,8 @@ impl<'de> serde::Deserialize<'de> for DeleteTableData { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut key__ = None; let mut key_type__ = None; @@ -2796,8 +2796,8 @@ impl<'de> serde::Deserialize<'de> for DeleteTableItem { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut state_key_hash__ = None; let mut handle__ = None; @@ -2923,8 +2923,8 @@ impl<'de> serde::Deserialize<'de> for DirectWriteSet { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut write_set_change__ = None; let mut events__ = None; @@ -3022,8 +3022,8 @@ impl<'de> serde::Deserialize<'de> for Ed25519 { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut signature__ = None; while let Some(k) = map.next_key()? { @@ -3125,8 +3125,8 @@ impl<'de> serde::Deserialize<'de> for Ed25519Signature { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut public_key__ = None; let mut signature__ = None; @@ -3237,8 +3237,8 @@ impl<'de> serde::Deserialize<'de> for EntryFunctionId { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut module__ = None; let mut name__ = None; @@ -3365,8 +3365,8 @@ impl<'de> serde::Deserialize<'de> for EntryFunctionPayload { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut function__ = None; let mut type_arguments__ = None; @@ -3518,8 +3518,8 @@ impl<'de> serde::Deserialize<'de> for Event { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut key__ = None; let mut sequence_number__ = None; @@ -3654,8 +3654,8 @@ impl<'de> serde::Deserialize<'de> for EventKey { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut creation_number__ = None; let mut account_address__ = None; @@ -3766,8 +3766,8 @@ impl<'de> serde::Deserialize<'de> for EventSizeInfo { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut type_tag_bytes__ = None; let mut total_bytes__ = None; @@ -4021,8 +4021,8 @@ impl<'de> serde::Deserialize<'de> for FeePayerSignature { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut sender__ = None; let mut secondary_signer_addresses__ = None; @@ -4153,8 +4153,8 @@ impl<'de> serde::Deserialize<'de> for GenesisTransaction { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut payload__ = None; let mut events__ = None; @@ -4261,8 +4261,8 @@ impl<'de> serde::Deserialize<'de> for IndexedSignature { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut index__ = None; let mut signature__ = None; @@ -4362,8 +4362,8 @@ impl<'de> serde::Deserialize<'de> for Keyless { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut signature__ = None; while let Some(k) = map.next_key()? { @@ -4586,8 +4586,8 @@ impl<'de> serde::Deserialize<'de> for MoveFunction { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut name__ = None; let mut visibility__ = None; @@ -4743,7 +4743,7 @@ impl serde::Serialize for MoveFunctionGenericTypeParam { let v = self.constraints.iter().cloned().map(|v| { MoveAbility::from_i32(v) .ok_or_else(|| serde::ser::Error::custom(format!("Invalid variant {}", v))) - }).collect::, _>>()?; + }).collect::, _>>()?; struct_ser.serialize_field("constraints", &v)?; } struct_ser.end() @@ -4800,8 +4800,8 @@ impl<'de> serde::Deserialize<'de> for MoveFunctionGenericTypeParam { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut constraints__ = None; while let Some(k) = map.next_key()? { @@ -4928,8 +4928,8 @@ impl<'de> serde::Deserialize<'de> for MoveModule { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut address__ = None; let mut name__ = None; @@ -5060,8 +5060,8 @@ impl<'de> serde::Deserialize<'de> for MoveModuleBytecode { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut bytecode__ = None; let mut abi__ = None; @@ -5170,8 +5170,8 @@ impl<'de> serde::Deserialize<'de> for MoveModuleId { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut address__ = None; let mut name__ = None; @@ -5278,8 +5278,8 @@ impl<'de> serde::Deserialize<'de> for MoveScriptBytecode { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut bytecode__ = None; let mut abi__ = None; @@ -5350,7 +5350,7 @@ impl serde::Serialize for MoveStruct { let v = self.abilities.iter().cloned().map(|v| { MoveAbility::from_i32(v) .ok_or_else(|| serde::ser::Error::custom(format!("Invalid variant {}", v))) - }).collect::, _>>()?; + }).collect::, _>>()?; struct_ser.serialize_field("abilities", &v)?; } if !self.generic_type_params.is_empty() { @@ -5431,8 +5431,8 @@ impl<'de> serde::Deserialize<'de> for MoveStruct { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut name__ = None; let mut is_native__ = None; @@ -5571,8 +5571,8 @@ impl<'de> serde::Deserialize<'de> for MoveStructField { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut name__ = None; let mut r#type__ = None; @@ -5620,7 +5620,7 @@ impl serde::Serialize for MoveStructGenericTypeParam { let v = self.constraints.iter().cloned().map(|v| { MoveAbility::from_i32(v) .ok_or_else(|| serde::ser::Error::custom(format!("Invalid variant {}", v))) - }).collect::, _>>()?; + }).collect::, _>>()?; struct_ser.serialize_field("constraints", &v)?; } if self.is_phantom { @@ -5684,8 +5684,8 @@ impl<'de> serde::Deserialize<'de> for MoveStructGenericTypeParam { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut constraints__ = None; let mut is_phantom__ = None; @@ -5811,8 +5811,8 @@ impl<'de> serde::Deserialize<'de> for MoveStructTag { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut address__ = None; let mut module__ = None; @@ -5966,8 +5966,8 @@ impl<'de> serde::Deserialize<'de> for MoveType { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut r#type__ = None; let mut content__ = None; @@ -5984,14 +5984,14 @@ impl<'de> serde::Deserialize<'de> for MoveType { return Err(serde::de::Error::duplicate_field("vector")); } content__ = map.next_value::<::std::option::Option<_>>()?.map(move_type::Content::Vector) -; + ; } GeneratedField::Struct => { if content__.is_some() { return Err(serde::de::Error::duplicate_field("struct")); } content__ = map.next_value::<::std::option::Option<_>>()?.map(move_type::Content::Struct) -; + ; } GeneratedField::GenericTypeParamIndex => { if content__.is_some() { @@ -6004,7 +6004,7 @@ impl<'de> serde::Deserialize<'de> for MoveType { return Err(serde::de::Error::duplicate_field("reference")); } content__ = map.next_value::<::std::option::Option<_>>()?.map(move_type::Content::Reference) -; + ; } GeneratedField::Unparsable => { if content__.is_some() { @@ -6101,8 +6101,8 @@ impl<'de> serde::Deserialize<'de> for move_type::ReferenceType { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut mutable__ = None; let mut to__ = None; @@ -6332,8 +6332,8 @@ impl<'de> serde::Deserialize<'de> for MultiAgentSignature { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut sender__ = None; let mut secondary_signer_addresses__ = None; @@ -6468,8 +6468,8 @@ impl<'de> serde::Deserialize<'de> for MultiEd25519Signature { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut public_keys__ = None; let mut signatures__ = None; @@ -6614,8 +6614,8 @@ impl<'de> serde::Deserialize<'de> for MultiKeySignature { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut public_keys__ = None; let mut signatures__ = None; @@ -6734,8 +6734,8 @@ impl<'de> serde::Deserialize<'de> for MultisigPayload { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut multisig_address__ = None; let mut transaction_payload__ = None; @@ -6856,8 +6856,8 @@ impl<'de> serde::Deserialize<'de> for MultisigTransactionPayload { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut r#type__ = None; let mut payload__ = None; @@ -6874,7 +6874,7 @@ impl<'de> serde::Deserialize<'de> for MultisigTransactionPayload { return Err(serde::de::Error::duplicate_field("entryFunctionPayload")); } payload__ = map.next_value::<::std::option::Option<_>>()?.map(multisig_transaction_payload::Payload::EntryFunctionPayload) -; + ; } GeneratedField::AutomationPayload => { if payload__.is_some() { @@ -7058,8 +7058,8 @@ impl<'de> serde::Deserialize<'de> for ScriptPayload { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut code__ = None; let mut type_arguments__ = None; @@ -7175,8 +7175,8 @@ impl<'de> serde::Deserialize<'de> for ScriptWriteSet { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut execute_as__ = None; let mut script__ = None; @@ -7274,8 +7274,8 @@ impl<'de> serde::Deserialize<'de> for Secp256k1Ecdsa { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut signature__ = None; while let Some(k) = map.next_key()? { @@ -7410,8 +7410,8 @@ impl<'de> serde::Deserialize<'de> for Signature { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut r#type__ = None; let mut signature__ = None; @@ -7428,35 +7428,35 @@ impl<'de> serde::Deserialize<'de> for Signature { return Err(serde::de::Error::duplicate_field("ed25519")); } signature__ = map.next_value::<::std::option::Option<_>>()?.map(signature::Signature::Ed25519) -; + ; } GeneratedField::MultiEd25519 => { if signature__.is_some() { return Err(serde::de::Error::duplicate_field("multiEd25519")); } signature__ = map.next_value::<::std::option::Option<_>>()?.map(signature::Signature::MultiEd25519) -; + ; } GeneratedField::MultiAgent => { if signature__.is_some() { return Err(serde::de::Error::duplicate_field("multiAgent")); } signature__ = map.next_value::<::std::option::Option<_>>()?.map(signature::Signature::MultiAgent) -; + ; } GeneratedField::FeePayer => { if signature__.is_some() { return Err(serde::de::Error::duplicate_field("feePayer")); } signature__ = map.next_value::<::std::option::Option<_>>()?.map(signature::Signature::FeePayer) -; + ; } GeneratedField::SingleSender => { if signature__.is_some() { return Err(serde::de::Error::duplicate_field("singleSender")); } signature__ = map.next_value::<::std::option::Option<_>>()?.map(signature::Signature::SingleSender) -; + ; } } } @@ -7633,8 +7633,8 @@ impl<'de> serde::Deserialize<'de> for SingleKeySignature { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut public_key__ = None; let mut signature__ = None; @@ -7732,8 +7732,8 @@ impl<'de> serde::Deserialize<'de> for SingleSender { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut sender__ = None; while let Some(k) = map.next_key()? { @@ -7797,7 +7797,7 @@ impl<'de> serde::Deserialize<'de> for StateCheckpointTransaction { where E: serde::de::Error, { - Err(serde::de::Error::unknown_field(value, FIELDS)) + Err(serde::de::Error::unknown_field(value, FIELDS)) } } deserializer.deserialize_identifier(GeneratedVisitor) @@ -7812,8 +7812,8 @@ impl<'de> serde::Deserialize<'de> for StateCheckpointTransaction { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { while map.next_key::()?.is_some() { let _ = map.next_value::()?; @@ -8004,8 +8004,8 @@ impl<'de> serde::Deserialize<'de> for Transaction { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut timestamp__ = None; let mut version__ = None; @@ -8070,49 +8070,49 @@ impl<'de> serde::Deserialize<'de> for Transaction { return Err(serde::de::Error::duplicate_field("blockMetadata")); } txn_data__ = map.next_value::<::std::option::Option<_>>()?.map(transaction::TxnData::BlockMetadata) -; + ; } GeneratedField::Genesis => { if txn_data__.is_some() { return Err(serde::de::Error::duplicate_field("genesis")); } txn_data__ = map.next_value::<::std::option::Option<_>>()?.map(transaction::TxnData::Genesis) -; + ; } GeneratedField::StateCheckpoint => { if txn_data__.is_some() { return Err(serde::de::Error::duplicate_field("stateCheckpoint")); } txn_data__ = map.next_value::<::std::option::Option<_>>()?.map(transaction::TxnData::StateCheckpoint) -; + ; } GeneratedField::User => { if txn_data__.is_some() { return Err(serde::de::Error::duplicate_field("user")); } txn_data__ = map.next_value::<::std::option::Option<_>>()?.map(transaction::TxnData::User) -; + ; } GeneratedField::Validator => { if txn_data__.is_some() { return Err(serde::de::Error::duplicate_field("validator")); } txn_data__ = map.next_value::<::std::option::Option<_>>()?.map(transaction::TxnData::Validator) -; + ; } GeneratedField::BlockEpilogue => { if txn_data__.is_some() { return Err(serde::de::Error::duplicate_field("blockEpilogue")); } txn_data__ = map.next_value::<::std::option::Option<_>>()?.map(transaction::TxnData::BlockEpilogue) -; + ; } GeneratedField::Automated => { if txn_data__.is_some() { return Err(serde::de::Error::duplicate_field("automated")); } txn_data__ = map.next_value::<::std::option::Option<_>>()?.map(transaction::TxnData::Automated) -; + ; } } } @@ -8369,8 +8369,8 @@ impl<'de> serde::Deserialize<'de> for TransactionInfo { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut hash__ = None; let mut state_change_hash__ = None; @@ -8601,8 +8601,8 @@ impl<'de> serde::Deserialize<'de> for TransactionPayload { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut r#type__ = None; let mut payload__ = None; @@ -8620,35 +8620,35 @@ impl<'de> serde::Deserialize<'de> for TransactionPayload { return Err(serde::de::Error::duplicate_field("entryFunctionPayload")); } payload__ = map.next_value::<::std::option::Option<_>>()?.map(transaction_payload::Payload::EntryFunctionPayload) -; + ; } GeneratedField::ScriptPayload => { if payload__.is_some() { return Err(serde::de::Error::duplicate_field("scriptPayload")); } payload__ = map.next_value::<::std::option::Option<_>>()?.map(transaction_payload::Payload::ScriptPayload) -; + ; } GeneratedField::WriteSetPayload => { if payload__.is_some() { return Err(serde::de::Error::duplicate_field("writeSetPayload")); } payload__ = map.next_value::<::std::option::Option<_>>()?.map(transaction_payload::Payload::WriteSetPayload) -; + ; } GeneratedField::MultisigPayload => { if payload__.is_some() { return Err(serde::de::Error::duplicate_field("multisigPayload")); } payload__ = map.next_value::<::std::option::Option<_>>()?.map(transaction_payload::Payload::MultisigPayload) -; + ; } GeneratedField::AutomationPayload => { if payload__.is_some() { return Err(serde::de::Error::duplicate_field("automationPayload")); } payload__ = map.next_value::<::std::option::Option<_>>()?.map(transaction_payload::Payload::AutomationPayload) -; + ; } GeneratedField::AutomationPayloads => { if payload__.is_some() { @@ -8854,8 +8854,8 @@ impl<'de> serde::Deserialize<'de> for TransactionSizeInfo { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut transaction_bytes__ = None; let mut event_size_info__ = None; @@ -8972,8 +8972,8 @@ impl<'de> serde::Deserialize<'de> for UserTransaction { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut request__ = None; let mut events__ = None; @@ -9129,8 +9129,8 @@ impl<'de> serde::Deserialize<'de> for UserTransactionRequest { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut sender__ = None; let mut sequence_number__ = None; @@ -9231,6 +9231,9 @@ impl serde::Serialize for ValidatorTransaction { validator_transaction::ValidatorTransactionType::DkgUpdate(v) => { struct_ser.serialize_field("dkgUpdate", v)?; } + validator_transaction::ValidatorTransactionType::Dkg(v) => { + struct_ser.serialize_field("dkg", v)?; + } } } struct_ser.end() @@ -9295,8 +9298,8 @@ impl<'de> serde::Deserialize<'de> for ValidatorTransaction { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut events__ = None; let mut validator_transaction_type__ = None; @@ -9313,14 +9316,14 @@ impl<'de> serde::Deserialize<'de> for ValidatorTransaction { return Err(serde::de::Error::duplicate_field("observedJwkUpdate")); } validator_transaction_type__ = map.next_value::<::std::option::Option<_>>()?.map(validator_transaction::ValidatorTransactionType::ObservedJwkUpdate) -; + ; } GeneratedField::DkgUpdate => { if validator_transaction_type__.is_some() { return Err(serde::de::Error::duplicate_field("dkgUpdate")); } validator_transaction_type__ = map.next_value::<::std::option::Option<_>>()?.map(validator_transaction::ValidatorTransactionType::DkgUpdate) -; + ; } } } @@ -9403,8 +9406,8 @@ impl<'de> serde::Deserialize<'de> for validator_transaction::DkgUpdate { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut dkg_transcript__ = None; while let Some(k) = map.next_key()? { @@ -9512,8 +9515,8 @@ impl<'de> serde::Deserialize<'de> for validator_transaction::dkg_update::DkgTran } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut epoch__ = None; let mut author__ = None; @@ -9554,7 +9557,7 @@ impl<'de> serde::Deserialize<'de> for validator_transaction::dkg_update::DkgTran deserializer.deserialize_struct("aptos.transaction.v1.ValidatorTransaction.DkgUpdate.DkgTranscript", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for validator_transaction::ObservedJwkUpdate { +impl serde::Serialize for validator_transaction::DkgTransactionData { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -9562,30 +9565,30 @@ impl serde::Serialize for validator_transaction::ObservedJwkUpdate { { use serde::ser::SerializeStruct; let mut len = 0; - if self.quorum_certified_update.is_some() { + if self.dkg_data.is_some() { len += 1; } - let mut struct_ser = serializer.serialize_struct("aptos.transaction.v1.ValidatorTransaction.ObservedJwkUpdate", len)?; - if let Some(v) = self.quorum_certified_update.as_ref() { - struct_ser.serialize_field("quorumCertifiedUpdate", v)?; + let mut struct_ser = serializer.serialize_struct("aptos.transaction.v1.ValidatorTransaction.DkgTransactionData", len)?; + if let Some(v) = self.dkg_data.as_ref() { + struct_ser.serialize_field("dkgData", v)?; } struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for validator_transaction::ObservedJwkUpdate { +impl<'de> serde::Deserialize<'de> for validator_transaction::DkgTransactionData { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "quorum_certified_update", - "quorumCertifiedUpdate", + "dkg_data", + "dkgData", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { - QuorumCertifiedUpdate, + DkgData, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -9607,7 +9610,7 @@ impl<'de> serde::Deserialize<'de> for validator_transaction::ObservedJwkUpdate { E: serde::de::Error, { match value { - "quorumCertifiedUpdate" | "quorum_certified_update" => Ok(GeneratedField::QuorumCertifiedUpdate), + "dkgData" | "dkg_data" => Ok(GeneratedField::DkgData), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -9617,15 +9620,297 @@ impl<'de> serde::Deserialize<'de> for validator_transaction::ObservedJwkUpdate { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = validator_transaction::ObservedJwkUpdate; + type Value = validator_transaction::DkgTransactionData; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct aptos.transaction.v1.ValidatorTransaction.ObservedJwkUpdate") + formatter.write_str("struct aptos.transaction.v1.ValidatorTransaction.DkgTransactionData") } - fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + fn visit_map(self, mut map: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut dkg_data__ = None; + while let Some(k) = map.next_key()? { + match k { + GeneratedField::DkgData => { + if dkg_data__.is_some() { + return Err(serde::de::Error::duplicate_field("dkgData")); + } + dkg_data__ = map.next_value()?; + } + } + } + Ok(validator_transaction::DkgTransactionData { + dkg_data: dkg_data__, + }) + } + } + deserializer.deserialize_struct("aptos.transaction.v1.ValidatorTransaction.DkgTransactionData", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for validator_transaction::dkg_data::DkgTransactionData { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.epoch != 0 { + len += 1; + } + if !self.author.is_empty() { + len += 1; + } + if !self.bls_aggregate_signature.is_empty() { + len += 1; + } + if !self.signer_indices_clan_committee.is_empty() { + len += 1; + } + if self.transaction_type != 0 { + len += 1; + } + if !self.payload.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("aptos.transaction.v1.ValidatorTransaction.DkgTransactionData.DkgTransactionData", len)?; + if self.epoch != 0 { + struct_ser.serialize_field("epoch", ToString::to_string(&self.epoch).as_str())?; + } + if !self.author.is_empty() { + struct_ser.serialize_field("author", &self.author)?; + } + if !self.bls_aggregate_signature.is_empty() { + struct_ser.serialize_field("blsAggregateSignature", pbjson::private::base64::encode(&self.bls_aggregate_signature).as_str())?; + } + if !self.signer_indices_clan_committee.is_empty() { + struct_ser.serialize_field("signerIndicesClanCommittee", &self.signer_indices_clan_committee.iter().map(ToString::to_string).collect::>())?; + } + if self.transaction_type != 0 { + struct_ser.serialize_field("transactionType", ToString::to_string(&self.transaction_type).as_str())?; + } + if !self.payload.is_empty() { + struct_ser.serialize_field("payload", pbjson::private::base64::encode(&self.payload).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for validator_transaction::dkg_data::DkgTransactionData { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "epoch", + "author", + "bls_aggregate_signature", + "blsAggregateSignature", + "signer_indices_clan_committee", + "signerIndicesClanCommittee", + "transaction_type", + "transactionType", + "payload", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Epoch, + Author, + BlsAggregateSignature, + SignerIndicesClanCommittee, + TransactionType, + Payload, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "epoch" => Ok(GeneratedField::Epoch), + "author" => Ok(GeneratedField::Author), + "blsAggregateSignature" | "bls_aggregate_signature" => Ok(GeneratedField::BlsAggregateSignature), + "signerIndicesClanCommittee" | "signer_indices_clan_committee" => Ok(GeneratedField::SignerIndicesClanCommittee), + "transactionType" | "transaction_type" => Ok(GeneratedField::TransactionType), + "payload" => Ok(GeneratedField::Payload), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = validator_transaction::dkg_data::DkgTransactionData; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct aptos.transaction.v1.ValidatorTransaction.DkgTransactionData.DkgTransactionData") + } + + fn visit_map(self, mut map: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut epoch__ = None; + let mut author__ = None; + let mut bls_aggregate_signature__ = None; + let mut signer_indices_clan_committee__ = None; + let mut transaction_type__ = None; + let mut payload__ = None; + while let Some(k) = map.next_key()? { + match k { + GeneratedField::Epoch => { + if epoch__.is_some() { + return Err(serde::de::Error::duplicate_field("epoch")); + } + epoch__ = + Some(map.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::Author => { + if author__.is_some() { + return Err(serde::de::Error::duplicate_field("author")); + } + author__ = Some(map.next_value()?); + } + GeneratedField::BlsAggregateSignature => { + if bls_aggregate_signature__.is_some() { + return Err(serde::de::Error::duplicate_field("blsAggregateSignature")); + } + bls_aggregate_signature__ = + Some(map.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + GeneratedField::SignerIndicesClanCommittee => { + if signer_indices_clan_committee__.is_some() { + return Err(serde::de::Error::duplicate_field("signerIndicesClanCommittee")); + } + signer_indices_clan_committee__ = + Some(map.next_value::>>()? + .into_iter().map(|x| x.0).collect()) + ; + } + GeneratedField::TransactionType => { + if transaction_type__.is_some() { + return Err(serde::de::Error::duplicate_field("transactionType")); + } + transaction_type__ = + Some(map.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::Payload => { + if payload__.is_some() { + return Err(serde::de::Error::duplicate_field("payload")); + } + payload__ = + Some(map.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + } + } + Ok(validator_transaction::dkg_data::DkgTransactionData { + epoch: epoch__.unwrap_or_default(), + author: author__.unwrap_or_default(), + bls_aggregate_signature: bls_aggregate_signature__.unwrap_or_default(), + signer_indices_clan_committee: signer_indices_clan_committee__.unwrap_or_default(), + transaction_type: transaction_type__.unwrap_or_default(), + payload: payload__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("aptos.transaction.v1.ValidatorTransaction.DkgTransactionData.DkgTransactionData", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for validator_transaction::ObservedJwkUpdate { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.quorum_certified_update.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("aptos.transaction.v1.ValidatorTransaction.ObservedJwkUpdate", len)?; + if let Some(v) = self.quorum_certified_update.as_ref() { + struct_ser.serialize_field("quorumCertifiedUpdate", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for validator_transaction::ObservedJwkUpdate { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "quorum_certified_update", + "quorumCertifiedUpdate", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + QuorumCertifiedUpdate, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "quorumCertifiedUpdate" | "quorum_certified_update" => Ok(GeneratedField::QuorumCertifiedUpdate), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = validator_transaction::ObservedJwkUpdate; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct aptos.transaction.v1.ValidatorTransaction.ObservedJwkUpdate") + } + + fn visit_map(self, mut map: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, { let mut quorum_certified_update__ = None; while let Some(k) = map.next_key()? { @@ -9725,8 +10010,8 @@ impl<'de> serde::Deserialize<'de> for validator_transaction::observed_jwk_update } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut signer_indices__ = None; let mut sig__ = None; @@ -9847,8 +10132,8 @@ impl<'de> serde::Deserialize<'de> for validator_transaction::observed_jwk_update } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut issuer__ = None; let mut version__ = None; @@ -9967,8 +10252,8 @@ impl<'de> serde::Deserialize<'de> for validator_transaction::observed_jwk_update } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut jwk_type__ = None; while let Some(k) = map.next_key()? { @@ -9978,14 +10263,14 @@ impl<'de> serde::Deserialize<'de> for validator_transaction::observed_jwk_update return Err(serde::de::Error::duplicate_field("unsupportedJwk")); } jwk_type__ = map.next_value::<::std::option::Option<_>>()?.map(validator_transaction::observed_jwk_update::exported_provider_jw_ks::jwk::JwkType::UnsupportedJwk) -; + ; } GeneratedField::Rsa => { if jwk_type__.is_some() { return Err(serde::de::Error::duplicate_field("rsa")); } jwk_type__ = map.next_value::<::std::option::Option<_>>()?.map(validator_transaction::observed_jwk_update::exported_provider_jw_ks::jwk::JwkType::Rsa) -; + ; } } } @@ -10102,8 +10387,8 @@ impl<'de> serde::Deserialize<'de> for validator_transaction::observed_jwk_update } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut kid__ = None; let mut kty__ = None; @@ -10234,8 +10519,8 @@ impl<'de> serde::Deserialize<'de> for validator_transaction::observed_jwk_update } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut id__ = None; let mut payload__ = None; @@ -10347,8 +10632,8 @@ impl<'de> serde::Deserialize<'de> for validator_transaction::observed_jwk_update } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut update__ = None; let mut multi_sig__ = None; @@ -10446,8 +10731,8 @@ impl<'de> serde::Deserialize<'de> for WebAuthn { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut signature__ = None; while let Some(k) = map.next_key()? { @@ -10558,8 +10843,8 @@ impl<'de> serde::Deserialize<'de> for WriteModule { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut address__ = None; let mut state_key_hash__ = None; @@ -10678,8 +10963,8 @@ impl<'de> serde::Deserialize<'de> for WriteOpSizeInfo { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut key_bytes__ = None; let mut value_bytes__ = None; @@ -10819,8 +11104,8 @@ impl<'de> serde::Deserialize<'de> for WriteResource { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut address__ = None; let mut state_key_hash__ = None; @@ -10968,8 +11253,8 @@ impl<'de> serde::Deserialize<'de> for WriteSet { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut write_set_type__ = None; let mut write_set__ = None; @@ -10986,14 +11271,14 @@ impl<'de> serde::Deserialize<'de> for WriteSet { return Err(serde::de::Error::duplicate_field("scriptWriteSet")); } write_set__ = map.next_value::<::std::option::Option<_>>()?.map(write_set::WriteSet::ScriptWriteSet) -; + ; } GeneratedField::DirectWriteSet => { if write_set__.is_some() { return Err(serde::de::Error::duplicate_field("directWriteSet")); } write_set__ = map.next_value::<::std::option::Option<_>>()?.map(write_set::WriteSet::DirectWriteSet) -; + ; } } } @@ -11202,8 +11487,8 @@ impl<'de> serde::Deserialize<'de> for WriteSetChange { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut r#type__ = None; let mut change__ = None; @@ -11220,42 +11505,42 @@ impl<'de> serde::Deserialize<'de> for WriteSetChange { return Err(serde::de::Error::duplicate_field("deleteModule")); } change__ = map.next_value::<::std::option::Option<_>>()?.map(write_set_change::Change::DeleteModule) -; + ; } GeneratedField::DeleteResource => { if change__.is_some() { return Err(serde::de::Error::duplicate_field("deleteResource")); } change__ = map.next_value::<::std::option::Option<_>>()?.map(write_set_change::Change::DeleteResource) -; + ; } GeneratedField::DeleteTableItem => { if change__.is_some() { return Err(serde::de::Error::duplicate_field("deleteTableItem")); } change__ = map.next_value::<::std::option::Option<_>>()?.map(write_set_change::Change::DeleteTableItem) -; + ; } GeneratedField::WriteModule => { if change__.is_some() { return Err(serde::de::Error::duplicate_field("writeModule")); } change__ = map.next_value::<::std::option::Option<_>>()?.map(write_set_change::Change::WriteModule) -; + ; } GeneratedField::WriteResource => { if change__.is_some() { return Err(serde::de::Error::duplicate_field("writeResource")); } change__ = map.next_value::<::std::option::Option<_>>()?.map(write_set_change::Change::WriteResource) -; + ; } GeneratedField::WriteTableItem => { if change__.is_some() { return Err(serde::de::Error::duplicate_field("writeTableItem")); } change__ = map.next_value::<::std::option::Option<_>>()?.map(write_set_change::Change::WriteTableItem) -; + ; } } } @@ -11426,8 +11711,8 @@ impl<'de> serde::Deserialize<'de> for WriteSetPayload { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut write_set__ = None; while let Some(k) = map.next_key()? { @@ -11546,8 +11831,8 @@ impl<'de> serde::Deserialize<'de> for WriteTableData { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut key__ = None; let mut key_type__ = None; @@ -11689,8 +11974,8 @@ impl<'de> serde::Deserialize<'de> for WriteTableItem { } fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + where + V: serde::de::MapAccess<'de>, { let mut state_key_hash__ = None; let mut handle__ = None; @@ -11736,4 +12021,4 @@ impl<'de> serde::Deserialize<'de> for WriteTableItem { } deserializer.deserialize_struct("aptos.transaction.v1.WriteTableItem", FIELDS, GeneratedVisitor) } -} +} \ No newline at end of file diff --git a/rust-toolchain.toml b/rust-toolchain.toml index b7051f1e849..68a2a77e5c5 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.86.0" +channel = "1.93.0" # Note: we don't specify cargofmt in our toolchain because we rely on # the nightly version of cargofmt and verify formatting in CI/CD. diff --git a/sdk/src/transaction_builder.rs b/sdk/src/transaction_builder.rs index a5f4477e2e7..7db0ecab262 100644 --- a/sdk/src/transaction_builder.rs +++ b/sdk/src/transaction_builder.rs @@ -218,14 +218,14 @@ impl TransactionFactory { &self, additional_owners: Vec, signatures_required: u64, - timeout_duration: u64, + timeout_duration: u64, ) -> TransactionBuilder { self.payload(aptos_stdlib::multisig_account_create_with_owners( additional_owners, signatures_required, vec![], vec![], - timeout_duration, + timeout_duration, )) } @@ -241,7 +241,7 @@ impl TransactionFactory { signatures_required, vec![], vec![], - timeout_duration + timeout_duration, ), ) } @@ -258,7 +258,7 @@ impl TransactionFactory { signatures_required, vec![], vec![], - timeout_duration + timeout_duration, ), ) } diff --git a/storage/accumulator/src/lib.rs b/storage/accumulator/src/lib.rs index fd464a7cf9f..4aff47df438 100644 --- a/storage/accumulator/src/lib.rs +++ b/storage/accumulator/src/lib.rs @@ -160,6 +160,14 @@ where MerkleAccumulatorView::::new(reader, num_leaves).get_proof(leaf_index) } + pub fn get_proof_by_position( + reader: &R, + num_leaves: LeafCount, + position: Position, + ) -> Result> { + MerkleAccumulatorView::::new(reader, num_leaves).get_proof_by_position(position) + } + /// Gets a proof that shows the full accumulator is consistent with a smaller accumulator. /// /// See [`aptos_types::proof::AccumulatorConsistencyProof`] for proof format. @@ -367,6 +375,17 @@ where Ok(AccumulatorProof::new(siblings)) } + fn get_proof_by_position(&self, position: Position) -> Result> { + let root_pos = Position::root_from_leaf_count(self.num_leaves); + let siblings = self.get_hashes( + &position + .iter_ancestor_sibling() + .take(root_pos.level() as usize) + .collect::>(), + )?; + Ok(AccumulatorProof::new(siblings)) + } + /// Implementation for public interface `MerkleAccumulator::get_consistency_proof`. fn get_consistency_proof( &self, diff --git a/storage/aptosdb/Cargo.toml b/storage/aptosdb/Cargo.toml index 4fb97d2c14a..951c7031120 100644 --- a/storage/aptosdb/Cargo.toml +++ b/storage/aptosdb/Cargo.toml @@ -73,6 +73,23 @@ rand = { workspace = true } [features] default = [] -fuzzing = ["proptest", "proptest-derive", "aptos-proptest-helpers", "aptos-temppath", "aptos-crypto/fuzzing", "aptos-jellyfish-merkle/fuzzing", "aptos-types/fuzzing", "aptos-executor-types/fuzzing", "aptos-schemadb/fuzzing", "aptos-scratchpad/fuzzing"] +fuzzing = [ + "proptest", + "proptest-derive", + "aptos-proptest-helpers", + "aptos-temppath", + "aptos-crypto/fuzzing", + "aptos-jellyfish-merkle/fuzzing", + "aptos-types/fuzzing", + "aptos-executor-types/fuzzing", + "aptos-schemadb/fuzzing", + "aptos-scratchpad/fuzzing", +] consensus-only-perf-test = [] -db-debugger = ["aptos-temppath", "clap", "crossbeam-channel", "owo-colors", "indicatif"] +db-debugger = [ + "aptos-temppath", + "clap", + "crossbeam-channel", + "owo-colors", + "indicatif", +] diff --git a/storage/backup/backup-cli/src/backup_types/transaction/analysis.rs b/storage/backup/backup-cli/src/backup_types/transaction/analysis.rs index 78a56c6439e..d2b7473fbb0 100644 --- a/storage/backup/backup-cli/src/backup_types/transaction/analysis.rs +++ b/storage/backup/backup-cli/src/backup_types/transaction/analysis.rs @@ -115,8 +115,9 @@ impl TransactionAnalysis { match txn { UserTransaction(signed_txn) => signed_txn.raw_txn_bytes_len(), - AutomatedTransaction(automated_txn) - | SystemAutomatedTransaction(automated_txn) => automated_txn.raw_txn_bytes_len(), + AutomatedTransaction(automated_txn) | SystemAutomatedTransaction(automated_txn) => { + automated_txn.raw_txn_bytes_len() + }, GenesisTransaction(_) | BlockMetadata(_) | BlockMetadataExt(_) diff --git a/storage/indexer_schemas/Cargo.toml b/storage/indexer_schemas/Cargo.toml index b25ff3cb50f..0837ec5d654 100644 --- a/storage/indexer_schemas/Cargo.toml +++ b/storage/indexer_schemas/Cargo.toml @@ -34,4 +34,9 @@ rand = { workspace = true } [features] default = [] -fuzzing = ["proptest", "proptest-derive", "aptos-types/fuzzing", "aptos-schemadb/fuzzing"] +fuzzing = [ + "proptest", + "proptest-derive", + "aptos-types/fuzzing", + "aptos-schemadb/fuzzing", +] diff --git a/storage/jellyfish-merkle/Cargo.toml b/storage/jellyfish-merkle/Cargo.toml index 3894481f9d1..d2438ad608f 100644 --- a/storage/jellyfish-merkle/Cargo.toml +++ b/storage/jellyfish-merkle/Cargo.toml @@ -45,4 +45,9 @@ rand = { workspace = true } [features] default = [] -fuzzing = ["proptest", "proptest-derive", "aptos-crypto/fuzzing", "aptos-types/fuzzing"] +fuzzing = [ + "proptest", + "proptest-derive", + "aptos-crypto/fuzzing", + "aptos-types/fuzzing", +] diff --git a/testsuite/forge/Cargo.toml b/testsuite/forge/Cargo.toml index 19aed74dbef..016008391fa 100644 --- a/testsuite/forge/Cargo.toml +++ b/testsuite/forge/Cargo.toml @@ -45,9 +45,14 @@ hyper = { workspace = true } itertools = { workspace = true } json-patch = { workspace = true } k8s-openapi = { version = "0.13.1", default-features = false, features = [ - "v1_22", + "v1_22", +] } +kube = { version = "0.65.0", default-features = false, features = [ + "jsonpatch", + "client", + "rustls-tls", + "derive", ] } -kube = { version = "0.65.0", default-features = false, features = ["jsonpatch", "client", "rustls-tls", "derive"] } log = { workspace = true } num_cpus = { workspace = true } once_cell = { workspace = true } diff --git a/testsuite/fuzzer/.cargo/config.toml b/testsuite/fuzzer/.cargo/config.toml index b9891568c79..90aa2f43f09 100644 --- a/testsuite/fuzzer/.cargo/config.toml +++ b/testsuite/fuzzer/.cargo/config.toml @@ -1,8 +1,26 @@ target-applies-to-host = false [host.aarch64-apple-darwin] -rustflags = ["--cfg", "tokio_unstable", "-C", "force-frame-pointers=yes", "-C", "force-unwind-tables=yes"] +rustflags = [ + "--cfg", + "tokio_unstable", + "-C", + "force-frame-pointers=yes", + "-C", + "force-unwind-tables=yes", +] [host.x86_64-unknown-linux-gnu] linker = "clang" -rustflags = ["--cfg", "tokio_unstable", "-C", "link-args=-fuse-ld=gold -Wl,--no-keep-files-mapped -Wl,--no-keep-memory -Wl,--no-threads", "-C", "codegen-units=1", "-C", "force-frame-pointers=yes", "-C", "force-unwind-tables=yes", "-C", "target-feature=+sse4.2"] +rustflags = [ + "--cfg", + "tokio_unstable", + "-C", + "link-args=-fuse-ld=gold -Wl,--no-keep-files-mapped -Wl,--no-keep-memory -Wl,--no-threads", "-C", "codegen-units=1", + "-C", + "force-frame-pointers=yes", + "-C", + "force-unwind-tables=yes", + "-C", + "target-feature=+sse4.2", +] diff --git a/testsuite/pyproject.toml b/testsuite/pyproject.toml index 3eb002623c0..fad50f770ae 100644 --- a/testsuite/pyproject.toml +++ b/testsuite/pyproject.toml @@ -27,4 +27,4 @@ build-backend = "poetry.core.masonry.api" [tool.pyright] reportUndefinedVariable = "none" -typeCheckingMode = "basic" # TODO(rustielin): eventually make this strict +typeCheckingMode = "basic" # TODO(rustielin): eventually make this strict diff --git a/testsuite/smoke-test/Cargo.toml b/testsuite/smoke-test/Cargo.toml index 0571013eaf3..97667d8532b 100644 --- a/testsuite/smoke-test/Cargo.toml +++ b/testsuite/smoke-test/Cargo.toml @@ -46,11 +46,11 @@ aptos-types = { workspace = true } aptos-vm = { workspace = true } bcs = { workspace = true } diesel = { workspace = true, features = [ - "chrono", - "postgres", - "r2d2", - "numeric", - "serde_json", + "chrono", + "postgres", + "r2d2", + "numeric", + "serde_json", ] } digest = { workspace = true } ethers = { workspace = true } diff --git a/third_party/move/extensions/move-table-extension/Cargo.toml b/third_party/move/extensions/move-table-extension/Cargo.toml index 07a9759b45b..4b8440eabef 100644 --- a/third_party/move/extensions/move-table-extension/Cargo.toml +++ b/third_party/move/extensions/move-table-extension/Cargo.toml @@ -22,5 +22,7 @@ smallvec = { workspace = true } move-cli = { workspace = true } move-package = { workspace = true } move-stdlib = { path = "../../move-stdlib", features = ["testing"] } -move-unit-test = { workspace = true, features = ["table-extension"] } +move-unit-test = { workspace = true, features = [ + "table-extension", +] } tempfile = { workspace = true } diff --git a/third_party/move/move-binary-format/Cargo.toml b/third_party/move/move-binary-format/Cargo.toml index 8a9f3bc8728..69bfac7b2b3 100644 --- a/third_party/move/move-binary-format/Cargo.toml +++ b/third_party/move/move-binary-format/Cargo.toml @@ -32,5 +32,10 @@ serde_json = { workspace = true } [features] default = [] -fuzzing = ["proptest", "proptest-derive", "arbitrary", "dearbitrary", "move-core-types/fuzzing"] +fuzzing = [ + "proptest", + "proptest-derive", + "arbitrary", + "dearbitrary", "move-core-types/fuzzing", +] testing = [] diff --git a/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml b/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml index 30c43d5d75f..6b38334f7dc 100644 --- a/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml +++ b/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml @@ -12,7 +12,9 @@ edition = "2021" [dev-dependencies] fail = { workspace = true, features = ['failpoints'] } hex = { workspace = true } -move-binary-format = { workspace = true, features = ["fuzzing"] } +move-binary-format = { workspace = true, features = [ + "fuzzing", +] } move-bytecode-verifier = { workspace = true } move-bytecode-verifier-invalid-mutations = { workspace = true } move-core-types = { workspace = true } diff --git a/third_party/move/move-bytecode-verifier/fuzz/Cargo.toml b/third_party/move/move-bytecode-verifier/fuzz/Cargo.toml index 7de0a965aba..3600c958d41 100644 --- a/third_party/move/move-bytecode-verifier/fuzz/Cargo.toml +++ b/third_party/move/move-bytecode-verifier/fuzz/Cargo.toml @@ -12,7 +12,9 @@ cargo-fuzz = true [dependencies] arbitrary = { workspace = true } libfuzzer-sys = { workspace = true } -move-binary-format = { workspace = true, features = ["fuzzing"] } +move-binary-format = { workspace = true, features = [ + "fuzzing", +] } move-bytecode-verifier = { workspace = true } move-core-types = { workspace = true, features = ["fuzzing"] } diff --git a/third_party/move/move-core/types/Cargo.toml b/third_party/move/move-core/types/Cargo.toml index da9c7b9f5f3..f104b79e039 100644 --- a/third_party/move/move-core/types/Cargo.toml +++ b/third_party/move/move-core/types/Cargo.toml @@ -11,7 +11,9 @@ edition = "2021" [dependencies] anyhow = { workspace = true } -arbitrary = { workspace = true, features = ["derive_arbitrary"], optional = true } +arbitrary = { workspace = true, features = [ + "derive_arbitrary", +], optional = true } bcs = { workspace = true } bytes = { workspace = true } dearbitrary = { workspace = true, optional = true, features = ["derive"] } diff --git a/third_party/move/move-core/types/src/vm_status.rs b/third_party/move/move-core/types/src/vm_status.rs index a308c4114cc..de1c04490b1 100644 --- a/third_party/move/move-core/types/src/vm_status.rs +++ b/third_party/move/move-core/types/src/vm_status.rs @@ -631,13 +631,32 @@ pub enum StatusCode { // Gas unit price capacity submitted for the automation-task is above the maximum // gas price set in the VM. AUTOMATION_TASK_GAS_PRICE_CAP_ABOVE_MAX_BOUND = 50, - // Reserved error code for future use - RESERVED_VALIDATION_ERROR_10 = 51, - RESERVED_VALIDATION_ERROR_11 = 52, - RESERVED_VALIDATION_ERROR_12 = 53, - RESERVED_VALIDATION_ERROR_13 = 54, - RESERVED_VALIDATION_ERROR_14 = 55, - RESERVED_VALIDATION_ERROR_15 = 56, + // DKG session is currently not in progress + DKG_SESSION_NOT_IN_PROGRESS = 51, + // DKG transaction has a future epoch number + DKG_TRANSACTION_FUTURE_EPOCH_NUM = 52, + // DKG transaction has a past epoch number + DKG_TRANSACTION_PAST_EPOCH_NUM = 53, + // DKG meta has already set so DKGMeta transaction should fail + DKG_META_ALREADY_SET = 54, + // DKG transaction data is invalid + DKG_TRANSACTION_NOT_VALID = 55, + // The sender of the dkg transaction is not a family node + DKG_TRANSACTION_SENDER_NOT_FAMILY_NODE = 56, + // Failed to get the public keys for the signer clan nodes + DKG_FAILED_TO_GET_CLAN_NODE_PUBKEYS = 57, + // Failed to deserialize the aggregated signature + DKG_FAILED_TO_DESER_AGG_SIG = 58, + // Failed to aggregate the public keys for the signer clan nodes + DKG_FAILED_TO_AGGREGATE_PUBLIC_KEYS = 59, + // Failed to verify the clan committee aggregated signature + DKG_AGG_SIG_VERIFICATION_FAILED = 60, // Reserved error code for future use + RESERVED_VALIDATION_ERROR_10 = 61, + RESERVED_VALIDATION_ERROR_11 = 62, + RESERVED_VALIDATION_ERROR_12 = 63, + RESERVED_VALIDATION_ERROR_13 = 64, + RESERVED_VALIDATION_ERROR_14 = 65, + RESERVED_VALIDATION_ERROR_15 = 66, // When a code module/script is published it is verified. These are the diff --git a/third_party/move/move-examples/diem-framework/crates/crypto/Cargo.toml b/third_party/move/move-examples/diem-framework/crates/crypto/Cargo.toml index bbca086b375..c077223c368 100644 --- a/third_party/move/move-examples/diem-framework/crates/crypto/Cargo.toml +++ b/third_party/move/move-examples/diem-framework/crates/crypto/Cargo.toml @@ -10,10 +10,15 @@ license = "Apache-2.0" aes-gcm = { workspace = true } anyhow = { workspace = true } bytes = { workspace = true } -curve25519-dalek = { workspace = true, package = "curve25519-dalek-fiat", features = ["std"] } +curve25519-dalek = { workspace = true, package = "curve25519-dalek-fiat", features = [ + "std", +] } diem-crypto-derive = { path = "../crypto-derive" } digest = { workspace = true } -ed25519-dalek = { workspace = true, package = "ed25519-dalek-fiat", features = ["std", "serde"] } +ed25519-dalek = { workspace = true, package = "ed25519-dalek-fiat", features = [ + "std", + "serde", +] } hex = { workspace = true } hkdf = { workspace = true } mirai-annotations = { workspace = true } @@ -28,7 +33,9 @@ sha2 = { workspace = true } static_assertions = { workspace = true } thiserror = { workspace = true } tiny-keccak = { workspace = true, features = ["sha3"] } -x25519-dalek = { workspace = true, package = "x25519-dalek-fiat", features = ["std"] } +x25519-dalek = { workspace = true, package = "x25519-dalek-fiat", features = [ + "std", +] } bcs = { workspace = true } @@ -49,9 +56,21 @@ default = ["fiat"] assert-private-keys-not-cloneable = [] cloneable-private-keys = [] fuzzing = ["proptest", "proptest-derive", "cloneable-private-keys"] -fiat = ["curve25519-dalek/fiat_u64_backend", "ed25519-dalek/fiat_u64_backend", "x25519-dalek/fiat_u64_backend"] -u64 = ["curve25519-dalek/u64_backend", "ed25519-dalek/u64_backend", "x25519-dalek/u64_backend"] -u32 = ["curve25519-dalek/u32_backend", "ed25519-dalek/u32_backend", "x25519-dalek/u32_backend"] +fiat = [ + "curve25519-dalek/fiat_u64_backend", + "ed25519-dalek/fiat_u64_backend", + "x25519-dalek/fiat_u64_backend", +] +u64 = [ + "curve25519-dalek/u64_backend", + "ed25519-dalek/u64_backend", + "x25519-dalek/u64_backend", +] +u32 = [ + "curve25519-dalek/u32_backend", + "ed25519-dalek/u32_backend", + "x25519-dalek/u32_backend", +] [[bench]] name = "noise" diff --git a/third_party/move/move-prover/lab/data/aptos-framework/prover.toml b/third_party/move/move-prover/lab/data/aptos-framework/prover.toml index 2f0df57c653..46f11342e24 100644 --- a/third_party/move/move-prover/lab/data/aptos-framework/prover.toml +++ b/third_party/move/move-prover/lab/data/aptos-framework/prover.toml @@ -1,16 +1,16 @@ move_named_address_values = [ - "std=0x1", - "aptos_std=0x1", - "supra_framework=0x1", - "aptos_token=0x3", - "core_resources=0xA550C18", - "vm_reserved=0x0", - "Extensions=0x1", - "vm=0x0", - "aptos_fungible_asset=0xA" + "std=0x1", + "aptos_std=0x1", + "supra_framework=0x1", + "aptos_token=0x3", + "core_resources=0xA550C18", + "vm_reserved=0x0", + "Extensions=0x1", + "vm=0x0", + "aptos_fungible_asset=0xA" ] move_deps = [ - "../../../../../../aptos-move/framework/move-stdlib/sources", - "../../../../../../aptos-move/framework/aptos-stdlib/sources", - "../../../../../../aptos-move/framework/supra-framework/sources", + "../../../../../../aptos-move/framework/move-stdlib/sources", + "../../../../../../aptos-move/framework/aptos-stdlib/sources", + "../../../../../../aptos-move/framework/supra-framework/sources", ] diff --git a/third_party/move/move-prover/lab/data/diem-framework/prover.toml b/third_party/move/move-prover/lab/data/diem-framework/prover.toml index 5c0fe4c002f..b990557b1d6 100644 --- a/third_party/move/move-prover/lab/data/diem-framework/prover.toml +++ b/third_party/move/move-prover/lab/data/diem-framework/prover.toml @@ -1,13 +1,13 @@ move_named_address_values = [ - "std=0x1", - "DiemFramework=0x1", - "DiemRoot=0xA550C18", - "TreasuryCompliance=0xB1E55ED", - "CurrencyInfo=0xA550C18", - "VMReserved=0x0", + "std=0x1", + "DiemFramework=0x1", + "DiemRoot=0xA550C18", + "TreasuryCompliance=0xB1E55ED", + "CurrencyInfo=0xA550C18", + "VMReserved=0x0", ] move_deps = [ - "../../../../../../aptos-move/framework/move-stdlib/sources", - "../../../../../../aptos-move/framework/aptos-stdlib/sources", - "../../../../../../aptos-move/framework/aptos-framework/sources", + "../../../../../../aptos-move/framework/move-stdlib/sources", + "../../../../../../aptos-move/framework/aptos-stdlib/sources", + "../../../../../../aptos-move/framework/aptos-framework/sources", ] diff --git a/third_party/move/move-prover/lab/data/mono/mono_backend.toml b/third_party/move/move-prover/lab/data/mono/mono_backend.toml index e69de29bb2d..8b137891791 100644 --- a/third_party/move/move-prover/lab/data/mono/mono_backend.toml +++ b/third_party/move/move-prover/lab/data/mono/mono_backend.toml @@ -0,0 +1 @@ + diff --git a/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/current_boogie_1.toml b/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/current_boogie_1.toml index 2f0df57c653..46f11342e24 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/current_boogie_1.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/current_boogie_1.toml @@ -1,16 +1,16 @@ move_named_address_values = [ - "std=0x1", - "aptos_std=0x1", - "supra_framework=0x1", - "aptos_token=0x3", - "core_resources=0xA550C18", - "vm_reserved=0x0", - "Extensions=0x1", - "vm=0x0", - "aptos_fungible_asset=0xA" + "std=0x1", + "aptos_std=0x1", + "supra_framework=0x1", + "aptos_token=0x3", + "core_resources=0xA550C18", + "vm_reserved=0x0", + "Extensions=0x1", + "vm=0x0", + "aptos_fungible_asset=0xA" ] move_deps = [ - "../../../../../../aptos-move/framework/move-stdlib/sources", - "../../../../../../aptos-move/framework/aptos-stdlib/sources", - "../../../../../../aptos-move/framework/supra-framework/sources", + "../../../../../../aptos-move/framework/move-stdlib/sources", + "../../../../../../aptos-move/framework/aptos-stdlib/sources", + "../../../../../../aptos-move/framework/supra-framework/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/current_boogie_2.toml b/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/current_boogie_2.toml index 2f0df57c653..46f11342e24 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/current_boogie_2.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/current_boogie_2.toml @@ -1,16 +1,16 @@ move_named_address_values = [ - "std=0x1", - "aptos_std=0x1", - "supra_framework=0x1", - "aptos_token=0x3", - "core_resources=0xA550C18", - "vm_reserved=0x0", - "Extensions=0x1", - "vm=0x0", - "aptos_fungible_asset=0xA" + "std=0x1", + "aptos_std=0x1", + "supra_framework=0x1", + "aptos_token=0x3", + "core_resources=0xA550C18", + "vm_reserved=0x0", + "Extensions=0x1", + "vm=0x0", + "aptos_fungible_asset=0xA" ] move_deps = [ - "../../../../../../aptos-move/framework/move-stdlib/sources", - "../../../../../../aptos-move/framework/aptos-stdlib/sources", - "../../../../../../aptos-move/framework/supra-framework/sources", + "../../../../../../aptos-move/framework/move-stdlib/sources", + "../../../../../../aptos-move/framework/aptos-stdlib/sources", + "../../../../../../aptos-move/framework/supra-framework/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/current_boogie_3.toml b/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/current_boogie_3.toml index 2f0df57c653..46f11342e24 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/current_boogie_3.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/current_boogie_3.toml @@ -1,16 +1,16 @@ move_named_address_values = [ - "std=0x1", - "aptos_std=0x1", - "supra_framework=0x1", - "aptos_token=0x3", - "core_resources=0xA550C18", - "vm_reserved=0x0", - "Extensions=0x1", - "vm=0x0", - "aptos_fungible_asset=0xA" + "std=0x1", + "aptos_std=0x1", + "supra_framework=0x1", + "aptos_token=0x3", + "core_resources=0xA550C18", + "vm_reserved=0x0", + "Extensions=0x1", + "vm=0x0", + "aptos_fungible_asset=0xA" ] move_deps = [ - "../../../../../../aptos-move/framework/move-stdlib/sources", - "../../../../../../aptos-move/framework/aptos-stdlib/sources", - "../../../../../../aptos-move/framework/supra-framework/sources", + "../../../../../../aptos-move/framework/move-stdlib/sources", + "../../../../../../aptos-move/framework/aptos-stdlib/sources", + "../../../../../../aptos-move/framework/supra-framework/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/new_boogie_1.toml b/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/new_boogie_1.toml index 2f0df57c653..46f11342e24 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/new_boogie_1.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/new_boogie_1.toml @@ -1,16 +1,16 @@ move_named_address_values = [ - "std=0x1", - "aptos_std=0x1", - "supra_framework=0x1", - "aptos_token=0x3", - "core_resources=0xA550C18", - "vm_reserved=0x0", - "Extensions=0x1", - "vm=0x0", - "aptos_fungible_asset=0xA" + "std=0x1", + "aptos_std=0x1", + "supra_framework=0x1", + "aptos_token=0x3", + "core_resources=0xA550C18", + "vm_reserved=0x0", + "Extensions=0x1", + "vm=0x0", + "aptos_fungible_asset=0xA" ] move_deps = [ - "../../../../../../aptos-move/framework/move-stdlib/sources", - "../../../../../../aptos-move/framework/aptos-stdlib/sources", - "../../../../../../aptos-move/framework/supra-framework/sources", + "../../../../../../aptos-move/framework/move-stdlib/sources", + "../../../../../../aptos-move/framework/aptos-stdlib/sources", + "../../../../../../aptos-move/framework/supra-framework/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/new_boogie_2.toml b/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/new_boogie_2.toml index 2f0df57c653..46f11342e24 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/new_boogie_2.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/new_boogie_2.toml @@ -1,16 +1,16 @@ move_named_address_values = [ - "std=0x1", - "aptos_std=0x1", - "supra_framework=0x1", - "aptos_token=0x3", - "core_resources=0xA550C18", - "vm_reserved=0x0", - "Extensions=0x1", - "vm=0x0", - "aptos_fungible_asset=0xA" + "std=0x1", + "aptos_std=0x1", + "supra_framework=0x1", + "aptos_token=0x3", + "core_resources=0xA550C18", + "vm_reserved=0x0", + "Extensions=0x1", + "vm=0x0", + "aptos_fungible_asset=0xA" ] move_deps = [ - "../../../../../../aptos-move/framework/move-stdlib/sources", - "../../../../../../aptos-move/framework/aptos-stdlib/sources", - "../../../../../../aptos-move/framework/supra-framework/sources", + "../../../../../../aptos-move/framework/move-stdlib/sources", + "../../../../../../aptos-move/framework/aptos-stdlib/sources", + "../../../../../../aptos-move/framework/supra-framework/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/new_boogie_3.toml b/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/new_boogie_3.toml index 2f0df57c653..46f11342e24 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/new_boogie_3.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-aptos-framework/new_boogie_3.toml @@ -1,16 +1,16 @@ move_named_address_values = [ - "std=0x1", - "aptos_std=0x1", - "supra_framework=0x1", - "aptos_token=0x3", - "core_resources=0xA550C18", - "vm_reserved=0x0", - "Extensions=0x1", - "vm=0x0", - "aptos_fungible_asset=0xA" + "std=0x1", + "aptos_std=0x1", + "supra_framework=0x1", + "aptos_token=0x3", + "core_resources=0xA550C18", + "vm_reserved=0x0", + "Extensions=0x1", + "vm=0x0", + "aptos_fungible_asset=0xA" ] move_deps = [ - "../../../../../../aptos-move/framework/move-stdlib/sources", - "../../../../../../aptos-move/framework/aptos-stdlib/sources", - "../../../../../../aptos-move/framework/supra-framework/sources", + "../../../../../../aptos-move/framework/move-stdlib/sources", + "../../../../../../aptos-move/framework/aptos-stdlib/sources", + "../../../../../../aptos-move/framework/supra-framework/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/current_boogie_1.toml b/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/current_boogie_1.toml index 73faf2039f6..91ce30e6fac 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/current_boogie_1.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/current_boogie_1.toml @@ -1,15 +1,15 @@ move_named_address_values = [ - "std=0x1", - "aptos_std=0x1", - "supra_framework=0x1", - "aptos_token=0x3", - "core_resources=0xA550C18", - "vm_reserved=0x0", - "Extensions=0x1", - "vm=0x0", - "aptos_fungible_asset=0xA" + "std=0x1", + "aptos_std=0x1", + "supra_framework=0x1", + "aptos_token=0x3", + "core_resources=0xA550C18", + "vm_reserved=0x0", + "Extensions=0x1", + "vm=0x0", + "aptos_fungible_asset=0xA" ] move_deps = [ - "../../../../../../aptos-move/framework/move-stdlib/sources", - "../../../../../../aptos-move/framework/aptos-stdlib/sources", + "../../../../../../aptos-move/framework/move-stdlib/sources", + "../../../../../../aptos-move/framework/aptos-stdlib/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/current_boogie_2.toml b/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/current_boogie_2.toml index 73faf2039f6..91ce30e6fac 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/current_boogie_2.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/current_boogie_2.toml @@ -1,15 +1,15 @@ move_named_address_values = [ - "std=0x1", - "aptos_std=0x1", - "supra_framework=0x1", - "aptos_token=0x3", - "core_resources=0xA550C18", - "vm_reserved=0x0", - "Extensions=0x1", - "vm=0x0", - "aptos_fungible_asset=0xA" + "std=0x1", + "aptos_std=0x1", + "supra_framework=0x1", + "aptos_token=0x3", + "core_resources=0xA550C18", + "vm_reserved=0x0", + "Extensions=0x1", + "vm=0x0", + "aptos_fungible_asset=0xA" ] move_deps = [ - "../../../../../../aptos-move/framework/move-stdlib/sources", - "../../../../../../aptos-move/framework/aptos-stdlib/sources", + "../../../../../../aptos-move/framework/move-stdlib/sources", + "../../../../../../aptos-move/framework/aptos-stdlib/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/current_boogie_3.toml b/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/current_boogie_3.toml index 73faf2039f6..91ce30e6fac 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/current_boogie_3.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/current_boogie_3.toml @@ -1,15 +1,15 @@ move_named_address_values = [ - "std=0x1", - "aptos_std=0x1", - "supra_framework=0x1", - "aptos_token=0x3", - "core_resources=0xA550C18", - "vm_reserved=0x0", - "Extensions=0x1", - "vm=0x0", - "aptos_fungible_asset=0xA" + "std=0x1", + "aptos_std=0x1", + "supra_framework=0x1", + "aptos_token=0x3", + "core_resources=0xA550C18", + "vm_reserved=0x0", + "Extensions=0x1", + "vm=0x0", + "aptos_fungible_asset=0xA" ] move_deps = [ - "../../../../../../aptos-move/framework/move-stdlib/sources", - "../../../../../../aptos-move/framework/aptos-stdlib/sources", + "../../../../../../aptos-move/framework/move-stdlib/sources", + "../../../../../../aptos-move/framework/aptos-stdlib/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/new_boogie_1.toml b/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/new_boogie_1.toml index 73faf2039f6..91ce30e6fac 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/new_boogie_1.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/new_boogie_1.toml @@ -1,15 +1,15 @@ move_named_address_values = [ - "std=0x1", - "aptos_std=0x1", - "supra_framework=0x1", - "aptos_token=0x3", - "core_resources=0xA550C18", - "vm_reserved=0x0", - "Extensions=0x1", - "vm=0x0", - "aptos_fungible_asset=0xA" + "std=0x1", + "aptos_std=0x1", + "supra_framework=0x1", + "aptos_token=0x3", + "core_resources=0xA550C18", + "vm_reserved=0x0", + "Extensions=0x1", + "vm=0x0", + "aptos_fungible_asset=0xA" ] move_deps = [ - "../../../../../../aptos-move/framework/move-stdlib/sources", - "../../../../../../aptos-move/framework/aptos-stdlib/sources", + "../../../../../../aptos-move/framework/move-stdlib/sources", + "../../../../../../aptos-move/framework/aptos-stdlib/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/new_boogie_2.toml b/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/new_boogie_2.toml index 73faf2039f6..91ce30e6fac 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/new_boogie_2.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/new_boogie_2.toml @@ -1,15 +1,15 @@ move_named_address_values = [ - "std=0x1", - "aptos_std=0x1", - "supra_framework=0x1", - "aptos_token=0x3", - "core_resources=0xA550C18", - "vm_reserved=0x0", - "Extensions=0x1", - "vm=0x0", - "aptos_fungible_asset=0xA" + "std=0x1", + "aptos_std=0x1", + "supra_framework=0x1", + "aptos_token=0x3", + "core_resources=0xA550C18", + "vm_reserved=0x0", + "Extensions=0x1", + "vm=0x0", + "aptos_fungible_asset=0xA" ] move_deps = [ - "../../../../../../aptos-move/framework/move-stdlib/sources", - "../../../../../../aptos-move/framework/aptos-stdlib/sources", + "../../../../../../aptos-move/framework/move-stdlib/sources", + "../../../../../../aptos-move/framework/aptos-stdlib/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/new_boogie_3.toml b/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/new_boogie_3.toml index 73faf2039f6..91ce30e6fac 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/new_boogie_3.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-aptos-stdlib/new_boogie_3.toml @@ -1,15 +1,15 @@ move_named_address_values = [ - "std=0x1", - "aptos_std=0x1", - "supra_framework=0x1", - "aptos_token=0x3", - "core_resources=0xA550C18", - "vm_reserved=0x0", - "Extensions=0x1", - "vm=0x0", - "aptos_fungible_asset=0xA" + "std=0x1", + "aptos_std=0x1", + "supra_framework=0x1", + "aptos_token=0x3", + "core_resources=0xA550C18", + "vm_reserved=0x0", + "Extensions=0x1", + "vm=0x0", + "aptos_fungible_asset=0xA" ] move_deps = [ - "../../../../../../aptos-move/framework/move-stdlib/sources", - "../../../../../../aptos-move/framework/aptos-stdlib/sources", + "../../../../../../aptos-move/framework/move-stdlib/sources", + "../../../../../../aptos-move/framework/aptos-stdlib/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-diem-framework/current_boogie.toml b/third_party/move/move-prover/lab/data/new-boogie-diem-framework/current_boogie.toml index ea89bd85520..71575034c2f 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-diem-framework/current_boogie.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-diem-framework/current_boogie.toml @@ -1,13 +1,13 @@ move_named_address_values = [ - "std=0x1", - "DiemFramework=0x1", - "DiemRoot=0xA550C18", - "TreasuryCompliance=0xB1E55ED", - "CurrencyInfo=0xA550C18", - "VMReserved=0x0", + "std=0x1", + "DiemFramework=0x1", + "DiemRoot=0xA550C18", + "TreasuryCompliance=0xB1E55ED", + "CurrencyInfo=0xA550C18", + "VMReserved=0x0", ] move_deps = [ - "../../../../move-examples/diem-framework/move-packages/DPN/sources", - "../../../../move-stdlib/sources", - "../../../../move-stdlib/nursery/sources", + "../../../../move-examples/diem-framework/move-packages/DPN/sources", + "../../../../move-stdlib/sources", + "../../../../move-stdlib/nursery/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie.toml b/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie.toml index ea89bd85520..71575034c2f 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie.toml @@ -1,13 +1,13 @@ move_named_address_values = [ - "std=0x1", - "DiemFramework=0x1", - "DiemRoot=0xA550C18", - "TreasuryCompliance=0xB1E55ED", - "CurrencyInfo=0xA550C18", - "VMReserved=0x0", + "std=0x1", + "DiemFramework=0x1", + "DiemRoot=0xA550C18", + "TreasuryCompliance=0xB1E55ED", + "CurrencyInfo=0xA550C18", + "VMReserved=0x0", ] move_deps = [ - "../../../../move-examples/diem-framework/move-packages/DPN/sources", - "../../../../move-stdlib/sources", - "../../../../move-stdlib/nursery/sources", + "../../../../move-examples/diem-framework/move-packages/DPN/sources", + "../../../../move-stdlib/sources", + "../../../../move-stdlib/nursery/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie_1.toml b/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie_1.toml index ea89bd85520..71575034c2f 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie_1.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie_1.toml @@ -1,13 +1,13 @@ move_named_address_values = [ - "std=0x1", - "DiemFramework=0x1", - "DiemRoot=0xA550C18", - "TreasuryCompliance=0xB1E55ED", - "CurrencyInfo=0xA550C18", - "VMReserved=0x0", + "std=0x1", + "DiemFramework=0x1", + "DiemRoot=0xA550C18", + "TreasuryCompliance=0xB1E55ED", + "CurrencyInfo=0xA550C18", + "VMReserved=0x0", ] move_deps = [ - "../../../../move-examples/diem-framework/move-packages/DPN/sources", - "../../../../move-stdlib/sources", - "../../../../move-stdlib/nursery/sources", + "../../../../move-examples/diem-framework/move-packages/DPN/sources", + "../../../../move-stdlib/sources", + "../../../../move-stdlib/nursery/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie_2.toml b/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie_2.toml index ea89bd85520..71575034c2f 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie_2.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie_2.toml @@ -1,13 +1,13 @@ move_named_address_values = [ - "std=0x1", - "DiemFramework=0x1", - "DiemRoot=0xA550C18", - "TreasuryCompliance=0xB1E55ED", - "CurrencyInfo=0xA550C18", - "VMReserved=0x0", + "std=0x1", + "DiemFramework=0x1", + "DiemRoot=0xA550C18", + "TreasuryCompliance=0xB1E55ED", + "CurrencyInfo=0xA550C18", + "VMReserved=0x0", ] move_deps = [ - "../../../../move-examples/diem-framework/move-packages/DPN/sources", - "../../../../move-stdlib/sources", - "../../../../move-stdlib/nursery/sources", + "../../../../move-examples/diem-framework/move-packages/DPN/sources", + "../../../../move-stdlib/sources", + "../../../../move-stdlib/nursery/sources", ] diff --git a/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie_3.toml b/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie_3.toml index ea89bd85520..71575034c2f 100644 --- a/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie_3.toml +++ b/third_party/move/move-prover/lab/data/new-boogie-diem-framework/new_boogie_3.toml @@ -1,13 +1,13 @@ move_named_address_values = [ - "std=0x1", - "DiemFramework=0x1", - "DiemRoot=0xA550C18", - "TreasuryCompliance=0xB1E55ED", - "CurrencyInfo=0xA550C18", - "VMReserved=0x0", + "std=0x1", + "DiemFramework=0x1", + "DiemRoot=0xA550C18", + "TreasuryCompliance=0xB1E55ED", + "CurrencyInfo=0xA550C18", + "VMReserved=0x0", ] move_deps = [ - "../../../../move-examples/diem-framework/move-packages/DPN/sources", - "../../../../move-stdlib/sources", - "../../../../move-stdlib/nursery/sources", + "../../../../move-examples/diem-framework/move-packages/DPN/sources", + "../../../../move-stdlib/sources", + "../../../../move-stdlib/nursery/sources", ] diff --git a/third_party/move/move-prover/lab/data/test/prover_stdlib.toml b/third_party/move/move-prover/lab/data/test/prover_stdlib.toml index 793c70611ff..5177472aa2d 100644 --- a/third_party/move/move-prover/lab/data/test/prover_stdlib.toml +++ b/third_party/move/move-prover/lab/data/test/prover_stdlib.toml @@ -1,5 +1,5 @@ move_named_address_values = ["std=0x1"] move_deps = [ - "../../../../move-stdlib/sources", - "../../../../move-stdlib/nursery/sources", + "../../../../move-stdlib/sources", + "../../../../move-stdlib/nursery/sources", ] diff --git a/third_party/move/move-vm/integration-tests/Cargo.toml b/third_party/move/move-vm/integration-tests/Cargo.toml index 2f9347c0dd2..0145bd356f9 100644 --- a/third_party/move/move-vm/integration-tests/Cargo.toml +++ b/third_party/move/move-vm/integration-tests/Cargo.toml @@ -17,7 +17,9 @@ claims = { workspace = true } codespan-reporting = { workspace = true } legacy-move-compiler = { workspace = true } memory-stats = { workspace = true } -move-binary-format = { workspace = true, features = ["testing"] } +move-binary-format = { workspace = true, features = [ + "testing", +] } move-bytecode-verifier = { workspace = true } move-compiler-v2 = { workspace = true } move-core-types = { workspace = true } diff --git a/third_party/move/move-vm/types/Cargo.toml b/third_party/move/move-vm/types/Cargo.toml index 6e3fc3c96f7..5e894a0f96f 100644 --- a/third_party/move/move-vm/types/Cargo.toml +++ b/third_party/move/move-vm/types/Cargo.toml @@ -32,7 +32,9 @@ triomphe = { workspace = true } [dev-dependencies] claims = { workspace = true } mockall = { workspace = true } -move-binary-format = { workspace = true, features = ["fuzzing"] } +move-binary-format = { workspace = true, features = [ + "fuzzing", +] } proptest = { workspace = true } rand = { workspace = true } diff --git a/third_party/move/testing-infra/transactional-test-runner/Cargo.toml b/third_party/move/testing-infra/transactional-test-runner/Cargo.toml index cb2c215d897..ac9c3e52521 100644 --- a/third_party/move/testing-infra/transactional-test-runner/Cargo.toml +++ b/third_party/move/testing-infra/transactional-test-runner/Cargo.toml @@ -16,7 +16,9 @@ clap = { workspace = true, features = ["derive"] } either = { workspace = true } legacy-move-compiler = { workspace = true } move-asm = { workspace = true } -move-binary-format = { workspace = true, features = ["testing"] } +move-binary-format = { workspace = true, features = [ + "testing", +] } move-bytecode-source-map = { workspace = true } move-bytecode-verifier = { workspace = true } move-command-line-common = { workspace = true } diff --git a/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename/Move.toml b/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename/Move.toml index a13ae9d9e4f..0a037bf8dfd 100644 --- a/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename/Move.toml +++ b/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename/Move.toml @@ -6,5 +6,5 @@ version = "0.0.0" A = "0x3" [dependencies] -C = { local = "./deps_only/C", addr_subst = {"CA" = "A" } } -D = { local = "./deps_only/D" , addr_subst = {"DA" = "A" } } +C = { local = "./deps_only/C", addr_subst = { "CA" = "A" } } +D = { local = "./deps_only/D", addr_subst = { "DA" = "A" } } diff --git a/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename_one/Move.toml b/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename_one/Move.toml index 423f3f880f1..70a39f3ee65 100644 --- a/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename_one/Move.toml +++ b/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename_one/Move.toml @@ -9,4 +9,4 @@ A = "0x1" [dependencies] C = { local = "./deps_only/C" } -D = { local = "./deps_only/D" , addr_subst = {"DA" = "A" } } +D = { local = "./deps_only/D", addr_subst = { "DA" = "A" } } diff --git a/third_party/move/tools/move-package/tests/test_sources/model/multiple_deps_rename/Move.toml b/third_party/move/tools/move-package/tests/test_sources/model/multiple_deps_rename/Move.toml index a13ae9d9e4f..0a037bf8dfd 100644 --- a/third_party/move/tools/move-package/tests/test_sources/model/multiple_deps_rename/Move.toml +++ b/third_party/move/tools/move-package/tests/test_sources/model/multiple_deps_rename/Move.toml @@ -6,5 +6,5 @@ version = "0.0.0" A = "0x3" [dependencies] -C = { local = "./deps_only/C", addr_subst = {"CA" = "A" } } -D = { local = "./deps_only/D" , addr_subst = {"DA" = "A" } } +C = { local = "./deps_only/C", addr_subst = { "CA" = "A" } } +D = { local = "./deps_only/D", addr_subst = { "DA" = "A" } } diff --git a/third_party/move/tools/move-package/tests/test_sources/parsing/no_path_set_for_dependency/Move.toml b/third_party/move/tools/move-package/tests/test_sources/parsing/no_path_set_for_dependency/Move.toml index dbd55273608..ff10e27d5d6 100644 --- a/third_party/move/tools/move-package/tests/test_sources/parsing/no_path_set_for_dependency/Move.toml +++ b/third_party/move/tools/move-package/tests/test_sources/parsing/no_path_set_for_dependency/Move.toml @@ -3,4 +3,4 @@ name = "name" version = "0.1.2" [dependencies] -A = { } +A = {} diff --git a/third_party/move/tools/move-package/tests/test_sources/parsing/non_identifier_address_name_in_subst/Move.toml b/third_party/move/tools/move-package/tests/test_sources/parsing/non_identifier_address_name_in_subst/Move.toml index 8b78acf0abc..bf549e92df8 100644 --- a/third_party/move/tools/move-package/tests/test_sources/parsing/non_identifier_address_name_in_subst/Move.toml +++ b/third_party/move/tools/move-package/tests/test_sources/parsing/non_identifier_address_name_in_subst/Move.toml @@ -3,4 +3,4 @@ name = "name" version = "0.1.2" [dependencies] -A = { local = "a", addr_subst = { "©" = "A" } } +A = { local = "a", addr_subst = { "©" = "A" } } diff --git a/third_party/move/tools/move-package/tests/test_sources/resolution/dep_good_digest/Move.toml b/third_party/move/tools/move-package/tests/test_sources/resolution/dep_good_digest/Move.toml index adfaac538f7..1cf7c5aea30 100644 --- a/third_party/move/tools/move-package/tests/test_sources/resolution/dep_good_digest/Move.toml +++ b/third_party/move/tools/move-package/tests/test_sources/resolution/dep_good_digest/Move.toml @@ -6,4 +6,4 @@ version = "0.0.0" A = "0x1" [dependencies] -OtherDep = { local = "./deps_only/other_dep", addr_subst = { "A" = "B" }, digest = "6A88B7888D6049EB0121900E22B6FA2C0E702F042C8C8D4FD62AD5C990B9F9A8"} +OtherDep = { local = "./deps_only/other_dep", addr_subst = { "A" = "B" }, digest = "6A88B7888D6049EB0121900E22B6FA2C0E702F042C8C8D4FD62AD5C990B9F9A8" } diff --git a/third_party/move/tools/move-package/tests/test_sources/resolution/multiple_deps_rename/Move.toml b/third_party/move/tools/move-package/tests/test_sources/resolution/multiple_deps_rename/Move.toml index 6bac3c7efc8..292d9a37375 100644 --- a/third_party/move/tools/move-package/tests/test_sources/resolution/multiple_deps_rename/Move.toml +++ b/third_party/move/tools/move-package/tests/test_sources/resolution/multiple_deps_rename/Move.toml @@ -3,5 +3,5 @@ name = "test" version = "0.0.0" [dependencies] -C = { local = "./deps_only/C", addr_subst = {"CA" = "A" } } -D = { local = "./deps_only/D" , addr_subst = {"DA" = "A" } } +C = { local = "./deps_only/C", addr_subst = { "CA" = "A" } } +D = { local = "./deps_only/D", addr_subst = { "DA" = "A" } } diff --git a/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_bad_digest/Move.toml b/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_bad_digest/Move.toml index bb8f33a3b75..7048f57b13f 100644 --- a/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_bad_digest/Move.toml +++ b/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_bad_digest/Move.toml @@ -6,4 +6,4 @@ version = "0.0.0" A = "0x1" [dependencies] -OtherDep = { local = "./deps_only/other_dep", addr_subst = { "A" = "B" }, digest = "BAD_DIGEST"} +OtherDep = { local = "./deps_only/other_dep", addr_subst = { "A" = "B" }, digest = "BAD_DIGEST" } diff --git a/third_party/move/tools/move-unit-test/Cargo.toml b/third_party/move/tools/move-unit-test/Cargo.toml index 88585e61d8a..fb46e74da23 100644 --- a/third_party/move/tools/move-unit-test/Cargo.toml +++ b/third_party/move/tools/move-unit-test/Cargo.toml @@ -53,7 +53,5 @@ name = "move_unit_test_testsuite" harness = false [features] -table-extension = [ - "move-vm-test-utils/table-extension" -] +table-extension = ["move-vm-test-utils/table-extension"] debugging = ["move-vm-runtime/debugging"] diff --git a/types/Cargo.toml b/types/Cargo.toml index c9bed803a29..d07d9cd6b00 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -31,6 +31,7 @@ base64 = { workspace = true } bcs = { workspace = true } bytes = { workspace = true } derive-getters = { workspace = true } +crypto = { workspace = true } chrono = { workspace = true } chrono-tz = { workspace = true } dashmap = { workspace = true } @@ -73,6 +74,11 @@ strum = { workspace = true } strum_macros = { workspace = true } thiserror = { workspace = true } tracing = { workspace = true } +utoipa = { features = [ + "non_strict_integers", + "preserve_order", + "uuid", +], optional = true, workspace = true } [dev-dependencies] ahash = { workspace = true } @@ -98,7 +104,14 @@ url = { workspace = true } [features] default = [] testing = ["aptos-crypto/fuzzing"] -fuzzing = ["proptest", "proptest-derive", "aptos-crypto/fuzzing", "move-core-types/fuzzing", "arbitrary"] +fuzzing = [ + "proptest", + "proptest-derive", + "aptos-crypto/fuzzing", + "move-core-types/fuzzing", + "arbitrary", +] +rest_api_schema = ["utoipa", "arbitrary"] [[bench]] name = "keyless" diff --git a/types/src/account_config/events/fungible_asset.rs b/types/src/account_config/events/fungible_asset.rs index 19eb9413703..72b4d541972 100644 --- a/types/src/account_config/events/fungible_asset.rs +++ b/types/src/account_config/events/fungible_asset.rs @@ -4,11 +4,11 @@ use crate::move_utils::move_event_v2::MoveEventV2Type; use derive_getters::Getters; use move_core_types::{ - account_address::AccountAddress, ident_str, identifier::IdentStr, move_resource::MoveStructType, - language_storage::TypeTag, + account_address::AccountAddress, ident_str, identifier::IdentStr, language_storage::TypeTag, + move_resource::MoveStructType, }; -use serde::{Deserialize, Serialize}; use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; /// Struct that represents a Withdraw event. #[derive(Debug, Serialize, Deserialize, Getters)] @@ -42,4 +42,4 @@ pub static FA_WITHDRAW_EVENT_TYPE_TAG: Lazy = Lazy::new(|| TypeTag::Struct(Box::new(WithdrawFAEvent::struct_tag()))); pub static FA_DEPOSIT_EVENT_TYPE_TAG: Lazy = - Lazy::new(|| TypeTag::Struct(Box::new(DepositFAEvent::struct_tag()))); \ No newline at end of file + Lazy::new(|| TypeTag::Struct(Box::new(DepositFAEvent::struct_tag()))); diff --git a/types/src/contract_event.rs b/types/src/contract_event.rs index 340cb7b95ab..62d82ec55e5 100644 --- a/types/src/contract_event.rs +++ b/types/src/contract_event.rs @@ -7,9 +7,13 @@ use crate::{ DepositEvent, NewBlockEvent, NewEpochEvent, WithdrawEvent, NEW_EPOCH_EVENT_MOVE_TYPE_TAG, NEW_EPOCH_EVENT_V2_MOVE_TYPE_TAG, }, - dkg::DKGStartEvent, + dkg::{ + events::{DKGFinishEvent, DKGMetaSetEvent, DKGStartEvent as SupraDKGStartEvent}, + DKGStartEvent, + }, event::EventKey, jwks::ObservedJWKsUpdated, + on_chain_config::new_epoch_event_key, transaction::Version, }; use anyhow::{bail, Error, Result}; @@ -161,6 +165,24 @@ impl ContractEvent { pub fn expect_new_block_event(&self) -> Result { NewBlockEvent::try_from_bytes(self.event_data()) } + + pub fn as_bytes_for_hash(&self) -> Vec { + let mut bytes = Vec::new(); + match self { + ContractEvent::V1(event) => { + bytes.extend_from_slice(&event.key().get_creation_number().to_le_bytes()); + bytes.extend_from_slice(event.key().get_creator_address().as_ref()); + bytes.extend_from_slice(&event.sequence_number().to_le_bytes()); + bytes.extend_from_slice(event.type_tag().to_canonical_string().as_bytes()); + bytes.extend_from_slice(event.event_data()); + }, + ContractEvent::V2(event) => { + bytes.extend_from_slice(event.type_tag().to_canonical_string().as_bytes()); + bytes.extend_from_slice(event.event_data()); + }, + } + bytes + } } #[cfg(any(test, feature = "testing"))] @@ -307,6 +329,48 @@ impl TryFrom<&ContractEvent> for NewBlockEvent { } } +impl TryFrom<(u64, NewEpochEvent)> for ContractEvent { + type Error = Error; + + fn try_from((seq_num, event): (u64, NewEpochEvent)) -> Result { + Self::new_v1( + new_epoch_event_key(), + seq_num, + TypeTag::from(NewEpochEvent::struct_tag()), + bcs::to_bytes(&event).unwrap(), + ) + } +} + +impl TryFrom<&ContractEvent> for SupraDKGStartEvent { + type Error = Error; + + fn try_from(event: &ContractEvent) -> Result { + match event { + ContractEvent::V1(_) => { + bail!("conversion to dkg start event failed with wrong contract event version"); + }, + ContractEvent::V2(event) => { + if event.type_tag != TypeTag::Struct(Box::new(Self::struct_tag())) { + bail!("conversion to dkg start event failed with wrong type tag") + } + bcs::from_bytes(&event.event_data).map_err(Into::into) + }, + } + } +} + +impl TryFrom for ContractEvent { + type Error = Error; + + fn try_from(event: SupraDKGStartEvent) -> Result { + Self::new_v2( + TypeTag::from(SupraDKGStartEvent::struct_tag()), + bcs::to_bytes(&event).unwrap(), + ) + } +} + impl TryFrom<&ContractEvent> for DKGStartEvent { type Error = Error; @@ -325,18 +389,75 @@ impl TryFrom<&ContractEvent> for DKGStartEvent { } } -impl TryFrom<&ContractEvent> for NewEpochEvent { +impl TryFrom for ContractEvent { + type Error = Error; + + fn try_from(event: DKGStartEvent) -> Result { + Self::new_v2( + TypeTag::from(DKGStartEvent::struct_tag()), + bcs::to_bytes(&event).unwrap(), + ) + } +} + +impl TryFrom<&ContractEvent> for DKGFinishEvent { + type Error = Error; + + fn try_from(event: &ContractEvent) -> Result { + match event { + ContractEvent::V1(_) => { + bail!("conversion to dkg finish event failed with wrong contract event version"); + }, + ContractEvent::V2(event) => { + if event.type_tag != TypeTag::Struct(Box::new(Self::struct_tag())) { + bail!("conversion to dkg finish event failed with wrong type tag") + } + bcs::from_bytes(&event.event_data).map_err(Into::into) + }, + } + } +} + +impl TryFrom for ContractEvent { + type Error = Error; + + fn try_from(event: DKGFinishEvent) -> Result { + Self::new_v2( + TypeTag::from(DKGFinishEvent::struct_tag()), + bcs::to_bytes(&event).unwrap(), + ) + } +} + +impl TryFrom<&ContractEvent> for DKGMetaSetEvent { type Error = Error; fn try_from(event: &ContractEvent) -> Result { - if event.is_new_epoch_event() { - Self::try_from_bytes(event.event_data()) - } else { - bail!("Expected NewEpochEvent") + match event { + ContractEvent::V1(_) => { + bail!("conversion to dkg meta set event failed with wrong contract event version"); + }, + ContractEvent::V2(event) => { + if event.type_tag != TypeTag::Struct(Box::new(Self::struct_tag())) { + bail!("conversion to dkg meta set event failed with wrong type tag") + } + bcs::from_bytes(&event.event_data).map_err(Into::into) + }, } } } +impl TryFrom for ContractEvent { + type Error = Error; + + fn try_from(event: DKGMetaSetEvent) -> Result { + Self::new_v2( + TypeTag::from(DKGMetaSetEvent::struct_tag()), + bcs::to_bytes(&event).unwrap(), + ) + } +} + impl TryFrom<&ContractEvent> for WithdrawEvent { type Error = Error; diff --git a/types/src/dkg/dkg_committee.rs b/types/src/dkg/dkg_committee.rs new file mode 100644 index 00000000000..c531cd35f82 --- /dev/null +++ b/types/src/dkg/dkg_committee.rs @@ -0,0 +1,55 @@ +use derive_getters::Getters; +use move_core_types::account_address::AccountAddress; +use serde::{Deserialize, Serialize}; + +/// Reflection of `0x1::dkg_committee::DkgNodeConfig` in rust. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Getters)] +pub struct DkgNodeConfig { + pool_address: AccountAddress, + identity: Vec, + dkg_pubkey: Vec, +} + +impl DkgNodeConfig { + pub fn new(pool_address: AccountAddress, identity: Vec, dkg_pubkey: Vec) -> Self { + Self { + pool_address, + identity, + dkg_pubkey, + } + } +} + +/// Reflection of `0x1::dkg_committee::DkgCommittee` in rust. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Getters)] +pub struct DkgCommittee { + committee: Vec, + threshold_type: u8, +} + +impl DkgCommittee { + pub fn new(committee: Vec, threshold_type: u8) -> Self { + Self { + committee, + threshold_type, + } + } +} + +/// Reflection of `0x1::dkg_committee::ReceiverCommittee` in rust. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Getters)] +pub struct ReceiverCommittee { + is_resharing: bool, + dkg_threshold_type: u8, + committee: DkgCommittee, +} + +impl ReceiverCommittee { + pub fn new(is_resharing: bool, dkg_threshold_type: u8, committee: DkgCommittee) -> Self { + Self { + is_resharing, + dkg_threshold_type, + committee, + } + } +} diff --git a/types/src/dkg/events.rs b/types/src/dkg/events.rs new file mode 100644 index 00000000000..c50cfba1556 --- /dev/null +++ b/types/src/dkg/events.rs @@ -0,0 +1,46 @@ +use crate::dkg::state::DKGSessionMetadata; +use move_core_types::{ + ident_str, identifier::IdentStr, language_storage::TypeTag, move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct DKGStartEvent { + pub session_metadata: DKGSessionMetadata, + pub start_time_us: u64, +} + +impl MoveStructType for DKGStartEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("supra_dkg"); + const STRUCT_NAME: &'static IdentStr = ident_str!("DKGStartEvent"); +} + +pub static DKG_START_EVENT_MOVE_TYPE_TAG: Lazy = + Lazy::new(|| TypeTag::Struct(Box::new(DKGStartEvent::struct_tag()))); + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct DKGMetaSetEvent { + pub dkg_meta_transcript: Vec, +} + +impl MoveStructType for DKGMetaSetEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("supra_dkg"); + const STRUCT_NAME: &'static IdentStr = ident_str!("DKGMetaSetEvent"); +} + +pub static DKG_META_SET_EVENT_MOVE_TYPE_TAG: Lazy = + Lazy::new(|| TypeTag::Struct(Box::new(DKGMetaSetEvent::struct_tag()))); + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct DKGFinishEvent { + pub target_committees_public_key_shares: Vec, +} + +impl MoveStructType for DKGFinishEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("supra_dkg"); + const STRUCT_NAME: &'static IdentStr = ident_str!("DKGFinishEvent"); +} + +pub static DKG_FINISH_EVENT_MOVE_TYPE_TAG: Lazy = + Lazy::new(|| TypeTag::Struct(Box::new(DKGFinishEvent::struct_tag()))); diff --git a/types/src/dkg/mod.rs b/types/src/dkg/mod.rs index 07723529e70..29351a16355 100644 --- a/types/src/dkg/mod.rs +++ b/types/src/dkg/mod.rs @@ -3,15 +3,20 @@ use self::real_dkg::RealDKG; use crate::{ - dkg::real_dkg::{rounding::DKGRoundingProfile, Transcripts}, + dkg::{ + dkg_committee::DkgCommittee, + real_dkg::{rounding::DKGRoundingProfile, Transcripts}, + }, on_chain_config::{OnChainConfig, OnChainRandomnessConfig, RandomnessConfigMoveStruct}, + validator_public_keys::ValidatorPublicKeys, validator_verifier::{ ValidatorConsensusInfo, ValidatorConsensusInfoMoveStruct, ValidatorVerifier, }, }; -use anyhow::{Context, Result}; -use aptos_crypto::Uniform; +use anyhow::{anyhow, Context, Result}; +use aptos_crypto::{bls12381::PublicKey, Uniform}; use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; +use crypto::utils::get_clan_node_indices; use move_core_types::{ account_address::AccountAddress, ident_str, identifier::IdentStr, language_storage::TypeTag, move_resource::MoveStructType, @@ -25,6 +30,16 @@ use std::{ time::Duration, }; +pub mod dummy_dkg; +pub mod real_dkg; + +pub type DefaultDKG = RealDKG; + +pub mod dkg_committee; +pub mod events; +pub mod state; +pub mod transactions; + #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, CryptoHasher, BCSCryptoHash)] pub struct DKGTranscriptMetadata { pub epoch: u64, @@ -174,7 +189,6 @@ pub trait MayHaveRoundingSummary { fn rounding_summary(&self) -> Option<&RoundingSummary>; } -/// NOTE: this is a subset of the full scheme. Some data items/algorithms are not used in DKG and are omitted. pub trait DKGTrait: Debug { type DealerPrivateKey; type PublicParams: Clone + Debug + Send + Sync + MayHaveRoundingSummary; @@ -229,7 +243,48 @@ pub trait DKGTrait: Debug { fn get_dealers(transcript: &Self::Transcript) -> BTreeSet; } -pub mod dummy_dkg; -pub mod real_dkg; +/// The threshold required to ensure the presence of honest majority in clan where +/// N = 2f+1 with f byzantine nodes +fn clan_threshold(total: u64) -> u64 { + total / 2 + 1 +} -pub type DefaultDKG = RealDKG; +pub fn get_clan_nodes_bls_keys_from_indices( + dealer_committee: &DkgCommittee, + signers: &Vec, + random_seed: &Vec, +) -> Result> { + let committee = dealer_committee.committee(); + let dealer_clan_committee_indices = + get_clan_node_indices(committee.len() as u32, random_seed.clone()); + + let mut clan_committee_bls_keys = Vec::new(); + if let Some(clan_committee_indices) = dealer_clan_committee_indices { + let clan_threshold = clan_threshold(clan_committee_indices.len() as u64); + + if signers.len() as u64 != clan_threshold { + return Err(anyhow!("dkg::number of signers must match clan_threshold")); + } + + for signer in signers { + let clan_node_index = clan_committee_indices + .get(*signer as usize) + .ok_or(anyhow!("dkg::node Invalid signer index: {signer}"))?; + let clan_node_key = committee + .get(*clan_node_index) + .ok_or(anyhow!("dkg::node Invalid clan node index: {signer}"))? + .dkg_pubkey(); + let clan_node_pk = ValidatorPublicKeys::try_from(clan_node_key).map_err(|e| { + anyhow!("dkg::node validator public key deserialization failed: {e}") + })?; + let clan_node_bls_pubkey_bytes = clan_node_pk.supra_keys().bls_multisig_key(); + let clan_node_bls_pubkey = + PublicKey::try_from(clan_node_bls_pubkey_bytes.as_slice()) + .map_err(|e| anyhow!("dkg::node bls public key deserialization failed: {e}"))?; + clan_committee_bls_keys.push(clan_node_bls_pubkey); + } + Ok(clan_committee_bls_keys) + } else { + Err(anyhow!("dkg::cannot derive clan committee")) + } +} diff --git a/types/src/dkg/state.rs b/types/src/dkg/state.rs new file mode 100644 index 00000000000..73db51eea76 --- /dev/null +++ b/types/src/dkg/state.rs @@ -0,0 +1,70 @@ +use crate::{ + dkg::dkg_committee::{DkgCommittee, ReceiverCommittee}, + on_chain_config::OnChainConfig, +}; +use serde::{Deserialize, Serialize}; + +// Reflection of `0x1::supra_dkg::DKGSessionMetadata` in rust. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct DKGSessionMetadata { + pub dealer_epoch: u64, + pub randomness_seed: Vec, + pub dealer_committee: DkgCommittee, + pub target_committees: Vec, +} + +impl DKGSessionMetadata { + pub fn target_committee_cloned(&self) -> Vec { + self.target_committees.clone() + } + + pub fn dealer_committee_cloned(&self) -> DkgCommittee { + self.dealer_committee.clone() + } +} + +/// Reflection of Move type `0x1::supra_dkg::DKGSessionState`. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct DKGSessionState { + pub metadata: DKGSessionMetadata, + pub start_time_us: u64, + pub dkg_meta_transcript: Vec, + pub target_committees_public_key_shares: Vec, +} + +impl DKGSessionState { + pub fn target_epoch(&self) -> u64 { + self.metadata.dealer_epoch + 1 + } +} +/// Reflection of Move type `0x1::supra_dkg::DKGState`. +#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] +pub struct DKGState { + pub last_completed: Option, + pub in_progress: Option, +} + +impl DKGState { + pub fn maybe_last_complete(&self, epoch: u64) -> Option<&DKGSessionState> { + match &self.last_completed { + Some(session) if session.target_epoch() == epoch => Some(session), + _ => None, + } + } + + pub fn maybe_in_progress(&self, epoch: u64) -> Option<&DKGSessionState> { + match &self.in_progress { + Some(session) if session.target_epoch() == epoch => Some(session), + _ => None, + } + } + + pub fn last_complete(&self) -> &DKGSessionState { + self.last_completed.as_ref().unwrap() + } +} + +impl OnChainConfig for DKGState { + const MODULE_IDENTIFIER: &'static str = "supra_dkg"; + const TYPE_IDENTIFIER: &'static str = "DKGState"; +} diff --git a/types/src/dkg/transactions.rs b/types/src/dkg/transactions.rs new file mode 100644 index 00000000000..dd1054520f1 --- /dev/null +++ b/types/src/dkg/transactions.rs @@ -0,0 +1,77 @@ +use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; +use derive_getters::Getters; +use move_core_types::account_address::AccountAddress; +use serde::{Deserialize, Serialize}; +use std::fmt::{Debug, Formatter}; + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] +pub enum DKGTransactionType { + DKGMeta, + PublicKeyShares, +} + +#[derive( + Clone, Serialize, Deserialize, Debug, PartialEq, Eq, CryptoHasher, BCSCryptoHash, Getters, +)] +pub struct DKGTransactionMetadata { + epoch: u64, + author: AccountAddress, + bls_aggregate_signature: Vec, + signer_indices_clan_committee: Vec, + transaction_type: DKGTransactionType, +} + +/// DKG transcript and its metadata. +#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Getters)] +pub struct DKGTransactionData { + metadata: DKGTransactionMetadata, + #[serde(with = "serde_bytes")] + data_bytes: Vec, +} + +impl Debug for DKGTransactionData { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("DKGTransactionData") + .field("metadata", &self.metadata) + .field("data_bytes_len", &self.data_bytes.len()) + .finish() + } +} + +impl DKGTransactionData { + pub fn new( + epoch: u64, + author: AccountAddress, + transcript_bytes: Vec, + bls_aggregate_signature: Vec, + signer_indices_clan_committee: Vec, + transaction_type: DKGTransactionType, + ) -> Self { + Self { + metadata: DKGTransactionMetadata { + epoch, + author, + bls_aggregate_signature, + signer_indices_clan_committee, + transaction_type, + }, + data_bytes: transcript_bytes, + } + } +} + +#[cfg(test)] +impl DKGTransactionData { + pub fn dummy() -> Self { + Self { + metadata: DKGTransactionMetadata { + epoch: 0, + author: AccountAddress::ZERO, + bls_aggregate_signature: vec![], + signer_indices_clan_committee: vec![], + transaction_type: DKGTransactionType::DKGMeta, + }, + data_bytes: vec![], + } + } +} diff --git a/types/src/lib.rs b/types/src/lib.rs index cc7f4b40b43..ca6cebcb731 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -50,6 +50,7 @@ pub mod utility_coin; pub mod validator_config; pub mod validator_info; pub mod validator_performances; +pub mod validator_public_keys; pub mod validator_signer; pub mod validator_txn; pub mod validator_verifier; diff --git a/types/src/on_chain_config/aptos_features.rs b/types/src/on_chain_config/aptos_features.rs index 8194b3661f5..9a7dabcb623 100644 --- a/types/src/on_chain_config/aptos_features.rs +++ b/types/src/on_chain_config/aptos_features.rs @@ -142,23 +142,32 @@ pub enum FeatureFlag { SUPRA_RLP_ENCODE = 94, SUPRA_DELEGATION_POOL_IDENTITY = 95, SUPRA_AUTOMATION_V2 = 96, - - - DERIVABLE_ACCOUNT_ABSTRACTION = 97, + /// This flag should only be enabled after all Validators have updated their keys to the new format, including the BLS keys. + SUPRA_BLS_KEYS = 97, + SUPRA_BCFT_CERTIFICATES = 98, + /// `SUPRA_BLS_KEYS` must be enabled first, as the new validator identity format is a prerequisite for the DKG. + /// The default DKG configuration also requires `SUPRA_BCFT_CERTIFICATES` to be enabled first. + SUPRA_DKG = 99, + SUPRA_TRANSACTIONS_INCLUSION_PROOFS = 100, + /// Enables smart contracts to register automation tasks via `register_without_validation`, + SUPRA_AUTOMATION_V2_1 = 101, + + DERIVABLE_ACCOUNT_ABSTRACTION = 102, /// Whether function values are enabled. - ENABLE_FUNCTION_VALUES = 98, - NEW_ACCOUNTS_DEFAULT_TO_FA_STORE = 99, - DEFAULT_ACCOUNT_RESOURCE = 100, - JWK_CONSENSUS_PER_KEY_MODE = 101, - TRANSACTION_PAYLOAD_V2 = 102, - ORDERLESS_TRANSACTIONS = 103, + ENABLE_FUNCTION_VALUES = 103, + NEW_ACCOUNTS_DEFAULT_TO_FA_STORE = 104, + DEFAULT_ACCOUNT_RESOURCE = 105, + JWK_CONSENSUS_PER_KEY_MODE = 106, + TRANSACTION_PAYLOAD_V2 = 107, + ORDERLESS_TRANSACTIONS = 108, // TODO(lazy-loading): Add link to AIP and its number + brief description. - ENABLE_LAZY_LOADING = 104, + ENABLE_LAZY_LOADING = 109, - CALCULATE_TRANSACTION_FEE_FOR_DISTRIBUTION = 105, - DISTRIBUTE_TRANSACTION_FEE = 106, + CALCULATE_TRANSACTION_FEE_FOR_DISTRIBUTION = 110, + DISTRIBUTE_TRANSACTION_FEE = 111, } +//TODO: add dkg feature impl FeatureFlag { pub fn default_features() -> Vec { vec![ @@ -169,7 +178,7 @@ impl FeatureFlag { // Feature flag V6 is used to enable metadata v1 format and needs to stay on, even // if we enable a higher version. FeatureFlag::VM_BINARY_FORMAT_V6, - FeatureFlag::VM_BINARY_FORMAT_V7, // new + FeatureFlag::VM_BINARY_FORMAT_V7, // new FeatureFlag::MULTI_ED25519_PK_VALIDATE_V2_NATIVES, FeatureFlag::BLAKE2B_256_NATIVE, FeatureFlag::RESOURCE_GROUPS, @@ -226,7 +235,7 @@ impl FeatureFlag { FeatureFlag::DISPATCHABLE_FUNGIBLE_ASSET, FeatureFlag::_DEPRECATED_REMOVE_DETAILED_ERROR_FROM_HASH, // FeatureFlag::NEW_ACCOUNTS_DEFAULT_TO_FA_APT_STORE, // new - // FeatureFlag::OPERATIONS_DEFAULT_TO_FA_APT_STORE, // new + // FeatureFlag::OPERATIONS_DEFAULT_TO_FA_APT_STORE, // new FeatureFlag::CONCURRENT_FUNGIBLE_ASSETS, FeatureFlag::AGGREGATOR_V2_IS_AT_LEAST_API, FeatureFlag::CONCURRENT_FUNGIBLE_BALANCE, @@ -263,6 +272,11 @@ impl FeatureFlag { FeatureFlag::SUPRA_COUNT_FAILED_PROPOSALS, FeatureFlag::SUPRA_DELEGATION_POOL_IDENTITY, FeatureFlag::SUPRA_AUTOMATION_V2, + FeatureFlag::SUPRA_BLS_KEYS, + FeatureFlag::SUPRA_BCFT_CERTIFICATES, + FeatureFlag::SUPRA_DKG, + FeatureFlag::SUPRA_TRANSACTIONS_INCLUSION_PROOFS, + FeatureFlag::SUPRA_AUTOMATION_V2_1, ] } } @@ -466,6 +480,10 @@ impl Features { file_format_common::VERSION_5 } } + + pub fn is_supra_automation_v2_1_enabled(&self) -> bool { + self.is_enabled(FeatureFlag::SUPRA_AUTOMATION_V2_1) + } } pub fn aptos_test_feature_flags_genesis() -> ChangeSet { diff --git a/types/src/on_chain_config/automation_registry.rs b/types/src/on_chain_config/automation_registry.rs index 95779e36300..e910f61baad 100644 --- a/types/src/on_chain_config/automation_registry.rs +++ b/types/src/on_chain_config/automation_registry.rs @@ -4,9 +4,13 @@ use crate::on_chain_config::OnChainConfig; use derive_getters::Getters; use derive_more::Constructor; -use move_core_types::account_address::AccountAddress; -use move_core_types::value::{serialize_values, MoveValue}; -use move_core_types::{ident_str, identifier::IdentStr, move_resource::MoveStructType}; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + move_resource::MoveStructType, + value::{serialize_values, MoveValue}, +}; use serde::{Deserialize, Serialize}; const ONE_MONTH_IN_SECS: u64 = 2_626_560; diff --git a/types/src/on_chain_config/evm_config.rs b/types/src/on_chain_config/evm_config.rs new file mode 100644 index 00000000000..fb7f87d8bc7 --- /dev/null +++ b/types/src/on_chain_config/evm_config.rs @@ -0,0 +1,560 @@ +// Copyright (c) 2026 Supra. +// SPDX-License-Identifier: Apache-2.0 + +use crate::on_chain_config::OnChainConfig; +use move_core_types::{account_address::AccountAddress, value::MoveValue}; +use serde::{Deserialize, Serialize}; +use std::{ + collections::BTreeMap, + fmt::{Display, Formatter}, + str::FromStr, +}; + +// -- EvmContractName ----------------------------------------------------------- + +/// Evm Contract Names deployed by Supra at genesis or later to be part of Supra EVM main state. +/// Currently only system targeted contracts have dedicated enum variants, the rest will be stored +/// as instance of [Self::Custom] variant. +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, Hash, PartialOrd, Ord)] +pub enum EvmContractName { + BlockMetadata, + AutomationRegistry, + Custom(String), +} + +impl FromStr for EvmContractName { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + match s { + "BlockMetadata" => Ok(EvmContractName::BlockMetadata), + "AutomationRegistry" => Ok(EvmContractName::AutomationRegistry), + n => Ok(EvmContractName::Custom(n.to_string())), + } + } +} + +impl Display for EvmContractName { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + EvmContractName::BlockMetadata => write!(f, "BlockMetadata"), + EvmContractName::AutomationRegistry => write!(f, "AutomationRegistry"), + EvmContractName::Custom(n) => write!(f, "{n}"), + } + } +} + +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] +pub(crate) struct EvmContractsDetails { + details: Vec<(String, AccountAddress)>, +} + +pub const EVM_ADDRESS_LENGTH: usize = 20; +pub type RawEvmAddress = [u8; EVM_ADDRESS_LENGTH]; + +/// Converts EVM(20bytes) Address to Move Address(32bytes) by left-padding it with 12 zero bytes. +pub fn evm_address_as_account_address(evm_address: &RawEvmAddress) -> AccountAddress { + // A Move `address` is 32 bytes serialised by BCS in big-endian order + // (most-significant byte at index 0). An EVM address is only 20 bytes, + // so we zero-pad the leading 12 bytes and place the EVM bytes at the + // tail (indices 12-31). This matches the invariant enforced by + // `is_valid_evm_address` in evm_config.move, which asserts that + // indices 0-11 are all zero. + let mut padded = [0u8; AccountAddress::LENGTH]; + padded[AccountAddress::LENGTH - EVM_ADDRESS_LENGTH..].copy_from_slice(evm_address); + AccountAddress::from(padded) +} + +/// The Genesis configuration for EVM that can only be set once at genesis epoch. +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] +pub struct OnChainEvmContractsDetails { + pub name_to_addresses: BTreeMap, +} + +impl OnChainEvmContractsDetails { + /// Converts keys and values to [`MoveValue`] and returns as tuple. + pub fn to_move_values(self) -> (MoveValue, MoveValue) { + let (keys, values): (Vec<_>, Vec<_>) = self + .name_to_addresses + .into_iter() + .map(|(key, value)| { + ( + MoveValue::vector_u8(key.to_string().into_bytes()), + evm_address_as_account_address(&value), + ) + }) + .unzip(); + (MoveValue::Vector(keys), MoveValue::vector_address(values)) + } + + pub fn get(&self, contract_name: EvmContractName) -> Option<&RawEvmAddress> { + self.name_to_addresses.get(&contract_name) + } + + pub fn has_all_keys(&self, keys: &[EvmContractName]) -> bool { + keys.into_iter() + .all(|key| self.name_to_addresses.contains_key(key)) + } +} + +impl OnChainConfig for OnChainEvmContractsDetails { + const MODULE_IDENTIFIER: &'static str = "evm_config"; + const TYPE_IDENTIFIER: &'static str = "EvmContractsDetails"; + + fn deserialize_into_config(bytes: &[u8]) -> anyhow::Result { + let raw_details = bcs::from_bytes::(bytes)?; + let details = raw_details + .details + .into_iter() + .filter_map(|(key, value)| { + let name = EvmContractName::from_str(&key).ok()?; + // BCS serialises a Move `address` as a raw 32-byte big-endian + // array. `to_move_values` places the 20-byte EVM address in the + // tail (indices 12-31) with the leading 12 bytes zeroed, so we + // must read from the back to recover the original EVM address. + let evm_address: RawEvmAddress = value.into_bytes() + [AccountAddress::LENGTH - EVM_ADDRESS_LENGTH..] + .try_into() + .ok()?; + Some((name, evm_address)) + }) + .collect::>(); + Ok(Self { + name_to_addresses: details, + }) + } +} + +// -- EvmScalarConfigKey -------------------------------------------------------- + +/// Typed keys for entries stored in the on-chain `EvmScalarConfig` resource. +/// Only keys whose string representation is known at compile time are listed +/// here; unknown keys are silently skipped during deserialization so that an +/// older node binary can still read a config that was extended with new keys. +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, Hash, PartialOrd, Ord)] +pub enum EvmScalarConfigKey { + EvmGasNormalizationDenom, + EvmGasEstimateMargin, + EvmGasUsedRatio, + EvmGasUsedRatioDecimalPrecision, +} + +impl EvmScalarConfigKey { + /// The set of keys that MUST be present in the on-chain config. + /// Deserialization hard-fails if any of these is missing. + pub fn required_keys() -> &'static [EvmScalarConfigKey] { + &[ + EvmScalarConfigKey::EvmGasNormalizationDenom, + EvmScalarConfigKey::EvmGasEstimateMargin, + EvmScalarConfigKey::EvmGasUsedRatio, + EvmScalarConfigKey::EvmGasUsedRatioDecimalPrecision, + ] + } +} + +impl FromStr for EvmScalarConfigKey { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + match s { + "evm_gas_normalization_denom" => Ok(EvmScalarConfigKey::EvmGasNormalizationDenom), + "evm_gas_estimate_margin" => Ok(EvmScalarConfigKey::EvmGasEstimateMargin), + "evm_gas_used_ratio" => Ok(EvmScalarConfigKey::EvmGasUsedRatio), + "evm_gas_used_ratio_decimal_precision" => { + Ok(EvmScalarConfigKey::EvmGasUsedRatioDecimalPrecision) + }, + _ => Err(anyhow::anyhow!("unknown evm scalar config key: {}", s)), + } + } +} + +impl Display for EvmScalarConfigKey { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + // Mirror FromStr: Display produces the canonical snake_case string that + // operators see in logs and error messages. + match self { + EvmScalarConfigKey::EvmGasNormalizationDenom => { + write!(f, "evm_gas_normalization_denom") + }, + EvmScalarConfigKey::EvmGasEstimateMargin => { + write!(f, "evm_gas_estimate_margin") + }, + EvmScalarConfigKey::EvmGasUsedRatio => { + write!(f, "evm_gas_used_ratio") + }, + EvmScalarConfigKey::EvmGasUsedRatioDecimalPrecision => { + write!(f, "evm_gas_used_ratio_decimal_precision") + }, + } + } +} + +// -- Internal BCS mirror struct ------------------------------------------------ + +/// BCS mirror of the on-chain `EvmScalarConfig` resource. +/// `SimpleMap` serializes as `Vec<(K, V)>` in BCS. +/// All config values are plain u128 scalars; the Move type system enforces +/// type correctness at compile time. +#[derive(Deserialize, Serialize)] +struct RawEvmScalarConfig { + config: Vec<(String, u128)>, +} + +// -- OnChainEvmConfig ---------------------------------------------------------- + +/// The decoded, type-safe representation of the on-chain `EvmScalarConfig` resource. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct OnChainEvmConfig { + pub config: BTreeMap, +} + +impl OnChainEvmConfig { + /// Convenience accessor for the EVM gas normalisation denominator. + pub fn evm_gas_normalization_denom(&self) -> anyhow::Result { + self.config + .get(&EvmScalarConfigKey::EvmGasNormalizationDenom) + .copied() + .ok_or_else(|| { + anyhow::anyhow!("evm_gas_normalization_denom not found in EvmScalarConfig") + }) + } + + pub fn evm_gas_estimate_margin(&self) -> anyhow::Result { + self.config + .get(&EvmScalarConfigKey::EvmGasEstimateMargin) + .copied() + .and_then(|v| v.try_into().ok()) + .ok_or_else(|| anyhow::anyhow!("evm_gas_estimate_margin not found in EvmScalarConfig")) + } + + pub fn evm_gas_used_ratio(&self) -> anyhow::Result { + // Decimal is guaranteed to be non-zero due to validation in evm_config.move, so this division is safe. + let decimal = self.evm_gas_used_ratio_decimal_precision()?; + self.config + .get(&EvmScalarConfigKey::EvmGasUsedRatio) + .copied() + .and_then(|v| { + let ratio = v as f64 / decimal as f64; + if ratio > 0.0 { + Some(ratio) + } else { + None + } + }) + .ok_or_else(|| anyhow::anyhow!("evm_gas_used_ratio not found in EvmScalarConfig")) + } + + pub fn evm_gas_used_ratio_decimal_precision(&self) -> anyhow::Result { + self.config + .get(&EvmScalarConfigKey::EvmGasUsedRatioDecimalPrecision) + .copied() + .and_then(|v| v.try_into().ok()) + .ok_or_else(|| { + anyhow::anyhow!("evm_gas_used_ratio_decimal_precision not found in EvmScalarConfig") + }) + } + + pub fn to_move_values(self) -> (MoveValue, MoveValue) { + let (keys, values): (Vec<_>, Vec<_>) = self + .config + .into_iter() + .map(|(key, value)| { + ( + MoveValue::vector_u8(key.to_string().into_bytes()), + MoveValue::U128(value), + ) + }) + .unzip(); + (MoveValue::Vector(keys), MoveValue::Vector(values)) + } +} + +impl OnChainConfig for OnChainEvmConfig { + const MODULE_IDENTIFIER: &'static str = "evm_config"; + const TYPE_IDENTIFIER: &'static str = "EvmScalarConfig"; + + fn deserialize_into_config(bytes: &[u8]) -> anyhow::Result { + let raw: RawEvmScalarConfig = bcs::from_bytes(bytes) + .map_err(|e| anyhow::anyhow!("failed to BCS-decode RawEvmScalarConfig: {}", e))?; + + let mut config = BTreeMap::new(); + for (key_str, value) in raw.config { + // Skip keys that are not (yet) known to this codebase; this allows + // the on-chain config to grow new entries without breaking older nodes. + let key = match EvmScalarConfigKey::from_str(&key_str) { + Ok(k) => k, + Err(_) => continue, + }; + config.insert(key, value); + } + + // Hard-fail if any required key is absent - the node cannot operate + // correctly without the full set of mandatory config values. + for required_key in EvmScalarConfigKey::required_keys() { + if !config.contains_key(required_key) { + return Err(anyhow::anyhow!( + "required EvmScalarConfig key '{}' is missing from on-chain state", + required_key // Display -> "evm_gas_normalization_denom" + )); + } + } + + Ok(Self { config }) + } +} + +#[cfg(test)] +mod unit_tests { + use super::*; + use crate::on_chain_config::{InMemoryOnChainConfig, OnChainConfig, OnChainConfigProvider}; + use std::collections::HashMap; + + // -- Helpers --------------------------------------------------------------- + + /// Returns a `RawEvmScalarConfig` with all four required keys populated. + /// Use this as the baseline for any test that needs a fully valid config. + fn raw_evm_scalar_config_all_keys( + denom: u128, + margin: u128, + gas_used_ratio: u128, + decimal_precision: u128, + ) -> RawEvmScalarConfig { + RawEvmScalarConfig { + config: vec![ + ("evm_gas_normalization_denom".to_string(), denom), + ("evm_gas_estimate_margin".to_string(), margin), + ("evm_gas_used_ratio".to_string(), gas_used_ratio), + ( + "evm_gas_used_ratio_decimal_precision".to_string(), + decimal_precision, + ), + ], + } + } + + /// Convenience wrapper with fixed margin/ratio/precision for tests that + /// only care about the denom value. + fn raw_evm_scalar_config_with_denom(denom: u128) -> RawEvmScalarConfig { + raw_evm_scalar_config_all_keys(denom, 500, 750, 1000) + } + + // -- OnChainEvmConfig deserialization -------------------------------------- + + #[test] + fn test_deserialize_evm_config_happy_path() { + let bytes = bcs::to_bytes(&raw_evm_scalar_config_with_denom(100)).unwrap(); + let config = OnChainEvmConfig::deserialize_into_config(&bytes).unwrap(); + assert_eq!(config.evm_gas_normalization_denom().unwrap(), 100u128); + // All four required keys must be decoded - no phantom entries. + assert_eq!(config.config.len(), 4); + } + + #[test] + fn test_deserialize_evm_config_missing_required_key() { + // Empty config - all required keys absent; the first one iterated + // (evm_gas_normalization_denom) must appear in the error. + let raw = RawEvmScalarConfig { config: vec![] }; + let bytes = bcs::to_bytes(&raw).unwrap(); + let result = OnChainEvmConfig::deserialize_into_config(&bytes); + assert!(result.is_err(), "expected Err when required key is missing"); + assert!( + result + .unwrap_err() + .to_string() + .contains("evm_gas_normalization_denom"), + "error should identify the missing key" + ); + } + + #[test] + fn test_deserialize_evm_config_each_required_key_missing() { + // Every required key must be individually enforced: removing any single + // one must hard-fail with an error message that names that key. + let required = [ + "evm_gas_normalization_denom", + "evm_gas_estimate_margin", + "evm_gas_used_ratio", + "evm_gas_used_ratio_decimal_precision", + ]; + let full = raw_evm_scalar_config_all_keys(100, 500, 750, 1000); + for missing_key in &required { + let partial = RawEvmScalarConfig { + config: full + .config + .iter() + .filter(|(k, _)| k != missing_key) + .cloned() + .collect(), + }; + let bytes = bcs::to_bytes(&partial).unwrap(); + let result = OnChainEvmConfig::deserialize_into_config(&bytes); + assert!( + result.is_err(), + "expected Err when '{}' is absent", + missing_key + ); + assert!( + result.unwrap_err().to_string().contains(missing_key), + "error must name the missing key '{}'", + missing_key + ); + } + } + + #[test] + fn test_deserialize_evm_config_unknown_key_skipped() { + // Unknown keys must be silently dropped so an older node binary can still + // read a config that was extended with new keys by a newer software version. + let mut raw = raw_evm_scalar_config_all_keys(42, 500, 750, 1000); + raw.config + .push(("completely_unknown_key".to_string(), 7u128)); + let bytes = bcs::to_bytes(&raw).unwrap(); + let config = OnChainEvmConfig::deserialize_into_config(&bytes).unwrap(); + assert_eq!(config.evm_gas_normalization_denom().unwrap(), 42u128); + // Only the four known keys should appear; the unknown one is dropped. + assert_eq!(config.config.len(), 4); + } + + // -- Accessor correctness -------------------------------------------------- + + #[test] + fn test_accessor_evm_gas_estimate_margin() { + let bytes = bcs::to_bytes(&raw_evm_scalar_config_all_keys(100, 1234, 750, 1000)).unwrap(); + let config = OnChainEvmConfig::deserialize_into_config(&bytes).unwrap(); + assert_eq!(config.evm_gas_estimate_margin().unwrap(), 1234u64); + } + + #[test] + fn test_accessor_evm_gas_used_ratio_decimal_precision() { + let bytes = bcs::to_bytes(&raw_evm_scalar_config_all_keys(100, 500, 750, 2000)).unwrap(); + let config = OnChainEvmConfig::deserialize_into_config(&bytes).unwrap(); + assert_eq!( + config.evm_gas_used_ratio_decimal_precision().unwrap(), + 2000u64 + ); + } + + #[test] + fn test_accessor_evm_gas_used_ratio() { + // ratio=750, decimal_precision=1000 -> 750 / 1000 = 0.75 + let bytes = bcs::to_bytes(&raw_evm_scalar_config_all_keys(100, 500, 750, 1000)).unwrap(); + let config = OnChainEvmConfig::deserialize_into_config(&bytes).unwrap(); + let ratio = config.evm_gas_used_ratio().unwrap(); + assert!( + (ratio - 0.75f64).abs() < f64::EPSILON, + "expected 0.75, got {}", + ratio + ); + } + + // -- to_move_values -------------------------------------------------------- + + #[test] + fn test_to_move_values_structure() { + // to_move_values must produce two parallel MoveValue::Vector outputs: + // keys as vector (UTF-8 strings) and values as u128. + let config = OnChainEvmConfig { + config: [ + (EvmScalarConfigKey::EvmGasNormalizationDenom, 42u128), + (EvmScalarConfigKey::EvmGasEstimateMargin, 500u128), + (EvmScalarConfigKey::EvmGasUsedRatio, 750u128), + ( + EvmScalarConfigKey::EvmGasUsedRatioDecimalPrecision, + 1000u128, + ), + ] + .into(), + }; + let (keys_mv, values_mv) = config.to_move_values(); + let MoveValue::Vector(keys) = keys_mv else { + panic!("expected MoveValue::Vector for keys") + }; + let MoveValue::Vector(values) = values_mv else { + panic!("expected MoveValue::Vector for values") + }; + assert_eq!(keys.len(), 4); + assert_eq!(values.len(), 4); + // Keys are encoded as vector (UTF-8 bytes). + assert!(matches!(keys[0], MoveValue::Vector(_))); + // Values are u128. + assert!(matches!(values[0], MoveValue::U128(_))); + } + + // -- OnChainEvmContractsDetails round-trip --------------------------------- + + #[test] + fn test_evm_contracts_details_round_trip() { + // 20-byte EVM address placed in the lower 20 bytes of a 32-byte Move + // address (upper 12 zeroed), matching the to_move_values encoding. + let evm_bytes: RawEvmAddress = [ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, + 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, + ]; + let original = OnChainEvmContractsDetails { + name_to_addresses: [(EvmContractName::BlockMetadata, evm_bytes)].into(), + }; + let mut padded = [0u8; AccountAddress::LENGTH]; + padded[AccountAddress::LENGTH - EVM_ADDRESS_LENGTH..].copy_from_slice(&evm_bytes); + let raw = EvmContractsDetails { + details: vec![("BlockMetadata".to_string(), AccountAddress::from(padded))], + }; + let bytes = bcs::to_bytes(&raw).unwrap(); + let recovered = OnChainEvmContractsDetails::deserialize_into_config(&bytes).unwrap(); + assert_eq!(recovered, original); + + let (_keys, addresses) = original.to_move_values(); + match addresses { + MoveValue::Vector(addrs) => { + assert_eq!(addrs.len(), 1); + match &addrs[0] { + MoveValue::Address(addr) => { + let recovered_evm_bytes: RawEvmAddress = addr.into_bytes() + [AccountAddress::LENGTH - EVM_ADDRESS_LENGTH..] + .try_into() + .expect("slice with correct length"); + assert_eq!(recovered_evm_bytes, evm_bytes); + }, + _ => panic!("expected MoveValue::Address in values vector"), + } + }, + _ => panic!("expected MoveValue::Vector"), + } + } + + // -- Tier 2: InMemoryOnChainConfig provider -------------------------------- + + #[test] + fn test_fetch_evm_config_via_provider() { + // Validates the full path: raw BCS bytes -> ConfigID lookup -> + // deserialize_into_config -> typed accessor, without a running VM. + let bytes = bcs::to_bytes(&raw_evm_scalar_config_with_denom(999)).unwrap(); + let mut map = HashMap::new(); + map.insert(OnChainEvmConfig::CONFIG_ID, bytes); + let provider = InMemoryOnChainConfig::new(map); + let config = provider.get::().unwrap(); + assert_eq!(config.evm_gas_normalization_denom().unwrap(), 999u128); + } + + #[test] + fn test_fetch_evm_contracts_details_via_provider() { + // Same end-to-end path for OnChainEvmContractsDetails. + let evm_bytes: RawEvmAddress = [ + 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + ]; + let mut padded = [0u8; AccountAddress::LENGTH]; + padded[AccountAddress::LENGTH - EVM_ADDRESS_LENGTH..].copy_from_slice(&evm_bytes); + let raw = EvmContractsDetails { + details: vec![("BlockMetadata".to_string(), AccountAddress::from(padded))], + }; + let bytes = bcs::to_bytes(&raw).unwrap(); + let mut map = HashMap::new(); + map.insert(OnChainEvmContractsDetails::CONFIG_ID, bytes); + let provider = InMemoryOnChainConfig::new(map); + let recovered = provider.get::().unwrap(); + assert_eq!( + recovered.get(EvmContractName::BlockMetadata), + Some(&evm_bytes) + ); + } +} diff --git a/types/src/on_chain_config/evm_genesis_config.rs b/types/src/on_chain_config/evm_genesis_config.rs index ec2f7b81262..4c000dcb916 100644 --- a/types/src/on_chain_config/evm_genesis_config.rs +++ b/types/src/on_chain_config/evm_genesis_config.rs @@ -1,18 +1,15 @@ -// Copyright (c) Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - // Copyright (c) Supra Foundation // SPDX-License-Identifier: Apache-2.0 -use once_cell::sync::Lazy; - use super::OnChainConfig; use crate::chain_id::ChainId; use anyhow::{anyhow, Result}; -use serde::{Deserialize, Serialize}; use move_core_types::{ ident_str, identifier::IdentStr, language_storage::TypeTag, move_resource::MoveStructType, }; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; +use std::fmt::Display; /// The Genesis configuration for EVM that can only be set once at genesis epoch. #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] @@ -25,6 +22,16 @@ pub struct OnChainEvmGenesisConfig { pub contracts: Vec, } +impl Display for OnChainEvmGenesisConfig { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "OnChainEvmGenesisConfig {{\n\t chain_id: {},\n\t eoas: {:?}, \n\t contracts: [{}\n\t]\n}}", + self.chain_id, self.eoas, self.contracts.iter().map(|c| format!("\n\t\t{}", c)).collect::>().join(", "), + ) + } +} + #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] pub struct GenesisEvmEOA { /// The address of the EOA to be funded @@ -33,6 +40,15 @@ pub struct GenesisEvmEOA { pub amount: u128, } +/// The Creator address and nonce determines the contract' deployment address. +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] +pub enum ContractKind { + /// Default contract creation API + Create, + /// EVM address that creates a contract. + Call(String), +} + /// The Creator address and nonce determines the contract' deployment address. #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] pub struct GenesisEvmContract { @@ -44,11 +60,34 @@ pub struct GenesisEvmContract { pub amount: u128, /// The bytecode of the contract to deploy. pub bytecode: Vec, + /// Type of the contract + pub kind: ContractKind, + /// Precalculated address of the contract + pub deploy_address: String, +} + +impl Display for GenesisEvmContract { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "GenesisEvmContract {{ creator: {}, nonce: {}, amount: {}, bytecode: {} bytes, kind: {:?}, deploy_address: {} }}", + self.creator, + self.nonce, + self.amount, + hex::encode(&self.bytecode), + self.kind, + self.deploy_address + ) + } } impl OnChainEvmGenesisConfig { /// Create a new OnChainEvmGenesisConfig with the given parameters. - pub fn new(chain_id: ChainId, eoas: Vec, contracts: Vec) -> Self { + pub fn new( + chain_id: ChainId, + eoas: Vec, + contracts: Vec, + ) -> Self { let chain_id = Self::derive_evm_chain_id_from_move_chain_id(chain_id); Self { @@ -89,13 +128,10 @@ impl OnChainConfig for OnChainEvmGenesisConfig { } } - - /// Move event type `0x1::evm_genesis_config::EvmGenesisEvent` in rust. /// See its doc in Move for more details. #[derive(Serialize, Deserialize)] -pub struct EvmGenesisEvent { -} +pub struct EvmGenesisEvent {} impl MoveStructType for EvmGenesisEvent { const MODULE_NAME: &'static IdentStr = ident_str!("evm_genesis_config"); diff --git a/types/src/on_chain_config/leader_ban_registry.rs b/types/src/on_chain_config/leader_ban_registry.rs new file mode 100644 index 00000000000..182dc0d131a --- /dev/null +++ b/types/src/on_chain_config/leader_ban_registry.rs @@ -0,0 +1,100 @@ +use crate::on_chain_config::OnChainConfig; +use anyhow::{format_err, Result}; +use derive_getters::Getters; +use derive_more::Constructor; +use move_core_types::{ + account_address::AccountAddress, + value::{serialize_values, MoveValue}, +}; +use serde::{Deserialize, Serialize}; + +/// Configuration for a [`BanRegistry`]. Stored in the Move state and updated via governance. +/// +/// This enum allows for future versions of the configuration to be added without breaking +/// the backwards compatibility constraints enforced by BCS. +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +pub enum BanRegistryParameters { + V0(BanRegistryParametersV0), +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +struct MoveBanRegistryParams { + pub config: Vec, + pub version: u8, +} + +impl Default for BanRegistryParameters { + fn default() -> Self { + BanRegistryParameters::V0(BanRegistryParametersV0::default()) + } +} + +impl OnChainConfig for BanRegistryParameters { + const MODULE_IDENTIFIER: &'static str = "leader_ban_registry_config"; + const TYPE_IDENTIFIER: &'static str = "BanRegistryParameters"; + + fn deserialize_default_impl(bytes: &[u8]) -> Result { + let move_ban_registry = bcs::from_bytes::(bytes).map_err(|e| { + format_err!("[on-chain config] Failed to deserialize into config: {}", e) + })?; + match move_ban_registry.version { + 0 => { + let params_v0 = bcs::from_bytes::(&move_ban_registry.config) + .map_err(|e| format_err!("[on-chain config] Failed to deserialize into config BanRegistryParametersV0: {}", e))?; + Ok(BanRegistryParameters::V0(params_v0)) + }, + _ => Err(format_err!( + "[on-chain config] Failed to deserialize into config: Invalid Version: {}", + move_ban_registry.version + )), + } + } +} + +impl BanRegistryParameters { + pub fn serialize_into_move_values_with_signer( + &self, + signer_address: AccountAddress, + ) -> Vec> { + let arguments: Vec = match &self { + BanRegistryParameters::V0(ban_registry_parameters_v0) => { + let params_bytes = bcs::to_bytes(ban_registry_parameters_v0) + .expect("serialisation of leader ban config failed"); + vec![ + MoveValue::Signer(signer_address), + MoveValue::vector_u8(params_bytes), + ] + }, + }; + serialize_values(&arguments) + } +} + +/// The parameters of the consensus leader [`BanRegistry`]. +/// +/// BCS field order **must** match the Move struct `BanRegistryParametersV0`: +/// `initial_elections_denied, max_elections_denied, minimum_unbanned_proposers, probation_elections`. +/// +/// The [`Default`] values of the parameters disable banning. +#[derive(Clone, Constructor, Debug, Default, Deserialize, Eq, PartialEq, Getters, Serialize)] +pub struct BanRegistryParametersV0 { + /// The (approximate) initial number of election opportunities denied to a validator that + /// fails to propose a committed block when elected as leader. + /// + /// This number is scaled in proportion to the size of the [`Committee`] for the current epoch to + /// derive the total number of consensus rounds for which a validator is banned. This enables the + /// ban duration to remain roughly constant, regardless of the number of validators in the committee. + initial_elections_denied: u8, + /// The (approximate) maximum number of election opportunities denied to a validator that + /// consecutively fails to propose a committed block when elected as leader. + max_elections_denied: u32, + /// The lower bound on the number of validators that must remain eligible to be elected as + /// consensus leader. If banning a validator would cause the number of eligible validators to + /// drop below this number, the ban is not applied. + minimum_unbanned_proposers: u8, + /// The number of elections a validator must serve on probation after their ban expires. + /// During probation, the validator is eligible for election but will be banned for a longer + /// period (with `consecutive_bans` incremented) if it fails again. If the validator completes + /// probation without failing, the ban record is fully removed. + probation_elections: u8, +} diff --git a/types/src/on_chain_config/mod.rs b/types/src/on_chain_config/mod.rs index 0795f5eff19..efe9dff5b12 100644 --- a/types/src/on_chain_config/mod.rs +++ b/types/src/on_chain_config/mod.rs @@ -8,7 +8,7 @@ use crate::{ event::{EventHandle, EventKey}, state_store::{state_key::StateKey, StateView}, }; -use anyhow::{format_err, Result}; +use anyhow::{format_err, Context, Result}; use bytes::Bytes; use move_core_types::{ account_address::AccountAddress, @@ -27,17 +27,18 @@ mod automation_registry; mod chain_id; mod commit_history; mod consensus_config; +mod evm_config; mod evm_genesis_config; mod execution_config; mod gas_schedule; mod jwk_consensus_config; +mod leader_ban_registry; pub mod randomness_api_v0_config; mod randomness_config; mod timed_features; mod timestamp; mod transaction_fee; mod validator_set; - pub use self::{ approved_execution_hashes::ApprovedExecutionHashes, aptos_features::*, @@ -46,7 +47,8 @@ pub use self::{ }, automation_registry::{ AutomationCycleDetails, AutomationCycleEvent, AutomationCycleInfo, AutomationCycleState, - AutomationRegistryConfig, AutomationRegistryConfigV1, AutomationRegistryConfigV2, AutomationCycleTransitionState + AutomationCycleTransitionState, AutomationRegistryConfig, AutomationRegistryConfigV1, + AutomationRegistryConfigV2, }, commit_history::CommitHistoryResource, consensus_config::{ @@ -54,6 +56,14 @@ pub use self::{ LeaderReputationType, OnChainConsensusConfig, ProposerAndVoterConfig, ProposerElectionType, ValidatorTxnConfig, DEFAULT_ENABLED_WINDOW_SIZE, DEFAULT_WINDOW_SIZE, }, + evm_config::{ + evm_address_as_account_address, EvmContractName, EvmScalarConfigKey, OnChainEvmConfig, + OnChainEvmContractsDetails, + }, + evm_genesis_config::{ + ContractKind, GenesisEvmContract, GenesisEvmEOA, OnChainEvmGenesisConfig, + EVM_GENESIS_EVENT_MOVE_TYPE_TAG, + }, execution_config::{ BlockGasLimitType, ExecutionConfigV1, ExecutionConfigV2, ExecutionConfigV4, OnChainExecutionConfig, TransactionDeduperType, TransactionShufflerType, @@ -62,6 +72,7 @@ pub use self::{ jwk_consensus_config::{ ConfigV1 as JWKConsensusConfigV1, OIDCProvider, OnChainJWKConsensusConfig, }, + leader_ban_registry::{BanRegistryParameters, BanRegistryParametersV0}, randomness_config::{ OnChainRandomnessConfig, RandomnessConfigMoveStruct, RandomnessConfigSeqNum, }, @@ -69,7 +80,6 @@ pub use self::{ timestamp::CurrentTimeMicroseconds, transaction_fee::TransactionFeeBurnCap, validator_set::{ConsensusScheme, ValidatorSet}, - evm_genesis_config::{OnChainEvmGenesisConfig, GenesisEvmContract, GenesisEvmEOA, EVM_GENESIS_EVENT_MOVE_TYPE_TAG}, }; /// To register an on-chain config in Rust: diff --git a/types/src/proof/definition.rs b/types/src/proof/definition.rs index 2e14d9a8b75..0084de3c725 100644 --- a/types/src/proof/definition.rs +++ b/types/src/proof/definition.rs @@ -32,14 +32,36 @@ use std::{any::type_name, marker::PhantomData}; /// example, both `LedgerInfoToTransactionInfoProof` and `TransactionInfoToEventProof` can be /// constructed on top of this structure. #[derive(Clone, Serialize, Deserialize)] +#[cfg_attr( + feature = "rest_api_schema", + derive(utoipa::ToSchema), + schema(bound = "") +)] pub struct AccumulatorProof { /// All siblings in this proof, including the default ones. Siblings are ordered from the bottom /// level to the root level. + #[cfg_attr(feature = "rest_api_schema",schema(value_type = String))] siblings: Vec, - + #[serde(skip)] + #[cfg_attr(feature = "rest_api_schema", schema(ignore))] phantom: PhantomData, } +#[cfg(test)] +mod tests { + #[cfg(feature = "rest_api_schema")] + #[test] + fn feature() { + use crate::proof::{AccumulatorProof, TransactionAccumulatorHasher}; + + #[derive(utoipa::ToSchema)] + pub struct TransactionInclusionProof { + #[schema(value_type = AccumulatorProof)] + pub proof: AccumulatorProof, + } + } +} + /// Because leaves can only take half the space in the tree, any numbering of the tree leaves must /// not take the full width of the total space. Thus, for a 64-bit ordering, our maximumm proof /// depth is limited to 63. diff --git a/types/src/proof/position/mod.rs b/types/src/proof/position/mod.rs index 771399b3890..af01125d8d3 100644 --- a/types/src/proof/position/mod.rs +++ b/types/src/proof/position/mod.rs @@ -26,12 +26,13 @@ use crate::proof::definition::{LeafCount, MAX_ACCUMULATOR_LEAVES, MAX_ACCUMULATOR_PROOF_DEPTH}; use anyhow::{ensure, Result}; +use serde::{Deserialize, Serialize}; use std::fmt; #[cfg(test)] mod position_test; -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize)] pub struct Position(u64); // invariant Position.0 < u64::MAX - 1 @@ -54,8 +55,7 @@ impl Position { /// What position is the node within the level? i.e. how many nodes /// are to the left of this node at the same level - #[cfg(test)] - fn pos_counting_from_left(self) -> u64 { + pub fn pos_counting_from_left(self) -> u64 { self.0 >> (self.level() + 1) } diff --git a/types/src/proptest_types.rs b/types/src/proptest_types.rs index deb3198dd01..be94d3b7e02 100644 --- a/types/src/proptest_types.rs +++ b/types/src/proptest_types.rs @@ -16,7 +16,7 @@ use crate::{ block_metadata_ext::BlockMetadataExt, chain_id::ChainId, contract_event::ContractEvent, - dkg::{DKGTranscript, DKGTranscriptMetadata}, + dkg::transactions::{DKGTransactionData, DKGTransactionType}, epoch_state::EpochState, event::{EventHandle, EventKey}, ledger_info::{generate_ledger_info_with_sig, LedgerInfo, LedgerInfoWithSignatures}, @@ -24,12 +24,13 @@ use crate::{ proof::TransactionInfoListWithProof, state_store::state_key::StateKey, transaction::{ - automated_transaction::AutomatedTransaction, block_epilogue::BlockEndInfo, ChangeSet, EntryFunction, ExecutionStatus, - IndexedTransactionSummary, Module, Multisig, MultisigTransactionPayload, RawTransaction, - ReplayProtector, Script, SignatureCheckedTransaction, SignedTransaction, Transaction, - TransactionArgument, TransactionAuxiliaryData, TransactionExecutable, - TransactionExtraConfig, TransactionInfo, TransactionListWithProof, TransactionPayload, - TransactionPayloadInner, TransactionStatus, TransactionToCommit, Version, WriteSetPayload, + automated_transaction::AutomatedTransaction, block_epilogue::BlockEndInfo, ChangeSet, + EntryFunction, ExecutionStatus, IndexedTransactionSummary, Module, Multisig, + MultisigTransactionPayload, RawTransaction, ReplayProtector, Script, + SignatureCheckedTransaction, SignedTransaction, Transaction, TransactionArgument, + TransactionAuxiliaryData, TransactionExecutable, TransactionExtraConfig, TransactionInfo, + TransactionListWithProof, TransactionPayload, TransactionPayloadInner, TransactionStatus, + TransactionToCommit, Version, WriteSetPayload, }, validator_info::ValidatorInfo, validator_signer::ValidatorSigner, @@ -49,6 +50,7 @@ use aptos_crypto::{ use move_core_types::{ identifier::Identifier, language_storage::{ModuleId, TypeTag}, + vm_status::StatusCode, }; use proptest::{ collection::{vec, SizeRange}, @@ -63,7 +65,6 @@ use std::{ iter::Iterator, sync::Arc, }; -use move_core_types::vm_status::StatusCode; impl Arbitrary for IndexedTransactionSummary { type Parameters = (); @@ -540,7 +541,7 @@ impl Arbitrary for TransactionExecutable { any::