Skip to content

perf(core): snapshots #3211

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 179 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
179 commits
Select commit Hold shift + click to select a range
098369e
chore(core) improve import blocks readability
pablodeymo Jun 2, 2025
4c94c78
Simplifying import_blocks
pablodeymo Jun 2, 2025
6346086
hash_no_commit_with_batch
pablodeymo Jun 2, 2025
61f2a8e
QueryPlan WIP
pablodeymo Jun 3, 2025
47d2d42
small changes
pablodeymo Jun 3, 2025
6918fe4
implement query_plan_apply
juanbono Jun 3, 2025
427d9b6
remove dbg statement
juanbono Jun 4, 2025
de7da8d
Comment out dbg in QueryPlan
pablodeymo Jun 4, 2025
245e2dd
Merge branch 'main' into storage_commit_change
pablodeymo Jun 4, 2025
7e4224e
Merge branch 'main' into storage_commit_change
pablodeymo Jun 4, 2025
f5790e7
remove unnecesary pub
pablodeymo Jun 4, 2025
30fae24
WIP full sync with batch writes
pablodeymo Jun 4, 2025
3e34382
finish migration to batch update for sync
Oppen Jun 4, 2025
e4dd995
Merge branch 'main' into storage_commit_change
pablodeymo Jun 5, 2025
d3d7f73
fixing compilation issue
pablodeymo Jun 5, 2025
8d0eb7a
add logging
Oppen Jun 6, 2025
847fc0f
more logs
Oppen Jun 6, 2025
6d24b58
use millis
Oppen Jun 6, 2025
c8a727c
wip: snapshot poc for account storage only
Oppen Jun 9, 2025
5e9fe65
refactor(core): refactor and implement bulk operations in other datab…
iovoid Jun 9, 2025
c5dd336
Co-authored-by: Juan Bono <[email protected]>
pablodeymo Jun 9, 2025
4ca6a19
returning the Trie apply_account_updates_from_trie_batch
pablodeymo Jun 9, 2025
b7075eb
account info snapshots
Oppen Jun 9, 2025
3c5ead5
todo!s in redb
pablodeymo Jun 9, 2025
3c18f72
changing if let in libmdbx
pablodeymo Jun 9, 2025
33b4f5d
tracing
Oppen Jun 9, 2025
dc5d0bc
fix error caused by apply_account_updates_from_trie_batch returning t…
pablodeymo Jun 9, 2025
8a70c08
Merge branch 'perf/snapshots_poc' into perf/storage_batch_and_snapshots
pablodeymo Jun 9, 2025
cc6d49c
fixing errors
pablodeymo Jun 9, 2025
25a5442
integration working
Oppen Jun 9, 2025
37f055b
try sorting and cursors
Oppen Jun 10, 2025
67856b0
progress on split tables, better sort
Oppen Jun 10, 2025
1ceb899
Revert "progress on split tables, better sort"
pablodeymo Jun 11, 2025
8e70278
Revert "try sorting and cursors"
pablodeymo Jun 11, 2025
180f768
Co-authored-by: Mario Rugiero <[email protected]>
pablodeymo Jun 11, 2025
7fb569a
WIP: re-generate snapshot
pablodeymo Jun 11, 2025
fad160e
Revert "WIP: re-generate snapshot"
pablodeymo Jun 11, 2025
8e2d0e9
WIP: tables for logs in libmdbx
pablodeymo Jun 11, 2025
3f4d650
Encodable for AccountInfoWriteLog
pablodeymo Jun 12, 2025
4be34a6
StorageStateWriteLog finished
pablodeymo Jun 12, 2025
f0d0bcb
WIP: storing log in the db
pablodeymo Jun 12, 2025
947dfd3
fix apply_updates method signature in StoreEngine
pablodeymo Jun 12, 2025
5258edb
WIP apply_updates in StoreEngine
pablodeymo Jun 12, 2025
3cd6690
init tables
Oppen Jun 13, 2025
bca0231
simplify and implement log saving
Oppen Jun 13, 2025
d9ba41e
fix: forgot to commit
Oppen Jun 13, 2025
8f44b09
fix: storage log entries
Oppen Jun 13, 2025
fa38d5a
wip: reorg support
Oppen Jun 13, 2025
311f1a6
commit
Oppen Jun 13, 2025
c92ade1
wip: fixing errors to make it compile
pablodeymo Jun 13, 2025
8fe3b87
fix loops to process the first value
pablodeymo Jun 13, 2025
651ee0d
implement the replay
Oppen Jun 13, 2025
fa93589
detect deletions
Oppen Jun 13, 2025
3e684a1
move comment
Oppen Jun 13, 2025
b677cdf
some blocks might not change storage or account info
Oppen Jun 13, 2025
6c1deb5
apply_fork_choice every 1000 blocks on import
Oppen Jun 13, 2025
345b102
derive debug for blocknumhash
Oppen Jun 14, 2025
079b8d5
reverse new_canonical_blocks
Oppen Jun 17, 2025
faf63d3
missing mut
Oppen Jun 17, 2025
b635586
Merge branch 'main' into perf/storage_batch_and_snapshots
pablodeymo Jun 17, 2025
e817511
fix cli,rs
pablodeymo Jun 17, 2025
a67f90a
clippy
pablodeymo Jun 17, 2025
f1dbc45
rework replay/undo algorithm
Oppen Jun 18, 2025
6a1f1ac
Merge branch 'perf/storage_batch_and_snapshots' of github.com:lambdac…
Oppen Jun 18, 2025
f92887f
Merge branch 'main' into perf/storage_batch_and_snapshots
pablodeymo Jun 18, 2025
a10c34f
Merge branch 'perf/storage_batch_and_snapshots' of github.com:lambdac…
Oppen Jun 18, 2025
bff316e
improve match
pablodeymo Jun 18, 2025
654a4b8
remove unnecessary mut
pablodeymo Jun 18, 2025
c995843
fix unwrap_or
pablodeymo Jun 18, 2025
e18d09e
remove unused use
pablodeymo Jun 18, 2025
2efc16d
fix unused index in enumerate()
pablodeymo Jun 18, 2025
a6233c9
fix clippy warning
pablodeymo Jun 18, 2025
835e633
fix: the new algorithm needs to happen *after* updating the canonical…
Oppen Jun 18, 2025
a734313
fix: always update the snapshot when marking a new chain as canonical
Oppen Jun 18, 2025
d0bad7b
Merge branch 'perf/storage_batch_and_snapshots' of github.com:lambdac…
Oppen Jun 18, 2025
201ec4e
refactor codec structs
pablodeymo Jun 18, 2025
40b8089
table! on top of libmdbx.rs file
pablodeymo Jun 18, 2025
1a3e7d0
refactor aux tables for libmdbx
pablodeymo Jun 18, 2025
bc288ea
conditional compilation of encobable methods
pablodeymo Jun 18, 2025
68b67d1
Merge branch 'main' into perf/storage_batch_and_snapshots
pablodeymo Jun 18, 2025
d7692b6
many fixes
Oppen Jun 18, 2025
d0e3ae4
fix build
Oppen Jun 18, 2025
c47332f
attemt to handle missing ancestor
Oppen Jun 18, 2025
8a0880f
fix codecs for log entries
Oppen Jun 18, 2025
a3a26a8
WIP cleanup and replace_value method in libmdbx
pablodeymo Jun 19, 2025
550dd3e
remove async in replace_value
pablodeymo Jun 19, 2025
f9a64b8
remove debub_assert_eq
pablodeymo Jun 19, 2025
e374a67
replay_writes_until_head: remove unnecesary variable
pablodeymo Jun 19, 2025
01a993c
comment removed
pablodeymo Jun 19, 2025
f2a4a82
Merge branch 'main' into perf/storage_batch_and_snapshots
pablodeymo Jun 19, 2025
340782c
fix an edge case + consistent use of constants
Oppen Jun 19, 2025
d0f990c
Merge branch 'perf/storage_batch_and_snapshots' of github.com:lambdac…
Oppen Jun 19, 2025
2d3249e
fix removed entry detection
Oppen Jun 19, 2025
0a67694
conditionally update the snapshot
Oppen Jun 19, 2025
77f35be
replace_value_or_delete
pablodeymo Jun 19, 2025
fe85651
refactor to use helper
Oppen Jun 19, 2025
e2e971b
just in case respect order of checks
Oppen Jun 19, 2025
3d8cfd6
AccountStorageLogEntry with named fields
pablodeymo Jun 19, 2025
e5702d6
clippy
pablodeymo Jun 19, 2025
6a959cd
refactor: update account storage log handling to use AccountStorageLo…
pablodeymo Jun 19, 2025
47c228e
fix errors
pablodeymo Jun 19, 2025
eeab456
add tracing for snapshot misses
Oppen Jun 23, 2025
7f46643
Merge branch 'perf/storage_batch_and_snapshots' of github.com:lambdac…
Oppen Jun 23, 2025
a4b4441
refactor: add feature flag annotations for account info and storage l…
pablodeymo Jun 23, 2025
c9a8834
Batch updates in account info and storage log updates
pablodeymo Jun 23, 2025
aad0d08
fixes
Oppen Jun 23, 2025
9bc0c45
fix
Oppen Jun 23, 2025
d2bd73c
fix
Oppen Jun 23, 2025
a26ea71
add logging for account removal
Oppen Jun 23, 2025
d92b3d8
try not clearing cache, update immutable_cache
Oppen Jun 24, 2025
7eb5b09
and take removal into account
Oppen Jun 24, 2025
207205f
try also not clearing the main cache
Oppen Jun 24, 2025
58501fa
Revert "try not clearing cache, update immutable_cache"
Oppen Jun 24, 2025
dc14c45
get_state_transitions per batch only
Oppen Jun 24, 2025
75e3341
wip: rework logs for block ranges
Oppen Jun 24, 2025
d0de977
Merge branch 'main' into perf/storage_batch_and_snapshots
pablodeymo Jun 24, 2025
dcac752
impl From<anyhow::Error> for StoreError
pablodeymo Jun 24, 2025
ae31621
simplify and document the undo and replay log functions
pablodeymo Jun 24, 2025
b87792c
skip blocks not found in canonical chain
Oppen Jun 24, 2025
e5bbd92
Merge branch 'main' into perf/storage_batch_and_snapshots
pablodeymo Jun 24, 2025
a0c61bb
simplify error handling in apply_updates function of StoreEngine
pablodeymo Jun 24, 2025
397c782
document todo
Oppen Jun 24, 2025
c59af67
Merge branch 'main' into perf/storage_batch_and_snapshots
pablodeymo Jun 24, 2025
811a59f
Merge branch 'main' into perf/storage_batch_and_snapshots
pablodeymo Jun 25, 2025
cd44051
fix paris! missed a cut case
Oppen Jun 25, 2025
53a8d48
fix: read old values from trie when base block is not snapshot
Oppen Jun 26, 2025
39461be
Merge remote-tracking branch 'origin/main' into perf/storage_batch_an…
Oppen Jun 26, 2025
3707d61
Merge branch 'main' into perf/storage_batch_and_snapshots
pablodeymo Jun 26, 2025
60e2aa4
Merge branch 'main' into perf/storage_batch_and_snapshots
damiramirez Jul 1, 2025
aaaf230
feat: implementing new methods in in memory file
damiramirez Jul 1, 2025
7ef8801
feat: implement undo_writes_until_canonical method in memory Store
damiramirez Jul 1, 2025
cef4f99
feat: implement replay_writes_until_head in memory Store
damiramirez Jul 1, 2025
c85ea2d
refactor: apply account info and storage logs in apply_updates
damiramirez Jul 1, 2025
455fccf
docs: improve comments in undo and replay
damiramirez Jul 2, 2025
e3e3dfa
feat: check if current_snapshot == (block_num, snapshot_hash) and bre…
damiramirez Jul 2, 2025
b576df8
feat: open ACCOUNT_INFO_TABLE table
damiramirez Jul 2, 2025
f4747ea
feat: implement get_current_storage in redb
damiramirez Jul 2, 2025
51a5e0e
feat: implement get_block_for_current_snapshot in redb
damiramirez Jul 2, 2025
814b777
feat: implement setup_genesis_flat_account_info in redb
damiramirez Jul 2, 2025
4c4644d
feat: implement setup_genesis_flat_account_storage in redb
damiramirez Jul 2, 2025
dbf4f3a
Merge branch 'main' into perf/storage_batch_and_snapshots
pablodeymo Jul 2, 2025
fa996d9
feat: scaffolding undo_writes_until_canonical
damiramirez Jul 2, 2025
3fb340f
refactor: fix borrow rebd issue
damiramirez Jul 2, 2025
e628e54
refactor: improve undo logic
damiramirez Jul 2, 2025
6b49f0e
refactor: improve undo logic
damiramirez Jul 3, 2025
258b723
refactor: finish with undo
damiramirez Jul 3, 2025
d1c3a71
feat: implement replay_writes_until_head in redb
damiramirez Jul 3, 2025
5ef0e46
Merge branch 'perf/storage_batch_and_snapshots' of github.com:lambdac…
damiramirez Jul 3, 2025
c4c42a5
refactor: update apply with new methods
damiramirez Jul 3, 2025
2ce8a3a
refactor: remove libmdbx flag in some files
damiramirez Jul 3, 2025
e05a243
refactor: use write batch in redb
damiramirez Jul 3, 2025
063ad41
fix: add redb feature flag in rlp imports
damiramirez Jul 3, 2025
dbb41ff
fix: compile error in l2 using store_block_updates
damiramirez Jul 3, 2025
20abfbc
refactor: remove warn when getting data with hash to avoid spam
damiramirez Jul 3, 2025
ec2d432
chore: run cargo fmt
damiramirez Jul 3, 2025
d5095d9
fix: avoid rewriting previous values in array
damiramirez Jul 3, 2025
5a7c8f5
chore: remove tracing from levm crate
damiramirez Jul 3, 2025
9109d33
Merge branch 'main' into perf/storage_batch_and_snapshots
pablodeymo Jul 3, 2025
0da99b6
refactor: only update snapshots if we have blocks
damiramirez Jul 3, 2025
03c3239
Merge branch 'perf/storage_batch_and_snapshots' of github.com:lambdac…
damiramirez Jul 3, 2025
d0498de
refactor: use a better name for blockNumHash from logs in libmdbx
damiramirez Jul 3, 2025
7fb4224
Merge branch 'main' into perf/storage_batch_and_snapshots
pablodeymo Jul 3, 2025
4240610
Merge branch 'perf/storage_batch_and_snapshots' of github.com:lambdac…
damiramirez Jul 3, 2025
5040cda
refactor: add flags to specific libmdbx const values
damiramirez Jul 3, 2025
9c8d09d
docs: add documentation to snapshot methods in trait
damiramirez Jul 3, 2025
49243dd
refactor: improve readability undo in libmdbx
damiramirez Jul 3, 2025
ed00f2d
refactor: improve readability replay in libmdbx
damiramirez Jul 3, 2025
e5d6727
docs: add documentation to UpdateBatch fields
damiramirez Jul 3, 2025
3146d5b
Merge branch 'main' into perf/storage_batch_and_snapshots
pablodeymo Jul 3, 2025
f42b979
refactor: remove logs
damiramirez Jul 3, 2025
ba59bb1
refactor: improve logic in libmdbx
damiramirez Jul 4, 2025
ab411ae
Merge branch 'perf/storage_batch_and_snapshots' of github.com:lambdac…
damiramirez Jul 4, 2025
2df54b4
fix: try to fix hive paris tests
damiramirez Jul 4, 2025
877b29f
docs: add comment explaining why break
damiramirez Jul 4, 2025
1ecb543
Merge branch 'main' into perf/storage_batch_and_snapshots
damiramirez Jul 4, 2025
513981b
Merge branch 'main' into perf/storage_batch_and_snapshots
damiramirez Jul 4, 2025
6c3b42b
Refactor BlockNumHash structure, assigning names to fields
pablodeymo Jul 4, 2025
1cde3b1
fix: remove field post cherry pick
damiramirez Jul 4, 2025
f2c39d9
Merge branch 'main' into perf/storage_batch_and_snapshots
pablodeymo Jul 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions cmd/ethrex/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,11 @@ pub async fn import_blocks(

// Make head canonical and label all special blocks correctly.
if let Some(block) = blocks.last() {
_ = store
.reconstruct_snapshots_for_new_canonical_chain(block.hash())
.await
.inspect_err(|error| warn!("Failed to reconstruct snapshot: {}", error));

store
.update_finalized_block_number(block.header.number)
.await?;
Expand Down
8 changes: 3 additions & 5 deletions cmd/ethrex/l2/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ impl Command {
.await
.expect("Error applying account updates");

let (new_state_root, state_updates, accounts_updates) =
let (new_state_root, state_updates, storage_updates) =
(
account_updates_list.state_trie_hash,
account_updates_list.state_updates,
Expand All @@ -393,10 +393,8 @@ impl Command {

let pseudo_update_batch = UpdateBatch {
account_updates: state_updates,
storage_updates: accounts_updates,
blocks: vec![],
receipts: vec![],
code_updates: vec![],
storage_updates,
..Default::default()
};

store.store_block_updates(pseudo_update_batch).await.expect("Error storing trie updates");
Expand Down
38 changes: 31 additions & 7 deletions crates/blockchain/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,16 +362,25 @@ impl Blockchain {
account_updates: &[AccountUpdate],
) -> Result<(), ChainError> {
// Apply the account updates over the last block's state and compute the new state root
let parent_hash = block.header.parent_hash;
let apply_updates_list = self
.storage
.apply_account_updates_batch(block.header.parent_hash, account_updates)
.apply_account_updates_batch(parent_hash, account_updates)
.await?
.ok_or(ChainError::ParentStateNotFound)?;

let new_state_root = apply_updates_list.state_trie_hash;
let state_updates = apply_updates_list.state_updates;
let accounts_updates = apply_updates_list.storage_updates;
let code_updates = apply_updates_list.code_updates;
let account_info_log_updates = self
.storage
.build_account_info_logs(parent_hash, account_updates.iter())
.map_err(ChainError::StoreError)?;
let storage_log_updates = self
.storage
.build_account_storage_logs(parent_hash, account_updates.iter())
.map_err(ChainError::StoreError)?;

// Check state root matches the one in block header
validate_state_root(&block.header, new_state_root)?;
Expand All @@ -382,10 +391,11 @@ impl Blockchain {
blocks: vec![block.clone()],
receipts: vec![(block.hash(), execution_result.receipts)],
code_updates,
account_info_log_updates,
storage_log_updates,
};

self.storage
.clone()
.store_block_updates(update_batch)
.await
.map_err(|e| e.into())
Expand Down Expand Up @@ -517,21 +527,22 @@ impl Blockchain {
log_batch_progress(blocks_len, i);
}

let account_updates = vm
.get_state_transitions()
.map_err(|err| (ChainError::EvmError(err), None))?;

let last_block = blocks
.last()
.ok_or_else(|| (ChainError::Custom("Last block not found".into()), None))?;

let last_block_number = last_block.header.number;
let last_block_gas_limit = last_block.header.gas_limit;

let account_updates = vm
.get_state_transitions()
.map_err(|err| (ChainError::EvmError(err), None))?;

let parent_hash = first_block_header.parent_hash;
// Apply the account updates over all blocks and compute the new state root
let account_updates_list = self
.storage
.apply_account_updates_batch(first_block_header.parent_hash, &account_updates)
.apply_account_updates_batch(parent_hash, &account_updates)
.await
.map_err(|e| (e.into(), None))?
.ok_or((ChainError::ParentStateNotFound, None))?;
Expand All @@ -544,12 +555,25 @@ impl Blockchain {
// Check state root matches the one in block header
validate_state_root(&last_block.header, new_state_root).map_err(|e| (e, None))?;

// call helper function to build write logs
let account_info_log_updates = self
.storage
.build_account_info_logs(parent_hash, account_updates.iter())
.map_err(|e| (e.into(), None))?;

let storage_log_updates = self
.storage
.build_account_storage_logs(parent_hash, account_updates.iter())
.map_err(|e| (e.into(), None))?;

let update_batch = UpdateBatch {
account_updates: state_updates,
storage_updates: accounts_updates,
blocks,
receipts: all_receipts,
code_updates,
account_info_log_updates,
storage_log_updates,
};

self.storage
Expand Down
20 changes: 11 additions & 9 deletions crates/blockchain/fork_choice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ pub async fn apply_fork_choice(
return Err(InvalidForkChoice::UnlinkedHead);
};

let link_block_number = match new_canonical_blocks.last() {
Some((number, _)) => *number,
None => head.number,
};
let link_block_number = new_canonical_blocks
.last()
.map(|(number, _)| *number)
.unwrap_or(head.number);

// Check that finalized and safe blocks are part of the new canonical chain.
if let Some(ref finalized) = finalized_res {
Expand Down Expand Up @@ -99,7 +99,6 @@ pub async fn apply_fork_choice(
}

// Finished all validations.

// Make all ancestors to head canonical.
for (number, hash) in new_canonical_blocks {
store.set_canonical_block(number, hash).await?;
Expand All @@ -112,6 +111,11 @@ pub async fn apply_fork_choice(

// Make head canonical and label all special blocks correctly.
store.set_canonical_block(head.number, head_hash).await?;

store
.reconstruct_snapshots_for_new_canonical_chain(head_hash)
.await?;

if let Some(finalized) = finalized_res {
store
.update_finalized_block_number(finalized.number)
Expand Down Expand Up @@ -176,10 +180,8 @@ async fn find_link_with_canonical_chain(
let parent_hash = header.parent_hash;

// Check that the parent exists.
let parent_header = match store.get_block_header_by_hash(parent_hash) {
Ok(Some(header)) => header,
Ok(None) => return Ok(None),
Err(error) => return Err(error),
let Some(parent_header) = store.get_block_header_by_hash(parent_hash)? else {
return Ok(None);
};

if is_canonical(store, block_number, parent_hash).await? {
Expand Down
30 changes: 24 additions & 6 deletions crates/blockchain/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,33 @@ impl StoreVmDatabase {

impl VmDatabase for StoreVmDatabase {
fn get_account_info(&self, address: Address) -> Result<Option<AccountInfo>, EvmError> {
self.store
.get_account_info_by_hash(self.block_hash, address)
.map_err(|e| EvmError::DB(e.to_string()))
let block_for_current_snapshot = self
.store
.get_block_for_current_snapshot()
.map_err(|e| EvmError::DB(e.to_string()))?;

if Some(self.block_hash) == block_for_current_snapshot {
self.store.get_current_account_info(address)
} else {
self.store
.get_account_info_by_hash(self.block_hash, address)
}
.map_err(|e| EvmError::DB(e.to_string()))
}

fn get_storage_slot(&self, address: Address, key: H256) -> Result<Option<U256>, EvmError> {
self.store
.get_storage_at_hash(self.block_hash, address, key)
.map_err(|e| EvmError::DB(e.to_string()))
let block_for_current_snapshot = self
.store
.get_block_for_current_snapshot()
.map_err(|e| EvmError::DB(e.to_string()))?;

if Some(self.block_hash) == block_for_current_snapshot {
self.store.get_current_storage(address, key)
} else {
self.store
.get_storage_at_hash(self.block_hash, address, key)
}
.map_err(|e| EvmError::DB(e.to_string()))
}

fn get_block_hash(&self, block_number: u64) -> Result<H256, EvmError> {
Expand Down
2 changes: 1 addition & 1 deletion crates/common/types/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub struct Account {
pub storage: HashMap<H256, U256>,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Eq)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub struct AccountInfo {
pub code_hash: H256,
pub balance: U256,
Expand Down
11 changes: 11 additions & 0 deletions crates/networking/p2p/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,13 +463,24 @@ impl Syncer {
.set_latest_valid_ancestor(failed_block_hash, last_valid_hash)
.await?;

// We also need to use the correct snapshot.
store
.reconstruct_snapshots_for_new_canonical_chain(last_valid_hash)
.await
.map_err(SyncError::Store)?;
// TODO(#2127): Just marking the failing ancestor is enough for the the Missing Ancestors hive test,
// we want to look at a more robust solution in the future if needed.
}

return Err(error.into());
}

// We also need to use the correct snapshot.
store
.reconstruct_snapshots_for_new_canonical_chain(last_block.hash())
.await
.map_err(SyncError::Store)?;

store
.update_latest_block_number(last_block.header.number)
.await?;
Expand Down
42 changes: 40 additions & 2 deletions crates/storage/api.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use bytes::Bytes;
use ethereum_types::{H256, U256};
use ethrex_common::Address;
use ethrex_common::types::{
AccountState, Block, BlockBody, BlockHash, BlockHeader, BlockNumber, ChainConfig, Index,
Receipt, Transaction, payload::PayloadBundle,
AccountInfo, AccountState, Block, BlockBody, BlockHash, BlockHeader, BlockNumber, ChainConfig,
Index, Receipt, Transaction, payload::PayloadBundle,
};
use std::{fmt::Debug, panic::RefUnwindSafe};

Expand All @@ -17,6 +18,17 @@ pub trait StoreEngine: Debug + Send + Sync + RefUnwindSafe {
/// Store changes in a batch from a vec of blocks
async fn apply_updates(&self, update_batch: UpdateBatch) -> Result<(), StoreError>;

/// Reverts the changes in the state using write logs until reaching a canonical block.
/// Used to restore state after a reorg by walking backwards through logs.
async fn undo_writes_until_canonical(&self) -> Result<(), StoreError>;

/// Replays writes from the write logs until the head block is reached.
/// This is used to restore the flat tables from the write logs after a reorg.
/// Assumes that the current flat representation corresponds to a block in the canonical chain.
/// Must be called after [`undo_writes_until_canonical`](StoreEngine::undo_writes_until_canonical)
/// to complete reorg recovery.
async fn replay_writes_until_head(&self, head: H256) -> Result<(), StoreError>;

/// Add a batch of blocks in a single transaction.
/// This will store -> BlockHeader, BlockBody, BlockTransactions, BlockNumber.
async fn add_blocks(&self, blocks: Vec<Block>) -> Result<(), StoreError>;
Expand Down Expand Up @@ -307,6 +319,32 @@ pub trait StoreEngine: Debug + Send + Sync + RefUnwindSafe {
&self,
) -> Result<Option<[H256; STATE_TRIE_SEGMENTS]>, StoreError>;

/// Sets up the flat tables of account storage for the genesis block
async fn setup_genesis_flat_account_storage(
&self,
genesis_block_number: u64,
genesis_block_hash: H256,
genesis_accounts: &[(Address, H256, U256)],
) -> Result<(), StoreError>;

/// Sets up the flat tables of account info for the genesis block
async fn setup_genesis_flat_account_info(
&self,
genesis_block_number: u64,
genesis_block_hash: H256,
genesis_accounts: &[(Address, u64, U256, H256, bool)],
) -> Result<(), StoreError>;

/// Gets the block hash for the current snapshot
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe clarify that the result is an option because there may be no current snapshot (if there is, there will always be an associated block hash).

fn get_block_for_current_snapshot(&self) -> Result<Option<BlockHash>, StoreError>;

/// Gets the account storage for an account
fn get_current_storage(&self, address: Address, key: H256) -> Result<Option<U256>, StoreError>;

/// Gets the account info for an account
fn get_current_account_info(&self, address: Address)
-> Result<Option<AccountInfo>, StoreError>;

/// Sets storage trie paths in need of healing, grouped by hashed address
/// This will overwite previously stored paths for the received storages but will not remove other storage's paths
async fn set_storage_heal_paths(
Expand Down
7 changes: 7 additions & 0 deletions crates/storage/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,10 @@ pub enum StoreError {
#[error("Failed to lock database for writing")]
LockError,
}

#[cfg(feature = "libmdbx")]
impl From<anyhow::Error> for StoreError {
fn from(err: anyhow::Error) -> Self {
StoreError::LibmdbxError(err)
}
}
Comment on lines +56 to +62
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems convoluted and counterintuitive. anyhow:Error is very generic. How can we make sure it would always be a libmdbx error? why do we need this?

23 changes: 23 additions & 0 deletions crates/storage/rlp.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
use std::fmt::Debug;
use std::marker::PhantomData;

#[cfg(feature = "redb")]
use crate::store_db::codec::{
account_info_log_entry::AccountInfoLogEntry, account_storage_log_entry::AccountStorageLogEntry,
block_num_hash::BlockNumHash,
};
use bytes::Bytes;
#[cfg(feature = "redb")]
use ethrex_common::{Address, U256, types::AccountInfo};
use ethrex_common::{
H256,
types::{
Expand All @@ -24,6 +31,22 @@ pub type AccountHashRLP = Rlp<H256>;
pub type AccountStateRLP = Rlp<AccountState>;
pub type TriePathsRLP = Rlp<Vec<Nibbles>>;

// Snapshot state RLP types
#[cfg(feature = "redb")]
pub type AccountInfoLogEntryRLP = Rlp<AccountInfoLogEntry>;
#[cfg(feature = "redb")]
pub type AccountStorageLogEntryRLP = Rlp<AccountStorageLogEntry>;
#[cfg(feature = "redb")]
pub type BlockNumHashRLP = Rlp<BlockNumHash>;
#[cfg(feature = "redb")]
pub type AccountAddressRLP = Rlp<Address>;
#[cfg(feature = "redb")]
pub type AccountInfoRLP = Rlp<AccountInfo>;
#[cfg(feature = "redb")]
pub type AccountStorageKeyRLP = Rlp<H256>;
#[cfg(feature = "redb")]
pub type AccountStorageValueRLP = Rlp<U256>;
Comment on lines +35 to +48
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is redb specific, why do we need it in the storage rlp directory? Can we not have it in the redb file instead?


// Block types
pub type BlockHashRLP = Rlp<BlockHash>;
pub type BlockHeaderRLP = Rlp<BlockHeader>;
Expand Down
Loading
Loading