Skip to content

Conversation

@wqfish
Copy link
Contributor

@wqfish wqfish commented Dec 23, 2025

In order to compute the hot state root hash for each block (including the
speculative ones), we have to be able to return Merkle proof for any given key
and version. The most straightforward way to do this is to add another instance
of StateMerkleDb in StateStore.

For now, we always delete and reset the DB on restart. This will give us more
flexibility to make changes.


Note

Adds a hot-state storage path to enable Merkle proofs for speculative blocks.

  • Introduces optional hot_state_merkle_db in AptosDB/StateStore; proof APIs now take use_hot_state to read from hot or regular state
  • Extends StateMerkleDb to support hot vs. regular instances (separate folder/CF names), deletion-on-restart, and checkpointing for both
  • Configuration: new HotStateConfig { max_items_per_shard, delete_on_restart }, path overrides for hot_state_merkle_db, and StorageDirPaths getters
  • AptosDB::open/open_internal/open_dbs gain reset_hot_state and return the optional hot DB; all call sites updated (genesis, tests, benchmarks, tools)
  • Storage interface and mocks updated (add use_hot_state params); new HotStateError for missing/misconfigured hot state
  • DB debugger and truncate tools updated to handle new DB shape; default test/bench runners reset hot state on open

Written by Cursor Bugbot for commit 97680f2. This will update automatically on new commits. Configure here.

@wqfish wqfish force-pushed the pr18385 branch 3 times, most recently from e43e00d to bf1a4dd Compare December 24, 2025 00:08
@wqfish wqfish changed the title [Hot State] Add separate StateMerkleDb for hot state [Hot State] Add a separate StateMerkleDb for hot state Dec 24, 2025
@wqfish wqfish force-pushed the pr18385 branch 2 times, most recently from e92b3e4 to 6c89feb Compare December 24, 2025 00:32
@wqfish wqfish marked this pull request as ready for review December 24, 2025 00:33
@wqfish wqfish requested a review from zekun000 December 24, 2025 00:33
@wqfish wqfish added the CICD:run-e2e-tests when this label is present github actions will run all land-blocking e2e tests from the PR label Dec 27, 2025
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

This part of the config is exposed via the `get_dir_paths` API.
@wqfish wqfish force-pushed the pr18385 branch 2 times, most recently from 375c1a9 to 19548d3 Compare January 8, 2026 04:38
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

In order to compute the hot state root hash for each block (including the
speculative ones), we have to be able to return Merkle proof for any given key
and version. The most straightforward way to do this is to add another instance
of `StateMerkleDb` in `StateStore`.

For now, we always delete and reset the DB on restart. This will give us more
flexibility to make changes.
@wqfish wqfish enabled auto-merge (rebase) January 8, 2026 05:16
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 8, 2026

✅ Forge suite realistic_env_max_load success on 97680f2cb8cc28da7b2e71dc533a960114048624

two traffics test: inner traffic : committed: 13526.98 txn/s, latency: 2788.92 ms, (p50: 2700 ms, p70: 3000, p90: 3100 ms, p99: 3600 ms), latency samples: 5038880
two traffics test : committed: 100.00 txn/s, latency: 754.34 ms, (p50: 700 ms, p70: 800, p90: 800 ms, p99: 1200 ms), latency samples: 1700
Latency breakdown for phase 0: ["MempoolToBlockCreation: max: 2.302, avg: 2.197", "ConsensusProposalToOrdered: max: 0.168, avg: 0.166", "ConsensusOrderedToCommit: max: 0.046, avg: 0.042", "ConsensusProposalToCommit: max: 0.213, avg: 0.208"]
Max non-epoch-change gap was: 0 rounds at version 0 (avg 0.00) [limit 4], 0.43s no progress at version 5773192 (avg 0.07s) [limit 15].
Max epoch-change gap was: 0 rounds at version 0 (avg 0.00) [limit 4], 0.27s no progress at version 2433051 (avg 0.27s) [limit 16].
Test Ok

@github-actions
Copy link
Contributor

github-actions bot commented Jan 8, 2026

✅ Forge suite compat success on a09bb94430a970de7bc45fe0d29bd33fd2e5a7d4 ==> 97680f2cb8cc28da7b2e71dc533a960114048624

