diff --git a/.cargo/release-version b/.cargo/release-version index b0607bd530..319b54fc3e 100644 --- a/.cargo/release-version +++ b/.cargo/release-version @@ -1 +1 @@ -v4.8.1 \ No newline at end of file +v4.9.0 \ No newline at end of file diff --git a/.circleci/config.yml b/.circleci/config.yml index a736b6f01a..d0f061563b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -864,6 +864,15 @@ jobs: workspace_member: snarkvm-ledger-store flags: --features=rocks + ledger-store-with-history: + executor: rust-docker + resource_class: << pipeline.parameters.twoxlarge >> + steps: + - run_test: + workspace_member: snarkvm-ledger-store + flags: --features=rocks,history + cache_key_suffix: -with-history + ledger-store-prerelease: executor: rust-docker resource_class: << pipeline.parameters.twoxlarge >> @@ -1293,6 +1302,7 @@ workflows: - ledger-puzzle-epoch - ledger-query - ledger-store + - ledger-store-with-history - ledger-test-helpers synthesizer-workflow: diff --git a/Cargo.lock b/Cargo.lock index 944704f190..ed3125b3c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -721,9 +721,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.20" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ "crossbeam-utils", ] @@ -3110,7 +3110,7 @@ dependencies = [ [[package]] name = "snarkvm" -version = "4.8.1" +version = "4.9.0" dependencies = [ "anyhow", "bincode", @@ -3139,7 +3139,7 @@ dependencies = [ [[package]] name = "snarkvm-algorithms" -version = "4.8.1" +version = "4.9.0" dependencies = [ "aleo-std", "anyhow", @@ -3171,7 +3171,7 @@ dependencies = [ [[package]] name = "snarkvm-algorithms-cuda" -version = "4.8.1" +version = "4.9.0" dependencies = [ "blst", "cc", @@ -3181,7 +3181,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit" -version = "4.8.1" +version = "4.9.0" dependencies = [ "snarkvm-circuit-account", "snarkvm-circuit-algorithms", @@ -3194,7 +3194,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-account" -version = "4.8.1" +version = "4.9.0" dependencies = [ "anyhow", "snarkvm-circuit-network", @@ -3205,7 +3205,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-algorithms" -version = "4.8.1" +version = "4.9.0" dependencies = [ "anyhow", "snarkvm-circuit-types", @@ -3217,7 +3217,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-collections" -version = "4.8.1" +version = "4.9.0" dependencies = [ "anyhow", "snarkvm-circuit-algorithms", @@ -3231,7 +3231,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-environment" -version = "4.8.1" +version = "4.9.0" dependencies = [ "anyhow", "criterion", @@ -3255,11 +3255,11 @@ dependencies = [ [[package]] name = "snarkvm-circuit-environment-witness" -version = "4.8.1" +version = "4.9.0" [[package]] name = "snarkvm-circuit-network" -version = "4.8.1" +version = "4.9.0" dependencies = [ "snarkvm-circuit-algorithms", "snarkvm-circuit-collections", @@ -3270,7 +3270,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-program" -version = "4.8.1" +version = "4.9.0" dependencies = [ "anyhow", "rand 0.10.2", @@ -3287,7 +3287,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types" -version = "4.8.1" +version = "4.9.0" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-address", @@ -3302,7 +3302,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-address" -version = "4.8.1" +version = "4.9.0" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3314,7 +3314,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-boolean" -version = "4.8.1" +version = "4.9.0" dependencies = [ "criterion", "snarkvm-circuit-environment", @@ -3323,7 +3323,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-field" -version = "4.8.1" +version = "4.9.0" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3332,7 +3332,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-group" -version = "4.8.1" +version = "4.9.0" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3344,7 +3344,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-integers" -version = "4.8.1" +version = "4.9.0" dependencies = [ "paste", "snarkvm-circuit-environment", @@ -3357,7 +3357,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-scalar" -version = "4.8.1" +version = "4.9.0" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3367,7 +3367,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-string" -version = "4.8.1" +version = "4.9.0" dependencies = [ "rand 0.10.2", "snarkvm-circuit-environment", @@ -3380,7 +3380,7 @@ dependencies = [ [[package]] name = "snarkvm-console" -version = "4.8.1" +version = "4.9.0" dependencies = [ "snarkvm-console-account", "snarkvm-console-algorithms", @@ -3392,7 +3392,7 @@ dependencies = [ [[package]] name = "snarkvm-console-account" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "bs58", @@ -3405,7 +3405,7 @@ dependencies = [ [[package]] name = "snarkvm-console-algorithms" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "blake2s_simd", @@ -3426,7 +3426,7 @@ dependencies = [ [[package]] name = "snarkvm-console-collections" -version = "4.8.1" +version = "4.9.0" dependencies = [ "aleo-std", "criterion", @@ -3442,7 +3442,7 @@ dependencies = [ [[package]] name = "snarkvm-console-network" -version = "4.8.1" +version = "4.9.0" dependencies = [ "anyhow", "enum-iterator", @@ -3461,7 +3461,7 @@ dependencies = [ [[package]] name = "snarkvm-console-network-environment" -version = "4.8.1" +version = "4.9.0" dependencies = [ "anyhow", "bech32", @@ -3478,7 +3478,7 @@ dependencies = [ [[package]] name = "snarkvm-console-program" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "criterion", @@ -3500,7 +3500,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types" -version = "4.8.1" +version = "4.9.0" dependencies = [ "criterion", "snarkvm-console-network", @@ -3516,7 +3516,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-address" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "serde_json", @@ -3528,7 +3528,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-boolean" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "serde_json", @@ -3537,7 +3537,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-field" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "serde_json", @@ -3548,7 +3548,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-group" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "serde_json", @@ -3560,7 +3560,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-integers" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "serde_json", @@ -3572,7 +3572,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-scalar" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "serde_json", @@ -3584,7 +3584,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-string" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "serde_json", @@ -3596,7 +3596,7 @@ dependencies = [ [[package]] name = "snarkvm-curves" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "criterion", @@ -3610,7 +3610,7 @@ dependencies = [ [[package]] name = "snarkvm-fields" -version = "4.8.1" +version = "4.9.0" dependencies = [ "aleo-std", "anyhow", @@ -3628,7 +3628,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger" -version = "4.8.1" +version = "4.9.0" dependencies = [ "aleo-std", "aleo-std-storage", @@ -3666,7 +3666,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-authority" -version = "4.8.1" +version = "4.9.0" dependencies = [ "anyhow", "bincode", @@ -3679,7 +3679,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-block" -version = "4.8.1" +version = "4.9.0" dependencies = [ "aleo-std", "anyhow", @@ -3709,7 +3709,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-committee" -version = "4.8.1" +version = "4.9.0" dependencies = [ "anyhow", "bincode", @@ -3730,7 +3730,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal" -version = "4.8.1" +version = "4.9.0" dependencies = [ "snarkvm-ledger-narwhal", "snarkvm-ledger-narwhal-batch-certificate", @@ -3743,7 +3743,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-batch-certificate" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "indexmap 2.14.0", @@ -3757,7 +3757,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-batch-header" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "indexmap 2.14.0", @@ -3770,7 +3770,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-data" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bytes", "serde_json", @@ -3782,7 +3782,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-subdag" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "indexmap 2.14.0", @@ -3798,7 +3798,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-transmission" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "bytes", @@ -3811,7 +3811,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-transmission-id" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "serde_json", @@ -3821,7 +3821,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-puzzle" -version = "4.8.1" +version = "4.9.0" dependencies = [ "aleo-std", "anyhow", @@ -3843,7 +3843,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-puzzle-epoch" -version = "4.8.1" +version = "4.9.0" dependencies = [ "aleo-std", "anyhow", @@ -3865,7 +3865,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-query" -version = "4.8.1" +version = "4.9.0" dependencies = [ "anyhow", "async-trait", @@ -3881,7 +3881,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-store" -version = "4.8.1" +version = "4.9.0" dependencies = [ "aleo-std", "aleo-std-storage", @@ -3913,7 +3913,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-test-helpers" -version = "4.8.1" +version = "4.9.0" dependencies = [ "aleo-std", "anyhow", @@ -3930,14 +3930,14 @@ dependencies = [ [[package]] name = "snarkvm-metrics" -version = "4.8.1" +version = "4.9.0" dependencies = [ "metrics", ] [[package]] name = "snarkvm-parameters" -version = "4.8.1" +version = "4.9.0" dependencies = [ "aleo-std", "anyhow", @@ -3969,14 +3969,14 @@ dependencies = [ [[package]] name = "snarkvm-slipstream-plugin-interface" -version = "4.8.1" +version = "4.9.0" dependencies = [ "anyhow", ] [[package]] name = "snarkvm-slipstream-plugin-manager" -version = "4.8.1" +version = "4.9.0" dependencies = [ "anyhow", "json5", @@ -3989,7 +3989,7 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer" -version = "4.8.1" +version = "4.9.0" dependencies = [ "aleo-std", "anyhow", @@ -4035,7 +4035,7 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer-error" -version = "4.8.1" +version = "4.9.0" dependencies = [ "anyhow", "snarkvm-circuit-environment", @@ -4046,7 +4046,7 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer-process" -version = "4.8.1" +version = "4.9.0" dependencies = [ "aleo-std", "bincode", @@ -4077,7 +4077,7 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer-program" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "criterion", @@ -4101,7 +4101,7 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer-snark" -version = "4.8.1" +version = "4.9.0" dependencies = [ "bincode", "serde_json", @@ -4126,7 +4126,7 @@ dependencies = [ [[package]] name = "snarkvm-utilities" -version = "4.8.1" +version = "4.9.0" dependencies = [ "aleo-std", "anyhow", @@ -4150,7 +4150,7 @@ dependencies = [ [[package]] name = "snarkvm-utilities-derives" -version = "4.8.1" +version = "4.9.0" dependencies = [ "proc-macro2", "quote 1.0.46", @@ -4159,7 +4159,7 @@ dependencies = [ [[package]] name = "snarkvm-wasm" -version = "4.8.1" +version = "4.9.0" dependencies = [ "getrandom 0.4.3", "snarkvm-console", diff --git a/Cargo.toml b/Cargo.toml index 3666daf46e..364a84758c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "A decentralized virtual machine" homepage = "https://aleo.org" @@ -129,7 +129,7 @@ package = [ async = [ "snarkvm-ledger/async", "snarkvm-synthesizer/async" ] cuda = [ "snarkvm-algorithms/cuda" ] -history = [ "snarkvm-synthesizer/history" ] +history = [ "snarkvm-ledger?/history", "snarkvm-synthesizer/history" ] history-staking-rewards = [ "snarkvm-synthesizer/history-staking-rewards" ] slipstream-plugins = [ "snarkvm-synthesizer/slipstream-plugins", "dep:snarkvm-slipstream-plugin-interface", "dep:snarkvm-slipstream-plugin-manager" ] parameters_no_std_out = [ "snarkvm-parameters/no_std_out" ] @@ -190,263 +190,263 @@ test_consensus_heights = [ "snarkvm-console/test_consensus_heights", "snarkvm-sy [workspace.dependencies.snarkvm-algorithms] path = "algorithms" -version = "=4.8.1" +version = "=4.9.0" default-features = false [workspace.dependencies.snarkvm-algorithms-cuda] path = "algorithms/cuda" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-circuit] path = "circuit" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-circuit-account] path = "circuit/account" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-circuit-algorithms] path = "circuit/algorithms" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-circuit-collections] path = "circuit/collections" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-circuit-environment] path = "circuit/environment" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-circuit-environment-witness] path = "circuit/environment/witness" -version = "=4.8.1" +version = "=4.9.0" default-features = false [workspace.dependencies.snarkvm-circuit-network] path = "circuit/network" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-circuit-program] path = "circuit/program" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-circuit-types] path = "circuit/types" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-circuit-types-address] path = "circuit/types/address" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-circuit-types-boolean] path = "circuit/types/boolean" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-circuit-types-field] path = "circuit/types/field" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-circuit-types-scalar] path = "circuit/types/scalar" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-circuit-types-string] path = "circuit/types/string" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-console] path = "console" -version = "=4.8.1" +version = "=4.9.0" default-features = false [workspace.dependencies.snarkvm-console-account] path = "console/account" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-console-algorithms] path = "console/algorithms" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-console-collections] path = "console/collections" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-console-network] path = "console/network" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-console-network-environment] path = "console/network/environment" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-console-program] path = "console/program" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-console-types] path = "console/types" -version = "=4.8.1" +version = "=4.9.0" default-features = false [workspace.dependencies.snarkvm-console-types-address] path = "console/types/address" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-console-types-boolean] path = "console/types/boolean" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-console-types-field] path = "console/types/field" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-console-types-group] path = "console/types/group" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-console-types-integers] path = "console/types/integers" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-console-types-scalar] path = "console/types/scalar" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-console-types-string] path = "console/types/string" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-circuit-types-group] path = "circuit/types/group" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-circuit-types-integers] path = "circuit/types/integers" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-curves] path = "curves" -version = "=4.8.1" +version = "=4.9.0" default-features = false [workspace.dependencies.snarkvm-fields] path = "fields" -version = "=4.8.1" +version = "=4.9.0" default-features = false [workspace.dependencies.snarkvm-ledger] path = "ledger" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-ledger-authority] path = "ledger/authority" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-ledger-block] path = "ledger/block" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-ledger-committee] path = "ledger/committee" -version = "=4.8.1" +version = "=4.9.0" default-features = false [workspace.dependencies.snarkvm-ledger-narwhal] path = "ledger/narwhal" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-ledger-narwhal-data] path = "ledger/narwhal/data" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-ledger-narwhal-batch-header] path = "ledger/narwhal/batch-header" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-ledger-narwhal-batch-certificate] path = "ledger/narwhal/batch-certificate" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-ledger-narwhal-subdag] path = "ledger/narwhal/subdag" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-ledger-narwhal-transmission] path = "ledger/narwhal/transmission" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-ledger-narwhal-transmission-id] path = "ledger/narwhal/transmission-id" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-ledger-puzzle] path = "ledger/puzzle" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-ledger-puzzle-epoch] path = "ledger/puzzle/epoch" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-ledger-query] path = "ledger/query" -version = "=4.8.1" +version = "=4.9.0" default-features = false [workspace.dependencies.snarkvm-ledger-store] path = "ledger/store" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-slipstream-plugin-interface] path = "plugins/slipstream_plugin_interface" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-slipstream-plugin-manager] path = "plugins/slipstream_plugin_manager" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-ledger-test-helpers] path = "ledger/test-helpers" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-metrics] path = "metrics" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-parameters] path = "parameters" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-synthesizer] path = "synthesizer" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-synthesizer-error] path = "synthesizer/error" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-synthesizer-process] path = "synthesizer/process" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-synthesizer-program] path = "synthesizer/program" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-synthesizer-snark] path = "synthesizer/snark" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-utilities] path = "utilities" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-utilities-derives] path = "utilities/derives" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.snarkvm-wasm] path = "wasm" -version = "=4.8.1" +version = "=4.9.0" [workspace.dependencies.aleo-std] version = "1.0.1" diff --git a/algorithms/Cargo.toml b/algorithms/Cargo.toml index 19c01a2806..9d653bca8c 100644 --- a/algorithms/Cargo.toml +++ b/algorithms/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-algorithms" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Algorithms for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/algorithms/cuda/Cargo.toml b/algorithms/cuda/Cargo.toml index f62d8819c7..9428ef89f3 100644 --- a/algorithms/cuda/Cargo.toml +++ b/algorithms/cuda/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-algorithms-cuda" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Cuda optimizations for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/circuit/Cargo.toml b/circuit/Cargo.toml index 57ca5d9781..f0991136f2 100644 --- a/circuit/Cargo.toml +++ b/circuit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Circuits for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/circuit/account/Cargo.toml b/circuit/account/Cargo.toml index 4d721a1586..1b2b57767e 100644 --- a/circuit/account/Cargo.toml +++ b/circuit/account/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit-account" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Account circuit library for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/circuit/algorithms/Cargo.toml b/circuit/algorithms/Cargo.toml index e3653c353c..1490cd44d1 100644 --- a/circuit/algorithms/Cargo.toml +++ b/circuit/algorithms/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit-algorithms" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Algorithm circuit library for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/circuit/collections/Cargo.toml b/circuit/collections/Cargo.toml index 29e0c28367..b3f2c90de8 100644 --- a/circuit/collections/Cargo.toml +++ b/circuit/collections/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit-collections" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Collections circuit library for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/circuit/environment/Cargo.toml b/circuit/environment/Cargo.toml index e6e4aea6ca..671c95f7aa 100644 --- a/circuit/environment/Cargo.toml +++ b/circuit/environment/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit-environment" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Circuit environment for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/circuit/environment/witness/Cargo.toml b/circuit/environment/witness/Cargo.toml index 8c7ab79524..c594262875 100644 --- a/circuit/environment/witness/Cargo.toml +++ b/circuit/environment/witness/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit-environment-witness" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "A procedural macro to construct a witness in an environment" homepage = "https://aleo.org" diff --git a/circuit/network/Cargo.toml b/circuit/network/Cargo.toml index b3db49c213..4ec5bbec92 100644 --- a/circuit/network/Cargo.toml +++ b/circuit/network/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit-network" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Network circuit library for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/circuit/program/Cargo.toml b/circuit/program/Cargo.toml index c09a2e4348..b02bfcca2b 100644 --- a/circuit/program/Cargo.toml +++ b/circuit/program/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit-program" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Program circuit library for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/circuit/types/Cargo.toml b/circuit/types/Cargo.toml index 3407e0e87a..77da84e376 100644 --- a/circuit/types/Cargo.toml +++ b/circuit/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit-types" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Primitive circuit for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/circuit/types/address/Cargo.toml b/circuit/types/address/Cargo.toml index c2a25da340..17bb22ef1e 100644 --- a/circuit/types/address/Cargo.toml +++ b/circuit/types/address/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit-types-address" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Address circuit for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/circuit/types/boolean/Cargo.toml b/circuit/types/boolean/Cargo.toml index 284ee5b232..325da73ed6 100644 --- a/circuit/types/boolean/Cargo.toml +++ b/circuit/types/boolean/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit-types-boolean" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Boolean circuit for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/circuit/types/field/Cargo.toml b/circuit/types/field/Cargo.toml index 977d7d6544..f79c689b25 100644 --- a/circuit/types/field/Cargo.toml +++ b/circuit/types/field/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit-types-field" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Field circuit for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/circuit/types/group/Cargo.toml b/circuit/types/group/Cargo.toml index 0785734542..04206de252 100644 --- a/circuit/types/group/Cargo.toml +++ b/circuit/types/group/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit-types-group" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Group circuit for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/circuit/types/integers/Cargo.toml b/circuit/types/integers/Cargo.toml index 6f6c4e61aa..418f038547 100644 --- a/circuit/types/integers/Cargo.toml +++ b/circuit/types/integers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit-types-integers" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Integer circuit for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/circuit/types/scalar/Cargo.toml b/circuit/types/scalar/Cargo.toml index 1f63f7c6ae..e71ed59c97 100644 --- a/circuit/types/scalar/Cargo.toml +++ b/circuit/types/scalar/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit-types-scalar" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Scalar circuit for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/circuit/types/string/Cargo.toml b/circuit/types/string/Cargo.toml index d721299d64..80f66deb4e 100644 --- a/circuit/types/string/Cargo.toml +++ b/circuit/types/string/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-circuit-types-string" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "String circuit for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/console/Cargo.toml b/console/Cargo.toml index cc730f1173..bacf0a8e00 100644 --- a/console/Cargo.toml +++ b/console/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-console" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Console environment for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/console/account/Cargo.toml b/console/account/Cargo.toml index bba5ae9dba..7de6dbf75a 100644 --- a/console/account/Cargo.toml +++ b/console/account/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-console-account" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Account operations for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/console/algorithms/Cargo.toml b/console/algorithms/Cargo.toml index a39a538645..9bd08e06c8 100644 --- a/console/algorithms/Cargo.toml +++ b/console/algorithms/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-console-algorithms" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Console algorithms for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/console/collections/Cargo.toml b/console/collections/Cargo.toml index f6310ee082..c3200d3632 100644 --- a/console/collections/Cargo.toml +++ b/console/collections/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-console-collections" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Collections for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/console/network/Cargo.toml b/console/network/Cargo.toml index 33b133cb77..556cbcf7bc 100644 --- a/console/network/Cargo.toml +++ b/console/network/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-console-network" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Network console library for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/console/network/environment/Cargo.toml b/console/network/environment/Cargo.toml index 794e4521a7..51e4d93f72 100644 --- a/console/network/environment/Cargo.toml +++ b/console/network/environment/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-console-network-environment" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Environment console library for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/console/network/src/consensus_heights.rs b/console/network/src/consensus_heights.rs index 8c2fd93f93..e1cba50e20 100644 --- a/console/network/src/consensus_heights.rs +++ b/console/network/src/consensus_heights.rs @@ -182,8 +182,8 @@ pub const TESTNET_V0_CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); NUM_CO (ConsensusVersion::V14, 15_370_000), (ConsensusVersion::V15, 16_886_000), (ConsensusVersion::V16, 17_319_000), - (ConsensusVersion::V17, u32::MAX), - (ConsensusVersion::V18, u32::MAX), + (ConsensusVersion::V17, 18_295_000), + (ConsensusVersion::V18, 18_296_000), ]; /// The consensus version heights when the `test_consensus_heights` feature is enabled. diff --git a/console/program/Cargo.toml b/console/program/Cargo.toml index 59a01590b9..5f630793de 100644 --- a/console/program/Cargo.toml +++ b/console/program/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-console-program" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Program operations for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/console/types/Cargo.toml b/console/types/Cargo.toml index 366244b228..bb53e17049 100644 --- a/console/types/Cargo.toml +++ b/console/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-console-types" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Console types for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/console/types/address/Cargo.toml b/console/types/address/Cargo.toml index 391a2f5c1e..c6b6325e56 100644 --- a/console/types/address/Cargo.toml +++ b/console/types/address/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-console-types-address" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Type operations for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/console/types/boolean/Cargo.toml b/console/types/boolean/Cargo.toml index cf77c1e0ab..049c507945 100644 --- a/console/types/boolean/Cargo.toml +++ b/console/types/boolean/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-console-types-boolean" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Type operations for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/console/types/field/Cargo.toml b/console/types/field/Cargo.toml index d9e28314d7..19d496039c 100644 --- a/console/types/field/Cargo.toml +++ b/console/types/field/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-console-types-field" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Type operations for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/console/types/group/Cargo.toml b/console/types/group/Cargo.toml index 416b71b3b2..a47220280e 100644 --- a/console/types/group/Cargo.toml +++ b/console/types/group/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-console-types-group" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Type operations for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/console/types/integers/Cargo.toml b/console/types/integers/Cargo.toml index 54c62fa262..e4afb8927a 100644 --- a/console/types/integers/Cargo.toml +++ b/console/types/integers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-console-types-integers" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Type operations for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/console/types/scalar/Cargo.toml b/console/types/scalar/Cargo.toml index 8e9f36b2a6..de9f87230f 100644 --- a/console/types/scalar/Cargo.toml +++ b/console/types/scalar/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-console-types-scalar" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Type operations for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/console/types/string/Cargo.toml b/console/types/string/Cargo.toml index 9d80598ead..ba18b303bf 100644 --- a/console/types/string/Cargo.toml +++ b/console/types/string/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-console-types-string" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Type operations for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/curves/Cargo.toml b/curves/Cargo.toml index eef58bb96a..27e5c2263b 100644 --- a/curves/Cargo.toml +++ b/curves/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-curves" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Curves for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/fields/Cargo.toml b/fields/Cargo.toml index e3b525d8c8..c9ee0f64d8 100644 --- a/fields/Cargo.toml +++ b/fields/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-fields" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Fields for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/Cargo.toml b/ledger/Cargo.toml index 40759bd525..003c11b763 100644 --- a/ledger/Cargo.toml +++ b/ledger/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "A node ledger for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/authority/Cargo.toml b/ledger/authority/Cargo.toml index a91f1a5347..4e2a342cc8 100644 --- a/ledger/authority/Cargo.toml +++ b/ledger/authority/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger-authority" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Data structures for a block authority in a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/block/Cargo.toml b/ledger/block/Cargo.toml index 0ac85bc777..0e1d3ad4e2 100644 --- a/ledger/block/Cargo.toml +++ b/ledger/block/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger-block" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "A block for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/committee/Cargo.toml b/ledger/committee/Cargo.toml index 5dcad3bbb0..d124e83096 100644 --- a/ledger/committee/Cargo.toml +++ b/ledger/committee/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger-committee" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "A committee for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/narwhal/Cargo.toml b/ledger/narwhal/Cargo.toml index 0d3f49ade9..68129a8fda 100644 --- a/ledger/narwhal/Cargo.toml +++ b/ledger/narwhal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger-narwhal" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Data structures for a Narwhal-style memory pool in a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/narwhal/batch-certificate/Cargo.toml b/ledger/narwhal/batch-certificate/Cargo.toml index ecc60cbab2..ac809bc8f5 100644 --- a/ledger/narwhal/batch-certificate/Cargo.toml +++ b/ledger/narwhal/batch-certificate/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger-narwhal-batch-certificate" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "A batch certificate for a Narwhal-style memory pool in a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/narwhal/batch-header/Cargo.toml b/ledger/narwhal/batch-header/Cargo.toml index 27dc172718..daab8eab82 100644 --- a/ledger/narwhal/batch-header/Cargo.toml +++ b/ledger/narwhal/batch-header/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger-narwhal-batch-header" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "A batch header for a Narwhal-style memory pool in a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/narwhal/data/Cargo.toml b/ledger/narwhal/data/Cargo.toml index 84701242f6..16675b40b1 100644 --- a/ledger/narwhal/data/Cargo.toml +++ b/ledger/narwhal/data/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger-narwhal-data" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "A batch certificate for a Narwhal-style memory pool in a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/narwhal/subdag/Cargo.toml b/ledger/narwhal/subdag/Cargo.toml index f3b893e764..2d0f7e111d 100644 --- a/ledger/narwhal/subdag/Cargo.toml +++ b/ledger/narwhal/subdag/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger-narwhal-subdag" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "A subdag for a Narwhal-style memory pool in a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/narwhal/transmission-id/Cargo.toml b/ledger/narwhal/transmission-id/Cargo.toml index bdd887cc9d..6e6f88dfda 100644 --- a/ledger/narwhal/transmission-id/Cargo.toml +++ b/ledger/narwhal/transmission-id/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger-narwhal-transmission-id" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "A transmission ID for a Narwhal-style memory pool in a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/narwhal/transmission/Cargo.toml b/ledger/narwhal/transmission/Cargo.toml index 8b4751e89a..fdc8fcbf85 100644 --- a/ledger/narwhal/transmission/Cargo.toml +++ b/ledger/narwhal/transmission/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger-narwhal-transmission" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "A transmission for a Narwhal-style memory pool in a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/puzzle/Cargo.toml b/ledger/puzzle/Cargo.toml index efd4f935aa..35f2ea953f 100644 --- a/ledger/puzzle/Cargo.toml +++ b/ledger/puzzle/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger-puzzle" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Puzzle for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/puzzle/epoch/Cargo.toml b/ledger/puzzle/epoch/Cargo.toml index 6c88ccde54..2c2e6039e5 100644 --- a/ledger/puzzle/epoch/Cargo.toml +++ b/ledger/puzzle/epoch/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger-puzzle-epoch" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Epoch puzzle for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/query/Cargo.toml b/ledger/query/Cargo.toml index 0c32812e87..ae9b7aad3e 100644 --- a/ledger/query/Cargo.toml +++ b/ledger/query/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger-query" -version = "4.8.1" +version = "4.9.0" authors = ["The Aleo Team "] description = "A query for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/src/lib.rs b/ledger/src/lib.rs index 793402ee4d..f2d1ee0e6d 100644 --- a/ledger/src/lib.rs +++ b/ledger/src/lib.rs @@ -65,6 +65,8 @@ use snarkvm_ledger_committee::Committee; use snarkvm_ledger_narwhal::{BatchCertificate, Subdag, Transmission, TransmissionID}; use snarkvm_ledger_puzzle::{Puzzle, PuzzleSolutions, Solution, SolutionID}; use snarkvm_ledger_query::QueryTrait; +#[cfg(not(feature = "history"))] +use snarkvm_ledger_store::AUTHORITY_RETENTION_BLOCKS; use snarkvm_ledger_store::{ConsensusStorage, ConsensusStore}; use snarkvm_synthesizer::{ program::{FinalizeGlobalState, Program}, @@ -244,13 +246,22 @@ impl> Ledger { } // Spot check the integrity of `NUM_BLOCKS` random blocks upon bootup. + // When built with the `history` feature, this spans across the entire ledger. + // When the `history` feature is not enabled, we limit ourselves to the last `AUTHORITY_RETENTION_BLOCKS` + // blocks since those are guaranteed to have not been pruned. const NUM_BLOCKS: usize = 10; - // Retrieve the latest height. let latest_height = ledger.current_block.read().height(); debug_assert_eq!(latest_height, ledger.vm.block_store().max_height().unwrap(), "Mismatch in latest height"); + + #[cfg(feature = "history")] + let earliest_height = 0; + #[cfg(not(feature = "history"))] + // Subtract one because the inclusive range should contain exactly `AUTHORITY_RETENTION_BLOCKS` blocks. + let earliest_height = latest_height.saturating_sub(AUTHORITY_RETENTION_BLOCKS.saturating_sub(1)); + // Sample random block heights. - let block_heights: Vec = - (0..=latest_height).sample(&mut rand::rng(), (latest_height as usize).min(NUM_BLOCKS)); + let num_blocks = usize::try_from(latest_height - earliest_height)?.min(NUM_BLOCKS); + let block_heights: Vec = (earliest_height..=latest_height).sample(&mut rand::rng(), num_blocks); cfg_into_iter!(block_heights).try_for_each(|height| { ledger.get_block(height)?; Ok::<_, Error>(()) @@ -298,8 +309,13 @@ impl> Ledger { const NUM_BLOCKS: usize = 10; let latest_height = ledger.current_block.read().height(); debug_assert_eq!(latest_height, ledger.vm.block_store().max_height().unwrap(), "Mismatch in latest height"); - let block_heights: Vec = - (0..=latest_height).sample(&mut rand::rng(), (latest_height as usize).min(NUM_BLOCKS)); + // Restrict non-history builds to the retained authority window. + #[cfg(feature = "history")] + let earliest_height = 0; + #[cfg(not(feature = "history"))] + let earliest_height = latest_height.saturating_sub(AUTHORITY_RETENTION_BLOCKS.saturating_sub(1)); + let num_blocks = usize::try_from(latest_height - earliest_height)?.min(NUM_BLOCKS); + let block_heights: Vec = (earliest_height..=latest_height).sample(&mut rand::rng(), num_blocks); cfg_into_iter!(block_heights).try_for_each(|height| { ledger.get_block(height)?; Ok::<_, Error>(()) diff --git a/ledger/store/Cargo.toml b/ledger/store/Cargo.toml index 1b791357b7..5fbebcb942 100644 --- a/ledger/store/Cargo.toml +++ b/ledger/store/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger-store" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "A data store for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/ledger/store/src/block/mod.rs b/ledger/store/src/block/mod.rs index 0ae0113b88..e0254ab62f 100644 --- a/ledger/store/src/block/mod.rs +++ b/ledger/store/src/block/mod.rs @@ -140,6 +140,130 @@ fn missing_block_in_tree_error(height: u32, block_tree_cache_path: Option<&std:: } } +/// The number of recent blocks whose authority data is retained when the `history` feature is disabled. +/// +/// At the ideal block time of 2.5 seconds, the network produces `60 * 60 * 24 / 2.5 = 34,560` blocks +/// per day, so retaining 100,000 blocks keeps roughly three days of authority data before pruning. +/// +/// This constant exists in all builds (including `history`) because it also describes the retention +/// window of pruned peers, which any node needs when requesting authority data during sync. +#[cfg(not(test))] +pub const AUTHORITY_RETENTION_BLOCKS: u32 = 100_000; +/// A reduced retention window for unit tests, so pruning can be exercised without building 100,000 blocks. +#[cfg(test)] +pub const AUTHORITY_RETENTION_BLOCKS: u32 = 100; + +/// The target maximum number of map deletions in one startup pruning batch. +#[cfg(not(feature = "history"))] +const AUTHORITY_PRUNING_BATCH_SIZE: usize = 10_000; + +/// Returns the certificate IDs for an authority after validating their block indexes. +#[cfg(not(feature = "history"))] +fn prepare_authority_for_pruning>( + storage: &B, + block_height: u32, + block_hash: &N::BlockHash, +) -> Result>>> { + let Some(authority) = storage.authority_map().get_speculative(block_hash)? else { + return Ok(None); + }; + + let certificate_ids = match authority.as_ref() { + Authority::Beacon(_) => Vec::new(), + Authority::Quorum(subdag) => subdag.certificate_ids().collect(), + }; + + for certificate_id in &certificate_ids { + if let Some(certificate_index) = storage.certificate_map().get_speculative(certificate_id)? { + ensure!( + certificate_index.0 == block_height, + "Certificate '{certificate_id}' points to block '{}' instead of block '{block_height}'", + certificate_index.0 + ); + } + } + + Ok(Some(certificate_ids)) +} + +/// Prunes authority data outside the retained block window when opening storage. +#[cfg(not(feature = "history"))] +fn prune_expired_authorities>(storage: &B, latest_height: u32) -> Result<()> { + let oldest_retained_height = latest_height.saturating_sub(AUTHORITY_RETENTION_BLOCKS - 1); + + if oldest_retained_height <= 1 { + return Ok(()); + } + + // Remove certificate indexes first to avoid leaving indexes that point to removed authorities after an interruption. + // Keep one forward iterator to avoid rescanning RocksDB tombstones. Each batch only removes keys already yielded. + let mut certificate_ids_to_remove = Vec::with_capacity(AUTHORITY_PRUNING_BATCH_SIZE); + for (certificate_id, certificate_index) in storage.certificate_map().iter_confirmed() { + let block_height = certificate_index.0; + if block_height == 0 || block_height >= oldest_retained_height { + continue; + } + + certificate_ids_to_remove.push(certificate_id.into_owned()); + if certificate_ids_to_remove.len() == AUTHORITY_PRUNING_BATCH_SIZE { + atomic_batch_scope!(storage, { + for certificate_id in &certificate_ids_to_remove { + storage.certificate_map().remove(certificate_id)?; + } + Ok(()) + })?; + certificate_ids_to_remove.clear(); + } + } + if !certificate_ids_to_remove.is_empty() { + atomic_batch_scope!(storage, { + for certificate_id in &certificate_ids_to_remove { + storage.certificate_map().remove(certificate_id)?; + } + Ok(()) + })?; + } + + let mut block_hashes_to_remove = Vec::with_capacity(AUTHORITY_PRUNING_BATCH_SIZE); + for block_hash in storage.authority_map().keys_confirmed() { + let block_hash = block_hash.into_owned(); + let block_height = storage + .reverse_id_map() + .get_confirmed(&block_hash)? + .with_context(|| format!("Missing block height for authority '{block_hash}'"))?; + let block_height = *block_height; + if block_height == 0 || block_height >= oldest_retained_height { + continue; + } + + let indexed_hash = storage + .id_map() + .get_confirmed(&block_height)? + .with_context(|| format!("Missing block hash for authority at height '{block_height}'"))?; + ensure!(*indexed_hash == block_hash, "Mismatching block hash for authority at height '{block_height}'"); + + block_hashes_to_remove.push(block_hash); + if block_hashes_to_remove.len() == AUTHORITY_PRUNING_BATCH_SIZE { + atomic_batch_scope!(storage, { + for block_hash in &block_hashes_to_remove { + storage.authority_map().remove(block_hash)?; + } + Ok(()) + })?; + block_hashes_to_remove.clear(); + } + } + if !block_hashes_to_remove.is_empty() { + atomic_batch_scope!(storage, { + for block_hash in &block_hashes_to_remove { + storage.authority_map().remove(block_hash)?; + } + Ok(()) + })?; + } + Ok(()) +} + /// A trait for block storage. pub trait BlockStorage: 'static + Clone + Send + Sync { /// The mapping of `block height` to `state root`. @@ -425,7 +549,31 @@ pub trait BlockStorage: 'static + Clone + Send + Sync { .map(|tx| tx.to_unconfirmed_transaction_id()) .collect::>>()?; + // Prepare the authority that expires when this block is inserted. + #[cfg(not(feature = "history"))] + let authority_to_prune = { + match block.height().checked_sub(AUTHORITY_RETENTION_BLOCKS).filter(|height| *height > 0) { + Some(expired_height) => { + let expired_hash = self.id_map().get_speculative(&expired_height)?.with_context(|| { + format!("Missing block hash for expired authority at height '{expired_height}'") + })?; + prepare_authority_for_pruning(self, expired_height, &expired_hash)? + .map(|certificate_ids| (*expired_hash, certificate_ids)) + } + None => None, + } + }; + atomic_batch_scope!(self, { + // Prune expired authority data before storing the incoming block. + #[cfg(not(feature = "history"))] + if let Some((expired_hash, certificate_ids)) = &authority_to_prune { + for certificate_id in certificate_ids { + self.certificate_map().remove(certificate_id)?; + } + self.authority_map().remove(expired_hash)?; + } + // Store the (block height, state root) pair. self.state_root_map().insert(block.height(), state_root)?; // Store the (state root, block height) pair. @@ -686,14 +834,30 @@ pub trait BlockStorage: 'static + Clone + Send + Sync { let Some(transition) = self.transition_store().get_transition(&transition_id)? else { bail!("The transition '{transition_id}' for commitment '{commitment}' is missing in storage"); }; - // Retrieve the block. - let Some(block) = self.get_block(&block_hash)? else { - bail!("The block '{block_hash}' for commitment '{commitment}' is missing in storage"); + // Retrieve the block height. + let Some(block_height) = self.get_block_height(&block_hash)? else { + bail!("The block height for commitment '{commitment}' is missing in storage"); + }; + // Retrieve the previous block hash. + let Some(previous_hash) = self.get_previous_block_hash(block_height)? else { + bail!("The previous block hash for commitment '{commitment}' is missing in storage"); + }; + // Retrieve the block header. + let Some(block_header) = self.get_block_header(&block_hash)? else { + bail!("The block header for commitment '{commitment}' is missing in storage"); + }; + // Ensure the block height matches. + if block_header.height() != block_height { + bail!("Mismatching block height for block {block_height} ('{block_hash}')") + } + // Retrieve the block transactions. + let Some(transactions) = self.get_block_transactions(&block_hash)? else { + bail!("The block transactions for commitment '{commitment}' are missing in storage"); }; // Construct the global state root and block path. let global_state_root = *block_tree.root(); - let block_path = block_tree.prove(block.height() as usize, &block.hash().to_bits_le())?; + let block_path = block_tree.prove(block_height as usize, &block_hash.to_bits_le())?; // Ensure the global state root exists in storage. if !self.reverse_state_root_map().contains_key_confirmed(&global_state_root.into())? { @@ -706,7 +870,6 @@ pub trait BlockStorage: 'static + Clone + Send + Sync { let transition_path = transition.to_path(&transition_leaf)?; // Construct the transactions path. - let transactions = block.transactions(); let Ok(transactions_path) = transactions.to_path(transaction_id) else { bail!("The transaction '{transaction_id}' for commitment '{commitment}' is not in the block"); }; @@ -719,7 +882,6 @@ pub trait BlockStorage: 'static + Clone + Send + Sync { let transaction_path = transaction.to_path(&transaction_leaf)?; // Construct the block header path. - let block_header = block.header(); let header_root = block_header.to_root()?; let header_leaf = HeaderLeaf::::new(1, block_header.transactions_root()); let header_path = block_header.to_path(&header_leaf)?; @@ -727,8 +889,8 @@ pub trait BlockStorage: 'static + Clone + Send + Sync { Ok(StatePath::from( global_state_root.into(), block_path, - block.hash(), - block.previous_hash(), + block_hash, + previous_hash, header_root, header_path, header_leaf, @@ -1090,6 +1252,13 @@ impl> BlockStore { } let block_cache = RwLock::new(BlockCache::new(initial_cache)?); + + #[cfg(not(feature = "history"))] + // Block heights start at zero, so the latest height is one less than the number of leaves. + if let Some(latest_height) = cache_end_height.checked_sub(1) { + prune_expired_authorities(&storage, latest_height)?; + } + Ok(Self { storage, tree: Arc::new(RwLock::new(tree)), block_cache: Arc::new(Some(block_cache)) }) } @@ -1463,7 +1632,7 @@ impl> BlockStore { } /// Retrieve an unconfirmed transaction using its ID. - /// + /// /// For a rejected transaction, this returns the origin transaction issued by the user, not the fee transaction. /// /// # Returns @@ -1591,10 +1760,122 @@ impl> BlockStore { mod tests { use super::*; use crate::helpers::memory::BlockMemory; + #[cfg(feature = "rocks")] + use crate::helpers::rocksdb::BlockDB; + #[cfg(any(not(feature = "history"), feature = "rocks"))] + use console::account::Address; + use console::account::PrivateKey; + use snarkvm_ledger_block::Metadata; use std::path::Path; type CurrentNetwork = console::network::MainnetV0; + fn sample_block_chain(num_blocks: u32, rng: &mut TestRng) -> Vec> { + assert!(num_blocks > 0, "The block chain must not be empty"); + + let private_key = PrivateKey::::new(rng).unwrap(); + let mut previous_hash = ::BlockHash::default(); + + (0..num_blocks) + .map(|height| { + let transactions = Transactions::from(&[]); + let ratifications = Ratifications::try_from(vec![]).unwrap(); + let header = if height == 0 { + Header::genesis(&ratifications, &transactions, vec![]).unwrap() + } else { + let metadata = Metadata::new( + CurrentNetwork::ID, + u64::from(height) * 2, + height, + 0, + u128::from(height) * 1000, + CurrentNetwork::GENESIS_COINBASE_TARGET, + CurrentNetwork::GENESIS_PROOF_TARGET + 1, + CurrentNetwork::GENESIS_COINBASE_TARGET, + CurrentNetwork::GENESIS_TIMESTAMP + i64::from(height - 1) * 100, + CurrentNetwork::GENESIS_TIMESTAMP + i64::from(height) * 100, + ) + .unwrap(); + + Header::from( + rng.random(), + Field::from_u32(1), + Field::from_u32(1), + Field::from_u32(1), + Field::from_u32(1), + Field::from_u32(1), + metadata, + ) + .unwrap() + }; + let block_hash = Field::rand(rng); + let authority = Authority::new_beacon(&private_key, block_hash, rng).unwrap(); + let block = Block::from_unchecked( + block_hash.into(), + previous_hash, + header, + authority, + ratifications, + None.into(), + vec![], + transactions, + vec![], + ) + .unwrap(); + + previous_hash = block.hash(); + block + }) + .collect() + } + + #[cfg(any(not(feature = "history"), feature = "rocks"))] + fn sample_quorum_authority(rng: &mut TestRng) -> (Authority, Field) { + let author_private_key = PrivateKey::::new(rng).unwrap(); + let signer_private_key = PrivateKey::::new(rng).unwrap(); + let author = Address::try_from(&author_private_key).unwrap(); + let round = 2u64; + let timestamp = CurrentNetwork::GENESIS_TIMESTAMP; + let committee_id = Field::::rand(rng); + let previous_certificate_id = Field::::rand(rng); + + let mut preimage = Vec::new(); + author.write_le(&mut preimage).unwrap(); + round.write_le(&mut preimage).unwrap(); + timestamp.write_le(&mut preimage).unwrap(); + committee_id.write_le(&mut preimage).unwrap(); + 0u32.write_le(&mut preimage).unwrap(); + 1u32.write_le(&mut preimage).unwrap(); + previous_certificate_id.write_le(&mut preimage).unwrap(); + let batch_id = CurrentNetwork::hash_bhp1024(&preimage.to_bits_le()).unwrap(); + let author_signature = author_private_key.sign(&[batch_id], rng).unwrap(); + let signer_signature = signer_private_key.sign(&[batch_id], rng).unwrap(); + + let authority = serde_json::from_value(serde_json::json!({ + "type": "quorum", + "subdag": { + "subdag": { + "2": [{ + "batch_header": { + "batch_id": batch_id, + "author": author, + "round": round, + "timestamp": timestamp, + "committee_id": committee_id, + "transmission_ids": [], + "previous_certificate_ids": [previous_certificate_id], + "signature": author_signature, + }, + "signatures": [signer_signature], + }], + }, + }, + })) + .unwrap(); + + (authority, batch_id) + } + #[test] fn test_current_block_height_empty() { // Initialize a new block store. @@ -1637,6 +1918,339 @@ mod tests { assert_eq!(None, candidate); } + /// Ensures non-history stores prune authority data outside the retention window while preserving permanent block data. + #[cfg(not(feature = "history"))] + #[test] + fn test_authority_retention_without_history() { + const NUM_BLOCKS: u32 = 103; + + let rng = &mut TestRng::default(); + let blocks = sample_block_chain(NUM_BLOCKS, rng); + let block_store = BlockStore::>::open(StorageMode::new_test(None)).unwrap(); + + for block in blocks.iter().take(101) { + block_store.insert(block).unwrap(); + } + + let genesis_hash = blocks[0].hash(); + let expired_hash = blocks[1].hash(); + let boundary_hash = blocks[2].hash(); + + // At height 100, height 1 is still inside the retained window. + assert!(block_store.get_block_authority(&expired_hash).unwrap().is_some()); + + // At height 101, height 1 expires while height 2 remains retained. + block_store.insert(&blocks[101]).unwrap(); + + assert!(block_store.get_block_authority(&genesis_hash).unwrap().is_some()); + assert!(block_store.get_block_authority(&expired_hash).unwrap().is_none()); + assert!(block_store.get_block_authority(&boundary_hash).unwrap().is_some()); + assert!(block_store.get_block(&expired_hash).is_err()); + + // Permanent block data remains available. + assert_eq!(block_store.get_block_hash(1).unwrap(), Some(expired_hash)); + assert_eq!(block_store.get_block_header(&expired_hash).unwrap(), Some(*blocks[1].header())); + assert_eq!(block_store.get_block_transactions(&expired_hash).unwrap(), Some(blocks[1].transactions().clone())); + } + + /// Ensures history stores retain authority data and continue reconstructing old blocks. + #[cfg(feature = "history")] + #[test] + fn test_authority_retention_with_history() { + const NUM_BLOCKS: u32 = 103; + + let rng = &mut TestRng::default(); + let blocks = sample_block_chain(NUM_BLOCKS, rng); + let block_store = BlockStore::>::open(StorageMode::new_test(None)).unwrap(); + + for block in blocks.iter().take(102) { + block_store.insert(block).unwrap(); + } + + let expired_hash = blocks[1].hash(); + + // At height 101, height 1 is still inside the retained window. + assert!(block_store.get_block_authority(&expired_hash).unwrap().is_some()); + + // History builds retain height 1 after height 102 is inserted. + block_store.insert(&blocks[102]).unwrap(); + + assert!(block_store.get_block_authority(&expired_hash).unwrap().is_some()); + assert_eq!(block_store.get_block(&expired_hash).unwrap(), Some(blocks[1].clone())); + } + + /// Ensures pruning an expired quorum authority also removes its certificate indexes. + #[cfg(not(feature = "history"))] + #[test] + fn test_certificate_pruning() { + let rng = &mut TestRng::default(); + let (authority, certificate_id) = sample_quorum_authority(rng); + let mut blocks = sample_block_chain(103, rng); + blocks[1] = Block::from_unchecked( + blocks[1].hash(), + blocks[1].previous_hash(), + *blocks[1].header(), + authority, + blocks[1].ratifications().clone(), + blocks[1].solutions().clone(), + blocks[1].aborted_solution_ids().clone(), + blocks[1].transactions().clone(), + blocks[1].aborted_transaction_ids().clone(), + ) + .unwrap(); + + let block_store = BlockStore::>::open(StorageMode::new_test(None)).unwrap(); + for block in blocks.iter().take(101) { + block_store.insert(block).unwrap(); + } + + assert!(block_store.contains_certificate(&certificate_id).unwrap()); + assert!(block_store.get_batch_certificate(&certificate_id).unwrap().is_some()); + + block_store.insert(&blocks[101]).unwrap(); + + assert!(!block_store.contains_certificate(&certificate_id).unwrap()); + assert!(block_store.get_batch_certificate(&certificate_id).unwrap().is_none()); + assert!(block_store.get_block_authority(&blocks[1].hash()).unwrap().is_none()); + } + + /// Ensures a failed block insertion atomically rolls back authority and certificate pruning. + #[cfg(not(feature = "history"))] + #[test] + fn test_insertion_failure_rolls_back_authority_pruning() { + let rng = &mut TestRng::default(); + let (authority, certificate_id) = sample_quorum_authority(rng); + let mut blocks = sample_block_chain(103, rng); + blocks[1] = Block::from_unchecked( + blocks[1].hash(), + blocks[1].previous_hash(), + *blocks[1].header(), + authority, + blocks[1].ratifications().clone(), + blocks[1].solutions().clone(), + blocks[1].aborted_solution_ids().clone(), + blocks[1].transactions().clone(), + blocks[1].aborted_transaction_ids().clone(), + ) + .unwrap(); + + let storage = BlockMemory::::open(StorageMode::new_test(None)).unwrap(); + for block in blocks.iter().take(101) { + let state_root = ::StateRoot::from(Field::from_u32(block.height())); + storage.insert(state_root, block).unwrap(); + } + + let expired_hash = blocks[1].hash(); + let candidate = &blocks[101]; + let candidate_hash = candidate.hash(); + let candidate_state_root = ::StateRoot::from(Field::from_u32(candidate.height())); + let result: Result<()> = atomic_batch_scope!(storage, { + storage.insert(candidate_state_root, candidate)?; + bail!("Injected failure after block insertion") + }); + + assert!(result.is_err()); + assert!(storage.authority_map().contains_key_confirmed(&expired_hash).unwrap()); + assert!(storage.certificate_map().contains_key_confirmed(&certificate_id).unwrap()); + assert!(!storage.id_map().contains_key_confirmed(&candidate.height()).unwrap()); + assert!(!storage.reverse_id_map().contains_key_confirmed(&candidate_hash).unwrap()); + assert!(!storage.authority_map().contains_key_confirmed(&candidate_hash).unwrap()); + assert!(!storage.reverse_state_root_map().contains_key_confirmed(&candidate_state_root).unwrap()); + + storage.insert(candidate_state_root, candidate).unwrap(); + assert!(!storage.authority_map().contains_key_confirmed(&expired_hash).unwrap()); + assert!(!storage.certificate_map().contains_key_confirmed(&certificate_id).unwrap()); + assert!(storage.id_map().contains_key_confirmed(&candidate.height()).unwrap()); + } + + /// Ensures certificate pruning tolerates missing indexes and rejects indexes for a different block height. + #[cfg(not(feature = "history"))] + #[test] + fn test_certificate_pruning_handles_missing_and_mismatched_indexes() { + let rng = &mut TestRng::default(); + let (authority, certificate_id) = sample_quorum_authority(rng); + let storage = BlockMemory::::open(StorageMode::new_test(None)).unwrap(); + let block_hash: ::BlockHash = Field::::rand(rng).into(); + let block_height = 1; + + storage.authority_map().insert(block_hash, authority).unwrap(); + storage.certificate_map().insert(certificate_id, (block_height + 1, 2)).unwrap(); + + let error = prepare_authority_for_pruning(&storage, block_height, &block_hash).unwrap_err(); + assert!(error.to_string().contains("points to block '2' instead of block '1'")); + assert!(storage.authority_map().contains_key_confirmed(&block_hash).unwrap()); + + storage.certificate_map().remove(&certificate_id).unwrap(); + let certificate_ids = prepare_authority_for_pruning(&storage, block_height, &block_hash).unwrap().unwrap(); + assert_eq!(certificate_ids, vec![certificate_id]); + storage.authority_map().remove(&block_hash).unwrap(); + assert!(!storage.authority_map().contains_key_confirmed(&block_hash).unwrap()); + } + + #[cfg(not(feature = "history"))] + fn check_authority_pruning_uses_multiple_batches>(storage: B) { + let rng = &mut TestRng::default(); + let authority = sample_block_chain(1, rng)[0].authority().clone(); + let latest_height = u32::try_from(AUTHORITY_PRUNING_BATCH_SIZE).unwrap() + AUTHORITY_RETENTION_BLOCKS + 1; + + atomic_batch_scope!(storage, { + for height in 0..=latest_height { + let block_hash = ::BlockHash::from(Field::from_u32(height)); + storage.id_map().insert(height, block_hash)?; + storage.reverse_id_map().insert(block_hash, height)?; + storage.authority_map().insert(block_hash, authority.clone())?; + if height > 0 { + storage.certificate_map().insert(Field::from_u32(height), (height, u64::from(height)))?; + } + } + Ok(()) + }) + .unwrap(); + + prune_expired_authorities(&storage, latest_height).unwrap(); + + let oldest_retained_height = latest_height - (AUTHORITY_RETENTION_BLOCKS - 1); + let genesis_hash = ::BlockHash::from(Field::from_u32(0)); + let expired_hash = ::BlockHash::from(Field::from_u32(oldest_retained_height - 1)); + let oldest_retained_hash = + ::BlockHash::from(Field::from_u32(oldest_retained_height)); + assert!(storage.authority_map().contains_key_confirmed(&genesis_hash).unwrap()); + assert!(!storage.authority_map().contains_key_confirmed(&expired_hash).unwrap()); + assert!(storage.authority_map().contains_key_confirmed(&oldest_retained_hash).unwrap()); + assert_eq!(storage.authority_map().len_confirmed(), AUTHORITY_RETENTION_BLOCKS as usize + 1); + assert!( + !storage.certificate_map().contains_key_confirmed(&Field::from_u32(oldest_retained_height - 1)).unwrap() + ); + assert!(storage.certificate_map().contains_key_confirmed(&Field::from_u32(oldest_retained_height)).unwrap()); + assert_eq!(storage.certificate_map().len_confirmed(), AUTHORITY_RETENTION_BLOCKS as usize); + + // Repeating cleanup after multiple committed batches is idempotent. + prune_expired_authorities(&storage, latest_height).unwrap(); + assert_eq!(storage.authority_map().len_confirmed(), AUTHORITY_RETENTION_BLOCKS as usize + 1); + } + + /// Ensures startup pruning spans multiple batches and is idempotent with in-memory storage. + #[cfg(not(feature = "history"))] + #[test] + fn test_authority_pruning_uses_multiple_batches() { + let storage = BlockMemory::::open(StorageMode::new_test(None)).unwrap(); + check_authority_pruning_uses_multiple_batches(storage); + } + + /// Ensures startup pruning spans multiple batches and is idempotent with RocksDB storage. + #[cfg(all(not(feature = "history"), feature = "rocks"))] + #[test] + fn test_authority_pruning_uses_multiple_rocksdb_batches() { + let temp_dir = Arc::new(tempfile::tempdir().unwrap()); + let storage = BlockDB::::open(StorageMode::new_test(Some(temp_dir))).unwrap(); + check_authority_pruning_uses_multiple_batches(storage); + } + + /// Ensures opening a non-history RocksDB store removes stale authority and certificate data. + #[cfg(all(feature = "rocks", not(feature = "history")))] + #[test] + fn test_authority_pruning_on_startup_without_history() { + let rng = &mut TestRng::default(); + let (authority, certificate_id) = sample_quorum_authority(rng); + let mut blocks = sample_block_chain(103, rng); + blocks[1] = Block::from_unchecked( + blocks[1].hash(), + blocks[1].previous_hash(), + *blocks[1].header(), + authority, + blocks[1].ratifications().clone(), + blocks[1].solutions().clone(), + blocks[1].aborted_solution_ids().clone(), + blocks[1].transactions().clone(), + blocks[1].aborted_transaction_ids().clone(), + ) + .unwrap(); + + let temp_dir = Arc::new(tempfile::tempdir().unwrap()); + let storage_mode = StorageMode::new_test(Some(temp_dir)); + let block_store = BlockStore::>::open(storage_mode.clone()).unwrap(); + for block in &blocks { + block_store.insert(block).unwrap(); + } + + assert!(block_store.get_block_authority(&blocks[1].hash()).unwrap().is_none()); + assert!(!block_store.contains_certificate(&certificate_id).unwrap()); + + // Restore stale authority data to emulate opening a database created before pruning. + block_store.storage.authority_map().insert(blocks[1].hash(), blocks[1].authority().clone()).unwrap(); + block_store.storage.certificate_map().insert(certificate_id, (1, 2)).unwrap(); + drop(block_store); + + let block_store = BlockStore::>::open(storage_mode.clone()).unwrap(); + assert!(block_store.get_block_authority(&blocks[1].hash()).unwrap().is_none()); + assert!(!block_store.contains_certificate(&certificate_id).unwrap()); + drop(block_store); + + // Reopening after cleanup is idempotent. + let block_store = BlockStore::>::open(storage_mode).unwrap(); + assert!(block_store.get_block_authority(&blocks[1].hash()).unwrap().is_none()); + assert!(!block_store.contains_certificate(&certificate_id).unwrap()); + } + + /// Ensures opening a history-enabled RocksDB store preserves authority and certificate data. + #[cfg(all(feature = "rocks", feature = "history"))] + #[test] + fn test_authority_pruning_on_startup_with_history() { + let rng = &mut TestRng::default(); + let (authority, certificate_id) = sample_quorum_authority(rng); + let mut blocks = sample_block_chain(103, rng); + blocks[1] = Block::from_unchecked( + blocks[1].hash(), + blocks[1].previous_hash(), + *blocks[1].header(), + authority, + blocks[1].ratifications().clone(), + blocks[1].solutions().clone(), + blocks[1].aborted_solution_ids().clone(), + blocks[1].transactions().clone(), + blocks[1].aborted_transaction_ids().clone(), + ) + .unwrap(); + + let temp_dir = Arc::new(tempfile::tempdir().unwrap()); + let storage_mode = StorageMode::new_test(Some(temp_dir)); + let block_store = BlockStore::>::open(storage_mode.clone()).unwrap(); + for block in &blocks { + block_store.insert(block).unwrap(); + } + + assert!(block_store.get_block_authority(&blocks[1].hash()).unwrap().is_some()); + assert!(block_store.contains_certificate(&certificate_id).unwrap()); + drop(block_store); + + let block_store = BlockStore::>::open(storage_mode.clone()).unwrap(); + assert!(block_store.get_block_authority(&blocks[1].hash()).unwrap().is_some()); + assert!(block_store.contains_certificate(&certificate_id).unwrap()); + drop(block_store); + + // Reopening with history remains idempotent. + let block_store = BlockStore::>::open(storage_mode).unwrap(); + assert!(block_store.get_block_authority(&blocks[1].hash()).unwrap().is_some()); + assert!(block_store.contains_certificate(&certificate_id).unwrap()); + } + + /// Ensures state paths remain available after the corresponding block authority is removed. + #[test] + fn test_state_path_does_not_require_authority() { + let rng = &mut TestRng::default(); + let block = snarkvm_ledger_test_helpers::sample_genesis_block(rng); + let block_hash = block.hash(); + let commitment = *block.transactions().commitments().next().unwrap(); + let block_store = BlockStore::>::open(StorageMode::new_test(None)).unwrap(); + + block_store.insert(&block).unwrap(); + let expected = block_store.get_state_path_for_commitment(&commitment).unwrap(); + + block_store.storage.authority_map().remove(&block_hash).unwrap(); + assert!(block_store.get_block(&block_hash).is_err()); + assert_eq!(block_store.get_state_path_for_commitment(&commitment).unwrap(), expected); + } + #[test] fn test_find_block_hash() { let rng = &mut TestRng::default(); diff --git a/ledger/test-helpers/Cargo.toml b/ledger/test-helpers/Cargo.toml index 34f4de2165..3686054614 100644 --- a/ledger/test-helpers/Cargo.toml +++ b/ledger/test-helpers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-ledger-test-helpers" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Test helpers for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/metrics/Cargo.toml b/metrics/Cargo.toml index 8a70fe2fbf..c2bc95e01f 100644 --- a/metrics/Cargo.toml +++ b/metrics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-metrics" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Metrics for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/parameters/Cargo.toml b/parameters/Cargo.toml index b9c8accdfb..7ab7951dc6 100644 --- a/parameters/Cargo.toml +++ b/parameters/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-parameters" -version = "4.8.1" +version = "4.9.0" authors = ["The Aleo Team "] description = "Parameters for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/plugins/slipstream_plugin_interface/Cargo.toml b/plugins/slipstream_plugin_interface/Cargo.toml index f5dfb50533..9dc4a1a63f 100644 --- a/plugins/slipstream_plugin_interface/Cargo.toml +++ b/plugins/slipstream_plugin_interface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-slipstream-plugin-interface" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "The SnarkVM Slipstream plugin interface." homepage = "https://aleo.org" diff --git a/plugins/slipstream_plugin_manager/Cargo.toml b/plugins/slipstream_plugin_manager/Cargo.toml index 09c4e3f0c3..632d90e45c 100644 --- a/plugins/slipstream_plugin_manager/Cargo.toml +++ b/plugins/slipstream_plugin_manager/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-slipstream-plugin-manager" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "The SnarkVM Slipstream plugin manager." homepage = "https://aleo.org" diff --git a/synthesizer/Cargo.toml b/synthesizer/Cargo.toml index ae464c96f3..431c5c70bb 100644 --- a/synthesizer/Cargo.toml +++ b/synthesizer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-synthesizer" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Synthesizer for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/synthesizer/error/Cargo.toml b/synthesizer/error/Cargo.toml index b00b8f6f05..b8c42092a0 100644 --- a/synthesizer/error/Cargo.toml +++ b/synthesizer/error/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-synthesizer-error" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "A decentralized virtual machine" homepage = "https://aleo.org" diff --git a/synthesizer/process/Cargo.toml b/synthesizer/process/Cargo.toml index 12cc15f2c6..f5a8f9f880 100644 --- a/synthesizer/process/Cargo.toml +++ b/synthesizer/process/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-synthesizer-process" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "A process for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/synthesizer/program/Cargo.toml b/synthesizer/program/Cargo.toml index 5efa881bbe..4eb89abd40 100644 --- a/synthesizer/program/Cargo.toml +++ b/synthesizer/program/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-synthesizer-program" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Program for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/synthesizer/snark/Cargo.toml b/synthesizer/snark/Cargo.toml index 6ab207d855..bd52953ad6 100644 --- a/synthesizer/snark/Cargo.toml +++ b/synthesizer/snark/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-synthesizer-snark" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "SNARK wrappers for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/utilities/Cargo.toml b/utilities/Cargo.toml index 753491f12c..793a8af9eb 100644 --- a/utilities/Cargo.toml +++ b/utilities/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-utilities" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Utilities for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/utilities/derives/Cargo.toml b/utilities/derives/Cargo.toml index 82868e89fe..d45f06c009 100644 --- a/utilities/derives/Cargo.toml +++ b/utilities/derives/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-utilities-derives" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "Canonical serialization for a decentralized virtual machine" homepage = "https://aleo.org" diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index 0c35d062cf..6c7c145d32 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snarkvm-wasm" -version = "4.8.1" +version = "4.9.0" authors = [ "The Aleo Team " ] description = "WASM for a decentralized virtual machine" homepage = "https://aleo.org"