Skip to content

Commit df9f996

Browse files
committed
[Hot State] Add a separate StateMerkleDb for hot state
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. (We don't have to do this in tools/tests though, just the nodes.)
1 parent 09a5a5e commit df9f996

File tree

29 files changed

+258
-58
lines changed

29 files changed

+258
-58
lines changed

api/test-context/src/test_context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ pub fn new_test_context_inner(
176176
BUFFERED_STATE_TARGET_ITEMS_FOR_TEST,
177177
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD,
178178
None,
179+
/* reset_hot_state = */ false,
179180
)
180181
.unwrap();
181182
if node_config

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ impl DBDebuggerInterface {
3232
BUFFERED_STATE_TARGET_ITEMS,
3333
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD,
3434
None,
35+
/* reset_hot_state = */ false,
3536
)
3637
.map_err(anyhow::Error::from)?,
3738
)))

config/src/config/storage_config.rs

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,26 @@ pub const BUFFERED_STATE_TARGET_ITEMS_FOR_TEST: usize = 10;
2929

3030
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
3131
#[serde(default, deny_unknown_fields)]
32-
pub struct DbPathConfig {
33-
pub ledger_db_path: Option<PathBuf>,
34-
pub state_kv_db_path: Option<ShardedDbPathConfig>,
35-
pub state_merkle_db_path: Option<ShardedDbPathConfig>,
36-
pub hot_state_kv_db_path: Option<ShardedDbPathConfig>,
32+
struct DbPathConfig {
33+
ledger_db_path: Option<PathBuf>,
34+
state_kv_db_path: Option<ShardedDbPathConfig>,
35+
state_merkle_db_path: Option<ShardedDbPathConfig>,
36+
hot_state_kv_db_path: Option<ShardedDbPathConfig>,
37+
hot_state_merkle_db_path: Option<ShardedDbPathConfig>,
3738
}
3839

3940
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
4041
#[serde(deny_unknown_fields)]
41-
pub struct ShardedDbPathConfig {
42-
pub metadata_path: Option<PathBuf>,
43-
pub shard_paths: Vec<ShardPathConfig>,
42+
struct ShardedDbPathConfig {
43+
metadata_path: Option<PathBuf>,
44+
shard_paths: Vec<ShardPathConfig>,
4445
}
4546

4647
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
4748
#[serde(deny_unknown_fields)]
48-
pub struct ShardPathConfig {
49-
pub shards: String,
50-
pub path: PathBuf,
49+
struct ShardPathConfig {
50+
shards: String,
51+
path: PathBuf,
5152
}
5253

5354
impl ShardedDbPathConfig {
@@ -242,12 +243,15 @@ impl Default for RocksdbConfigs {
242243
pub struct HotStateConfig {
243244
/// Max number of items in each shard.
244245
pub max_items_per_shard: usize,
246+
/// Whether to delete persisted data on disk on restart. Used during development.
247+
pub delete_on_restart: bool,
245248
}
246249

247250
impl Default for HotStateConfig {
248251
fn default() -> Self {
249252
Self {
250253
max_items_per_shard: 250_000,
254+
delete_on_restart: true,
251255
}
252256
}
253257
}
@@ -284,7 +288,7 @@ pub struct StorageConfig {
284288
/// Fine grained control for db paths of individal databases/shards.
285289
/// If not specificed, will use `dir` as default.
286290
/// Only allowed when sharding is enabled.
287-
pub db_path_overrides: Option<DbPathConfig>,
291+
db_path_overrides: Option<DbPathConfig>,
288292
/// ensure `ulimit -n`, set to 0 to not ensure.
289293
pub ensure_rlimit_nofile: u64,
290294
/// panic if failed to ensure `ulimit -n`
@@ -458,6 +462,7 @@ impl StorageConfig {
458462
let mut state_kv_db_paths = ShardedDbPaths::default();
459463
let mut state_merkle_db_paths = ShardedDbPaths::default();
460464
let mut hot_state_kv_db_paths = ShardedDbPaths::default();
465+
let mut hot_state_merkle_db_paths = ShardedDbPaths::default();
461466

462467
if let Some(db_path_overrides) = self.db_path_overrides.as_ref() {
463468
db_path_overrides
@@ -475,6 +480,12 @@ impl StorageConfig {
475480
if let Some(hot_state_kv_db_path) = db_path_overrides.hot_state_kv_db_path.as_ref() {
476481
hot_state_kv_db_paths = ShardedDbPaths::new(hot_state_kv_db_path);
477482
}
483+
484+
if let Some(hot_state_merkle_db_path) =
485+
db_path_overrides.hot_state_merkle_db_path.as_ref()
486+
{
487+
hot_state_merkle_db_paths = ShardedDbPaths::new(hot_state_merkle_db_path);
488+
}
478489
}
479490

480491
StorageDirPaths::new(
@@ -483,6 +494,7 @@ impl StorageConfig {
483494
state_kv_db_paths,
484495
state_merkle_db_paths,
485496
hot_state_kv_db_paths,
497+
hot_state_merkle_db_paths,
486498
)
487499
}
488500

@@ -503,6 +515,7 @@ pub struct StorageDirPaths {
503515
state_kv_db_paths: ShardedDbPaths,
504516
state_merkle_db_paths: ShardedDbPaths,
505517
hot_state_kv_db_paths: ShardedDbPaths,
518+
hot_state_merkle_db_paths: ShardedDbPaths,
506519
}
507520

508521
impl StorageDirPaths {
@@ -548,13 +561,26 @@ impl StorageDirPaths {
548561
.unwrap_or(&self.default_path)
549562
}
550563

564+
pub fn hot_state_merkle_db_metadata_root_path(&self) -> &PathBuf {
565+
self.hot_state_merkle_db_paths
566+
.metadata_path()
567+
.unwrap_or(&self.default_path)
568+
}
569+
570+
pub fn hot_state_merkle_db_shard_root_path(&self, shard_id: usize) -> &PathBuf {
571+
self.hot_state_merkle_db_paths
572+
.shard_path(shard_id)
573+
.unwrap_or(&self.default_path)
574+
}
575+
551576
pub fn from_path<P: AsRef<Path>>(path: P) -> Self {
552577
Self {
553578
default_path: path.as_ref().to_path_buf(),
554579
ledger_db_path: None,
555580
state_kv_db_paths: Default::default(),
556581
state_merkle_db_paths: Default::default(),
557582
hot_state_kv_db_paths: Default::default(),
583+
hot_state_merkle_db_paths: Default::default(),
558584
}
559585
}
560586

@@ -564,13 +590,15 @@ impl StorageDirPaths {
564590
state_kv_db_paths: ShardedDbPaths,
565591
state_merkle_db_paths: ShardedDbPaths,
566592
hot_state_kv_db_paths: ShardedDbPaths,
593+
hot_state_merkle_db_paths: ShardedDbPaths,
567594
) -> Self {
568595
Self {
569596
default_path,
570597
ledger_db_path,
571598
state_kv_db_paths,
572599
state_merkle_db_paths,
573600
hot_state_kv_db_paths,
601+
hot_state_merkle_db_paths,
574602
}
575603
}
576604
}
@@ -741,10 +769,8 @@ impl ConfigSanitizer for StorageConfig {
741769

742770
#[cfg(test)]
743771
mod test {
744-
use crate::config::{
745-
config_optimizer::ConfigOptimizer, NodeConfig, NodeType, PrunerConfig, ShardPathConfig,
746-
ShardedDbPathConfig, StorageConfig,
747-
};
772+
use super::{ShardPathConfig, ShardedDbPathConfig, StorageConfig};
773+
use crate::config::{config_optimizer::ConfigOptimizer, NodeConfig, NodeType, PrunerConfig};
748774
use aptos_types::chain_id::ChainId;
749775

750776
#[test]

crates/aptos-genesis/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ impl GenesisInfo {
177177
BUFFERED_STATE_TARGET_ITEMS,
178178
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD,
179179
None,
180+
/* reset_hot_state = */ false,
180181
)?;
181182
let db_rw = DbReaderWriter::new(aptosdb);
182183
aptos_executor::db_bootstrapper::generate_waypoint::<AptosVMBlockExecutor>(&db_rw, genesis)

crates/aptos-genesis/src/mainnet.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ impl MainnetGenesisInfo {
161161
BUFFERED_STATE_TARGET_ITEMS,
162162
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD,
163163
None,
164+
/* reset_hot_state = */ false,
164165
)?;
165166
let db_rw = DbReaderWriter::new(aptosdb);
166167
aptos_executor::db_bootstrapper::generate_waypoint::<AptosVMBlockExecutor>(&db_rw, genesis)

execution/executor-benchmark/src/db_generator.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ pub(crate) fn bootstrap_with_genesis(
104104
BUFFERED_STATE_TARGET_ITEMS,
105105
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD,
106106
None,
107+
/* reset_hot_state = */ false,
107108
)
108109
.expect("DB should open."),
109110
);

execution/executor-benchmark/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ pub fn init_db(config: &NodeConfig) -> DbReaderWriter {
117117
config.storage.buffered_state_target_items,
118118
config.storage.max_num_nodes_per_lru_cache_shard,
119119
None,
120+
/* reset_hot_state = */ false,
120121
)
121122
.expect("DB should open."),
122123
)

state-sync/state-sync-driver/src/tests/driver_factory.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ fn test_new_initialized_configs() {
4141
BUFFERED_STATE_TARGET_ITEMS,
4242
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD,
4343
None,
44+
/* reset_hot_state = */ false,
4445
)
4546
.unwrap();
4647
let (_, db_rw) = DbReaderWriter::wrap(db);

storage/aptosdb/src/db/aptosdb_internal.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ use std::{
4141
impl AptosDB {
4242
fn new_with_dbs(
4343
ledger_db: LedgerDb,
44+
hot_state_merkle_db: Option<StateMerkleDb>,
4445
state_merkle_db: StateMerkleDb,
4546
state_kv_db: StateKvDb,
4647
pruner_config: PrunerConfig,
@@ -51,6 +52,7 @@ impl AptosDB {
5152
internal_indexer_db: Option<InternalIndexerDB>,
5253
) -> Self {
5354
let ledger_db = Arc::new(ledger_db);
55+
let hot_state_merkle_db = hot_state_merkle_db.map(Arc::new);
5456
let state_merkle_db = Arc::new(state_merkle_db);
5557
let state_kv_db = Arc::new(state_kv_db);
5658
let state_merkle_pruner = StateMerklePrunerManager::new(
@@ -65,6 +67,7 @@ impl AptosDB {
6567
StateKvPrunerManager::new(Arc::clone(&state_kv_db), pruner_config.ledger_pruner_config);
6668
let state_store = Arc::new(StateStore::new(
6769
Arc::clone(&ledger_db),
70+
hot_state_merkle_db,
6871
Arc::clone(&state_merkle_db),
6972
Arc::clone(&state_kv_db),
7073
state_merkle_pruner,
@@ -113,6 +116,7 @@ impl AptosDB {
113116
max_num_nodes_per_lru_cache_shard: usize,
114117
empty_buffered_state_for_restore: bool,
115118
internal_indexer_db: Option<InternalIndexerDB>,
119+
reset_hot_state: bool,
116120
) -> Result<Self> {
117121
ensure!(
118122
pruner_config.eq(&NO_OP_STORAGE_PRUNER_CONFIG) || !readonly,
@@ -128,17 +132,19 @@ impl AptosDB {
128132
/* estimated_entry_charge = */ 0,
129133
);
130134

131-
let (ledger_db, state_merkle_db, state_kv_db) = Self::open_dbs(
135+
let (ledger_db, hot_state_merkle_db, state_merkle_db, state_kv_db) = Self::open_dbs(
132136
db_paths,
133137
rocksdb_configs,
134138
Some(&env),
135139
Some(&block_cache),
136140
readonly,
137141
max_num_nodes_per_lru_cache_shard,
142+
reset_hot_state,
138143
)?;
139144

140145
let mut myself = Self::new_with_dbs(
141146
ledger_db,
147+
hot_state_merkle_db,
142148
state_merkle_db,
143149
state_kv_db,
144150
pruner_config,
@@ -243,6 +249,7 @@ impl AptosDB {
243249
buffered_state_target_items,
244250
max_num_nodes_per_lru_cache_shard,
245251
None,
252+
/* reset_hot_state = */ false,
246253
)
247254
.expect("Unable to open AptosDB")
248255
}

storage/aptosdb/src/db/aptosdb_reader.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -660,12 +660,17 @@ impl DbReader for AptosDB {
660660
key_hash: &HashValue,
661661
version: Version,
662662
root_depth: usize,
663+
use_hot_state: bool,
663664
) -> Result<SparseMerkleProofExt> {
664665
gauged_api("get_state_proof_by_version_ext", || {
665666
self.error_if_state_merkle_pruned("State merkle", version)?;
666667

667-
self.state_store
668-
.get_state_proof_by_version_ext(key_hash, version, root_depth)
668+
self.state_store.get_state_proof_by_version_ext(
669+
key_hash,
670+
version,
671+
root_depth,
672+
use_hot_state,
673+
)
669674
})
670675
}
671676

@@ -674,12 +679,17 @@ impl DbReader for AptosDB {
674679
key_hash: &HashValue,
675680
version: Version,
676681
root_depth: usize,
682+
use_hot_state: bool,
677683
) -> Result<(Option<StateValue>, SparseMerkleProofExt)> {
678684
gauged_api("get_state_value_with_proof_by_version_ext", || {
679685
self.error_if_state_merkle_pruned("State merkle", version)?;
680686

681-
self.state_store
682-
.get_state_value_with_proof_by_version_ext(key_hash, version, root_depth)
687+
self.state_store.get_state_value_with_proof_by_version_ext(
688+
key_hash,
689+
version,
690+
root_depth,
691+
use_hot_state,
692+
)
683693
})
684694
}
685695

0 commit comments

Comments
 (0)