Compatibility test results for a09bb94430a970de7bc45fe0d29bd33fd2e5a7d4 ==> 97680f2cb8cc28da7b2e71dc533a960114048624 (PR)
1. Check liveness of validators at old version: a09bb94430a970de7bc45fe0d29bd33fd2e5a7d4
compatibility::simple-validator-upgrade::liveness-check : committed: 9915.40 txn/s, latency: 3643.75 ms, (p50: 2800 ms, p70: 3000, p90: 3600 ms, p99: 13300 ms), latency samples: 418140
2. Upgrading first Validator to new version: 97680f2cb8cc28da7b2e71dc533a960114048624
compatibility::simple-validator-upgrade::single-validator-upgrade : committed: 5948.29 txn/s, latency: 5682.05 ms, (p50: 6200 ms, p70: 6400, p90: 6500 ms, p99: 6800 ms), latency samples: 208040
3. Upgrading rest of first batch to new version: 97680f2cb8cc28da7b2e71dc533a960114048624
compatibility::simple-validator-upgrade::half-validator-upgrade : committed: 5837.77 txn/s, latency: 5774.56 ms, (p50: 6400 ms, p70: 6500, p90: 6600 ms, p99: 6700 ms), latency samples: 200720
4. upgrading second batch to new version: 97680f2cb8cc28da7b2e71dc533a960114048624
compatibility::simple-validator-upgrade::rest-validator-upgrade : committed: 10038.49 txn/s, latency: 3278.13 ms, (p50: 3100 ms, p70: 3800, p90: 4600 ms, p99: 5100 ms), latency samples: 332520
5. check swarm health
Compatibility test for a09bb94430a970de7bc45fe0d29bd33fd2e5a7d4 ==> 97680f2cb8cc28da7b2e71dc533a960114048624 passed
Test Ok

@github-actions
Copy link
Contributor

github-actions bot commented Jan 8, 2026

✅ Forge suite framework_upgrade success on a09bb94430a970de7bc45fe0d29bd33fd2e5a7d4 ==> 97680f2cb8cc28da7b2e71dc533a960114048624

Compatibility test results for a09bb94430a970de7bc45fe0d29bd33fd2e5a7d4 ==> 97680f2cb8cc28da7b2e71dc533a960114048624 (PR)
Upgrade the nodes to version: 97680f2cb8cc28da7b2e71dc533a960114048624
framework_upgrade::framework-upgrade::full-framework-upgrade : committed: 2172.24 txn/s, submitted: 2179.75 txn/s, failed submission: 7.51 txn/s, expired: 7.51 txn/s, latency: 1342.24 ms, (p50: 1200 ms, p70: 1500, p90: 1800 ms, p99: 2400 ms), latency samples: 196760
framework_upgrade::framework-upgrade::full-framework-upgrade : committed: 2186.62 txn/s, submitted: 2193.15 txn/s, failed submission: 6.52 txn/s, expired: 6.52 txn/s, latency: 1353.69 ms, (p50: 1200 ms, p70: 1500, p90: 1800 ms, p99: 2700 ms), latency samples: 194400
5. check swarm health
Compatibility test for a09bb94430a970de7bc45fe0d29bd33fd2e5a7d4 ==> 97680f2cb8cc28da7b2e71dc533a960114048624 passed
Upgrade the remaining nodes to version: 97680f2cb8cc28da7b2e71dc533a960114048624
framework_upgrade::framework-upgrade::full-framework-upgrade : committed: 2334.28 txn/s, submitted: 2343.07 txn/s, failed submission: 8.79 txn/s, expired: 8.79 txn/s, latency: 1253.84 ms, (p50: 1200 ms, p70: 1500, p90: 1700 ms, p99: 2100 ms), latency samples: 212461
Test Ok

@wqfish wqfish merged commit 5524f4d into main Jan 8, 2026
101 of 104 checks passed
@wqfish wqfish deleted the pr18385 branch January 8, 2026 06:05
wqfish added a commit that referenced this pull request Jan 8, 2026
This commit implements the logic to compute root hashes for hot state. It's an initial version with a number of TODO items, but it's a reasonable start. Most of the logic is gated behind a flag so we are not enabling this in mainnet yet, until we run things in testnet for some time and gain more confidence.

