Skip to content

Commit 7e7f2f0

Browse files
committed
[Hot State] Compute root hash for hot state
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`.
1 parent 7b8a45e commit 7e7f2f0

File tree

34 files changed

+606
-245
lines changed

34 files changed

+606
-245
lines changed

api/test-context/src/test_context.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ use aptos_api_types::{
1010
use aptos_cached_packages::aptos_stdlib;
1111
use aptos_config::{
1212
config::{
13-
NodeConfig, RocksdbConfigs, StorageDirPaths, BUFFERED_STATE_TARGET_ITEMS_FOR_TEST,
14-
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, NO_OP_STORAGE_PRUNER_CONFIG,
13+
HotStateConfig, NodeConfig, RocksdbConfigs, StorageDirPaths,
14+
BUFFERED_STATE_TARGET_ITEMS_FOR_TEST, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD,
15+
NO_OP_STORAGE_PRUNER_CONFIG,
1516
},
1617
keys::ConfigKey,
1718
};
@@ -176,7 +177,7 @@ pub fn new_test_context_inner(
176177
BUFFERED_STATE_TARGET_ITEMS_FOR_TEST,
177178
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD,
178179
None,
179-
/* reset_hot_state = */ true,
180+
HotStateConfig::default(),
180181
)
181182
.unwrap();
182183
if node_config

aptos-move/aptos-validator-interface/src/storage_interface.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use crate::{AptosValidatorInterface, FilterCondition};
55
use anyhow::{ensure, Result};
66
use aptos_config::config::{
7-
RocksdbConfigs, StorageDirPaths, BUFFERED_STATE_TARGET_ITEMS,
7+
HotStateConfig, RocksdbConfigs, StorageDirPaths, BUFFERED_STATE_TARGET_ITEMS,
88
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, NO_OP_STORAGE_PRUNER_CONFIG,
99
};
1010
use aptos_db::AptosDB;
@@ -32,7 +32,10 @@ impl DBDebuggerInterface {
3232
BUFFERED_STATE_TARGET_ITEMS,
3333
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD,
3434
/* internal_indexer_db = */ None,
35-
/* reset_hot_state = */ false,
35+
HotStateConfig {
36+
delete_on_restart: false,
37+
..Default::default()
38+
},
3639
)
3740
.map_err(anyhow::Error::from)?,
3841
)))

config/src/config/storage_config.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,13 +245,17 @@ pub struct HotStateConfig {
245245
pub max_items_per_shard: usize,
246246
/// Whether to delete persisted data on disk on restart. Used during development.
247247
pub delete_on_restart: bool,
248+
/// Whether we compute root hashes for hot state in executor and commit the resulting JMT to
249+
/// db.
250+
pub compute_root_hash: bool,
248251
}
249252

250253
impl Default for HotStateConfig {
251254
fn default() -> Self {
252255
Self {
253256
max_items_per_shard: 250_000,
254257
delete_on_restart: true,
258+
compute_root_hash: true,
255259
}
256260
}
257261
}
@@ -658,6 +662,13 @@ impl ConfigOptimizer for StorageConfig {
658662
{
659663
panic!("Storage sharding (AIP-97) is not enabled in node config. Please follow the guide to migration your node, and set storage.rocksdb_configs.enable_storage_sharding to true explicitly in your node config. https://aptoslabs.notion.site/DB-Sharding-Migration-Public-Full-Nodes-1978b846eb7280b29f17ceee7d480730");
660664
}
665+
// TODO(HotState): Hot state root hash computation is off by default in Mainnet unless
666+
// explicitly enabled.
667+
if chain_id.is_mainnet()
668+
&& config_yaml["hot_state_config"]["compute_root_hash"].as_bool() != Some(true)
669+
{
670+
config.hot_state_config.compute_root_hash = false;
671+
}
661672
}
662673

663674
Ok(modified_config)

crates/aptos-genesis/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub mod test_utils;
1313

1414
use crate::{builder::GenesisConfiguration, config::ValidatorConfiguration};
1515
use aptos_config::config::{
16-
RocksdbConfigs, StorageDirPaths, BUFFERED_STATE_TARGET_ITEMS,
16+
HotStateConfig, RocksdbConfigs, StorageDirPaths, BUFFERED_STATE_TARGET_ITEMS,
1717
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, NO_OP_STORAGE_PRUNER_CONFIG,
1818
};
1919
use aptos_crypto::ed25519::Ed25519PublicKey;
@@ -177,7 +177,7 @@ impl GenesisInfo {
177177
BUFFERED_STATE_TARGET_ITEMS,
178178
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD,
179179
/* internal_indexer_db = */ None,
180-
/* reset_hot_state = */ true,
180+
HotStateConfig::default(),
181181
)?;
182182
let db_rw = DbReaderWriter::new(aptosdb);
183183
aptos_executor::db_bootstrapper::generate_waypoint::<AptosVMBlockExecutor>(&db_rw, genesis)

crates/aptos-genesis/src/mainnet.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use crate::{builder::GenesisConfiguration, config::ValidatorConfiguration};
55
use aptos_config::config::{
6-
RocksdbConfigs, StorageDirPaths, BUFFERED_STATE_TARGET_ITEMS,
6+
HotStateConfig, RocksdbConfigs, StorageDirPaths, BUFFERED_STATE_TARGET_ITEMS,
77
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, NO_OP_STORAGE_PRUNER_CONFIG,
88
};
99
use aptos_db::AptosDB;
@@ -161,7 +161,7 @@ impl MainnetGenesisInfo {
161161
BUFFERED_STATE_TARGET_ITEMS,
162162
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD,
163163
/* internal_indexer_db = */ None,
164-
/* reset_hot_state = */ true,
164+
HotStateConfig::default(),
165165
)?;
166166
let db_rw = DbReaderWriter::new(aptosdb);
167167
aptos_executor::db_bootstrapper::generate_waypoint::<AptosVMBlockExecutor>(&db_rw, genesis)

execution/executor-benchmark/src/db_generator.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use crate::{add_accounts_impl, PipelineConfig, StorageTestConfig};
55
use aptos_config::{
66
config::{
7-
RocksdbConfigs, StorageDirPaths, BUFFERED_STATE_TARGET_ITEMS,
7+
HotStateConfig, RocksdbConfigs, StorageDirPaths, BUFFERED_STATE_TARGET_ITEMS,
88
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, NO_OP_STORAGE_PRUNER_CONFIG,
99
},
1010
utils::get_genesis_txn,
@@ -104,7 +104,7 @@ pub(crate) fn bootstrap_with_genesis(
104104
BUFFERED_STATE_TARGET_ITEMS,
105105
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD,
106106
None, /* internal_indexer_db */
107-
true, /* reset_hot_state */
107+
HotStateConfig::default(),
108108
)
109109
.expect("DB should open."),
110110
);

execution/executor-benchmark/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ use crate::{
2525
};
2626
use aptos_api::context::Context;
2727
use aptos_config::config::{
28-
get_default_processor_task_count, NodeConfig, PrunerConfig, NO_OP_STORAGE_PRUNER_CONFIG,
28+
get_default_processor_task_count, HotStateConfig, NodeConfig, PrunerConfig,
29+
NO_OP_STORAGE_PRUNER_CONFIG,
2930
};
3031
use aptos_db::AptosDB;
3132
use aptos_db_indexer::{db_ops::open_db, db_v2::IndexerAsyncV2, indexer_reader::IndexerReaders};
@@ -117,7 +118,7 @@ pub fn init_db(config: &NodeConfig) -> DbReaderWriter {
117118
config.storage.buffered_state_target_items,
118119
config.storage.max_num_nodes_per_lru_cache_shard,
119120
None,
120-
/* reset_hot_state = */ true,
121+
HotStateConfig::default(),
121122
)
122123
.expect("DB should open."),
123124
)

execution/executor-types/src/execution_output.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
use aptos_config::config::HotStateConfig;
1111
use aptos_drop_helper::DropHelper;
1212
use aptos_storage_interface::state_store::{
13-
state::LedgerState, state_view::cached_state_view::ShardedStateCache,
13+
state::LedgerState, state_view::cached_state_view::ShardedStateCache, HotStateUpdates,
1414
};
1515
use aptos_types::{
1616
contract_event::ContractEvent,
@@ -38,6 +38,7 @@ impl ExecutionOutput {
3838
to_retry: TransactionsWithOutput,
3939
result_state: LedgerState,
4040
state_reads: ShardedStateCache,
41+
hot_state_updates: HotStateUpdates,
4142
block_end_info: Option<BlockEndInfo>,
4243
next_epoch_state: Option<EpochState>,
4344
subscribable_events: Planned<Vec<ContractEvent>>,
@@ -62,6 +63,7 @@ impl ExecutionOutput {
6263
to_retry,
6364
result_state,
6465
state_reads,
66+
hot_state_updates,
6567
block_end_info,
6668
next_epoch_state,
6769
subscribable_events,
@@ -78,6 +80,7 @@ impl ExecutionOutput {
7880
to_retry: TransactionsWithOutput::new_empty(),
7981
state_reads: ShardedStateCache::new_empty(state.version()),
8082
result_state: state,
83+
hot_state_updates: HotStateUpdates::new_empty(),
8184
block_end_info: None,
8285
next_epoch_state: None,
8386
subscribable_events: Planned::ready(vec![]),
@@ -96,6 +99,7 @@ impl ExecutionOutput {
9699
to_retry: TransactionsWithOutput::new_empty(),
97100
result_state: LedgerState::new_empty(HotStateConfig::default()),
98101
state_reads: ShardedStateCache::new_empty(None),
102+
hot_state_updates: HotStateUpdates::new_empty(),
99103
block_end_info: None,
100104
next_epoch_state: None,
101105
subscribable_events: Planned::ready(vec![]),
@@ -116,6 +120,7 @@ impl ExecutionOutput {
116120
to_retry: TransactionsWithOutput::new_empty(),
117121
result_state: self.result_state.clone(),
118122
state_reads: ShardedStateCache::new_empty(self.next_version().checked_sub(1)),
123+
hot_state_updates: HotStateUpdates::new_empty(),
119124
block_end_info: None,
120125
next_epoch_state: self.next_epoch_state.clone(),
121126
subscribable_events: Planned::ready(vec![]),
@@ -158,6 +163,8 @@ pub struct Inner {
158163
/// State items read during execution, useful for calculating the state storge usage and
159164
/// indices used by the db pruner.
160165
pub state_reads: ShardedStateCache,
166+
/// Updates to hot state, mainly used to compute hot state root hashes.
167+
pub hot_state_updates: HotStateUpdates,
161168

162169
/// Optional StateCheckpoint payload
163170
pub block_end_info: Option<BlockEndInfo>,

execution/executor-types/src/state_checkpoint_output.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#![forbid(unsafe_code)]
55

6+
use aptos_config::config::HotStateConfig;
67
use aptos_crypto::HashValue;
78
use aptos_drop_helper::DropHelper;
89
use aptos_storage_interface::state_store::state_summary::LedgerStateSummary;
@@ -34,7 +35,7 @@ impl StateCheckpointOutput {
3435
}
3536

3637
pub fn new_dummy() -> Self {
37-
Self::new_empty(LedgerStateSummary::new_empty())
38+
Self::new_empty(LedgerStateSummary::new_empty(HotStateConfig::default()))
3839
}
3940

4041
fn new_impl(inner: Inner) -> Self {

execution/executor/src/workflow/do_get_execution_output.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ impl Parser {
417417
},
418418
)?;
419419

420-
let result_state = parent_state.update_with_memorized_reads(
420+
let (result_state, hot_state_updates) = parent_state.update_with_memorized_reads(
421421
base_state_view.persisted_hot_state(),
422422
base_state_view.persisted_state(),
423423
to_commit.state_update_refs(),
@@ -434,6 +434,7 @@ impl Parser {
434434
to_retry,
435435
result_state,
436436
state_reads,
437+
hot_state_updates,
437438
block_end_info,
438439
next_epoch_state,
439440
Planned::place_holder(),

0 commit comments

Comments
 (0)