How this roughly works:
- `State::update` computes the changes to hot state. They are saved in `ExecutionOutput`.
- The above changes are passed to `StateSummary::update` and used to compute in-memory `SparseMerkleTree`.
- The resulting Merkle trees are committed to persisted database (`hot_state_merkle_db` introduced in #18385) so the proofs can be used in turn for future `StateSummary::update`.
wqfish added a commit that referenced this pull request Jan 8, 2026
This commit implements the logic to compute root hashes for hot state. It's an initial version with a number of TODO items, but it's a reasonable start. Most of the logic is gated behind a flag so we are not enabling this in mainnet yet, until we run things in testnet for some time and gain more confidence.

How this roughly works:
- `State::update` computes the changes to hot state. They are saved in `ExecutionOutput`.
- The above changes are passed to `StateSummary::update` and used to compute in-memory `SparseMerkleTree`.
- The resulting Merkle trees are committed to persisted database (`hot_state_merkle_db` introduced in #18385) so the proofs can be used in turn for future `StateSummary::update`.
wqfish added a commit that referenced this pull request Jan 8, 2026
This commit implements the logic to compute root hashes for hot state. It's an initial version with a number of TODO items, but it's a reasonable start. Most of the logic is gated behind a flag so we are not enabling this in mainnet yet, until we run things in testnet for some time and gain more confidence.

How this roughly works:
- `State::update` computes the changes to hot state. They are saved in `ExecutionOutput`.
- The above changes are passed to `StateSummary::update` and used to compute in-memory `SparseMerkleTree`.
- The resulting Merkle trees are committed to persisted database (`hot_state_merkle_db` introduced in #18385) so the proofs can be used in turn for future `StateSummary::update`.
wqfish added a commit that referenced this pull request Jan 8, 2026
This commit implements the logic to compute root hashes for hot state. It's an initial version with a number of TODO items, but it's a reasonable start. Most of the logic is gated behind a flag so we are not enabling this in mainnet yet, until we run things in testnet for some time and gain more confidence.

How this roughly works:
- `State::update` computes the changes to hot state. They are saved in `ExecutionOutput`.
- The above changes are passed to `StateSummary::update` and used to compute in-memory `SparseMerkleTree`.
- The resulting Merkle trees are committed to persisted database (`hot_state_merkle_db` introduced in #18385) so the proofs can be used in turn for future `StateSummary::update`.
wqfish added a commit that referenced this pull request Jan 8, 2026
This commit implements the logic to compute root hashes for hot state. It's an initial version with a number of TODO items, but it's a reasonable start. Most of the logic is gated behind a flag so we are not enabling this in mainnet yet, until we run things in testnet for some time and gain more confidence.

How this roughly works:
- `State::update` computes the changes to hot state. They are saved in `ExecutionOutput`.
- The above changes are passed to `StateSummary::update` and used to compute in-memory `SparseMerkleTree`.
- The resulting Merkle trees are committed to persisted database (`hot_state_merkle_db` introduced in #18385) so the proofs can be used in turn for future `StateSummary::update`.
wqfish added a commit that referenced this pull request Jan 8, 2026
This commit implements the logic to compute root hashes for hot state. It's an initial version with a number of TODO items, but it's a reasonable start. Most of the logic is gated behind a flag so we are not enabling this in mainnet yet, until we run things in testnet for some time and gain more confidence.

How this roughly works:
- `State::update` computes the changes to hot state. They are saved in `ExecutionOutput`.
- The above changes are passed to `StateSummary::update` and used to compute in-memory `SparseMerkleTree`.
- The resulting Merkle trees are committed to persisted database (`hot_state_merkle_db` introduced in #18385) so the proofs can be used in turn for future `StateSummary::update`.
wqfish added a commit that referenced this pull request Jan 8, 2026
This commit implements the logic to compute root hashes for hot state. It's an initial version with a number of TODO items, but it's a reasonable start. Most of the logic is gated behind a flag so we are not enabling this in mainnet yet, until we run things in testnet for some time and gain more confidence.

How this roughly works:
- `State::update` computes the changes to hot state. They are saved in `ExecutionOutput`.
- The above changes are passed to `StateSummary::update` and used to compute in-memory `SparseMerkleTree`.
- The resulting Merkle trees are committed to persisted database (`hot_state_merkle_db` introduced in #18385) so the proofs can be used in turn for future `StateSummary::update`.
wqfish added a commit that referenced this pull request Jan 8, 2026
This commit implements the logic to compute root hashes for hot state. It's an initial version with a number of TODO items, but it's a reasonable start. Most of the logic is gated behind a flag so we are not enabling this in mainnet yet, until we run things in testnet for some time and gain more confidence.

How this roughly works:
- `State::update` computes the changes to hot state. They are saved in `ExecutionOutput`.
- The above changes are passed to `StateSummary::update` and used to compute in-memory `SparseMerkleTree`.
- The resulting Merkle trees are committed to persisted database (`hot_state_merkle_db` introduced in #18385) so the proofs can be used in turn for future `StateSummary::update`.
wqfish added a commit that referenced this pull request Jan 8, 2026
This commit implements the logic to compute root hashes for hot state. It's an initial version with a number of TODO items, but it's a reasonable start. Most of the logic is gated behind a flag so we are not enabling this in mainnet yet, until we run things in testnet for some time and gain more confidence.

How this roughly works:
- `State::update` computes the changes to hot state. They are saved in `ExecutionOutput`.
- The above changes are passed to `StateSummary::update` and used to compute in-memory `SparseMerkleTree`.
- The resulting Merkle trees are committed to persisted database (`hot_state_merkle_db` introduced in #18385) so the proofs can be used in turn for future `StateSummary::update`.
wqfish added a commit that referenced this pull request Jan 11, 2026
This commit implements the logic to compute root hashes for hot state. It's an initial version with a number of TODO items, but it's a reasonable start. Most of the logic is gated behind a flag so we are not enabling this in mainnet yet, until we run things in testnet for some time and gain more confidence.

How this roughly works:
- `State::update` computes the changes to hot state. They are saved in `ExecutionOutput`.
- The above changes are passed to `StateSummary::update` and used to compute in-memory `SparseMerkleTree`.
- The resulting Merkle trees are committed to persisted database (`hot_state_merkle_db` introduced in #18385) so the proofs can be used in turn for future `StateSummary::update`.
wqfish added a commit that referenced this pull request Jan 11, 2026
This commit implements the logic to compute root hashes for hot state. It's an initial version with a number of TODO items, but it's a reasonable start. Most of the logic is gated behind a flag so we are not enabling this in mainnet yet, until we run things in testnet for some time and gain more confidence.

How this roughly works:
- `State::update` computes the changes to hot state. They are saved in `ExecutionOutput`.
- The above changes are passed to `StateSummary::update` and used to compute in-memory `SparseMerkleTree`.
- The resulting Merkle trees are committed to persisted database (`hot_state_merkle_db` introduced in #18385) so the proofs can be used in turn for future `StateSummary::update`.
wqfish added a commit that referenced this pull request Jan 14, 2026
This commit implements the logic to compute root hashes for hot state. It's an initial version with a number of TODO items, but it's a reasonable start. Most of the logic is gated behind a flag so we are not enabling this in mainnet yet, until we run things in testnet for some time and gain more confidence.

How this roughly works:
- `State::update` computes the changes to hot state. They are saved in `ExecutionOutput`.
- The above changes are passed to `StateSummary::update` and used to compute in-memory `SparseMerkleTree`.
- The resulting Merkle trees are committed to persisted database (`hot_state_merkle_db` introduced in #18385) so the proofs can be used in turn for future `StateSummary::update`.
wqfish added a commit that referenced this pull request Jan 14, 2026
This commit implements the logic to compute root hashes for hot state. It's an initial version with a number of TODO items, but it's a reasonable start. Most of the logic is gated behind a flag so we are not enabling this in mainnet yet, until we run things in testnet for some time and gain more confidence.

How this roughly works:
- `State::update` computes the changes to hot state. They are saved in `ExecutionOutput`.
- The above changes are passed to `StateSummary::update` and used to compute in-memory `SparseMerkleTree`.
- The resulting Merkle trees are committed to persisted database (`hot_state_merkle_db` introduced in #18385) so the proofs can be used in turn for future `StateSummary::update`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD:run-e2e-tests when this label is present github actions will run all land-blocking e2e tests from the PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants