Skip to content

Commit edbd4aa

Browse files
authored
Merge 575a8a8 into 56e563a
2 parents 56e563a + 575a8a8 commit edbd4aa

File tree

21 files changed

+438
-71
lines changed

21 files changed

+438
-71
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/ethrex/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ ethrex-sdk = { workspace = true, optional = true }
2626
ethrex-storage.workspace = true
2727
ethrex-storage-rollup = { workspace = true, optional = true }
2828
ethrex-vm.workspace = true
29-
29+
ethrex-trie.workspace = true
3030
tikv-jemallocator = { version = "0.6.0", optional = true, features = [
3131
"stats",
3232
"unprefixed_malloc_on_supported_platforms",

crates/common/trie/db.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ pub trait TrieDB: Send + Sync {
2525
fn put(&self, key: Nibbles, value: Vec<u8>) -> Result<(), TrieError> {
2626
self.put_batch(vec![(key, value)])
2727
}
28+
fn flatkeyvalue_computed(&self, _key: Nibbles) -> bool {
29+
false
30+
}
2831
}
2932

3033
/// InMemory implementation for the TrieDB trait, with get and put operations.
@@ -102,15 +105,3 @@ impl TrieDB for InMemoryTrieDB {
102105
Ok(())
103106
}
104107
}
105-
106-
pub fn nibbles_to_fixed_size(nibbles: Nibbles) -> [u8; 33] {
107-
let node_hash_ref = nibbles.to_bytes();
108-
let original_len = node_hash_ref.len();
109-
110-
let mut buffer = [0u8; 33];
111-
112-
// Encode the node as [node_path..., original_len]
113-
buffer[32] = nibbles.len() as u8;
114-
buffer[..original_len].copy_from_slice(&node_hash_ref);
115-
buffer
116-
}

crates/common/trie/node.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ impl NodeRef {
7070
Node::Leaf(_) => {}
7171
}
7272
let hash = *hash.get_or_init(|| node.compute_hash());
73+
if let Node::Leaf(leaf) = node.as_ref() {
74+
acc.push((path.concat(&leaf.partial), leaf.value.clone()));
75+
}
7376
acc.push((path.clone(), node.encode_to_vec()));
7477

7578
*self = hash.into();

crates/common/trie/trie.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,19 @@ impl Trie {
9898
pub fn get(&self, pathrlp: &PathRLP) -> Result<Option<ValueRLP>, TrieError> {
9999
let path = Nibbles::from_bytes(pathrlp);
100100

101+
if pathrlp.len() == 32
102+
&& !self.pending_removal.contains(&path)
103+
&& self.db().flatkeyvalue_computed(path.clone())
104+
{
105+
let Some(value_rlp) = self.db.get(path)? else {
106+
return Ok(None);
107+
};
108+
if value_rlp.is_empty() {
109+
return Ok(None);
110+
}
111+
return Ok(Some(value_rlp));
112+
}
113+
101114
Ok(match self.root {
102115
NodeRef::Node(ref node, _) => node.get(self.db.as_ref(), path)?,
103116
NodeRef::Hash(hash) if hash.is_valid() => Node::decode(
@@ -138,6 +151,10 @@ impl Trie {
138151
if !self.root.is_valid() {
139152
return Ok(None);
140153
}
154+
if path.len() == 32 {
155+
self.pending_removal.insert(Nibbles::from_bytes(path));
156+
}
157+
141158
// If the trie is not empty, call the root node's removal logic.
142159
let (node, value) = self
143160
.root

crates/common/trie/trie_sorted.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,10 @@ mod test {
429429
let computed_data = computed_data.lock().unwrap();
430430
let expected_data = expected_data.lock().unwrap();
431431
for (k, v) in expected_data.iter() {
432+
// skip flatkeyvalues, we don't want them
433+
if k.last().cloned() == Some(16) {
434+
continue;
435+
}
432436
assert!(computed_data.contains_key(k));
433437
assert_eq!(*v, computed_data[k]);
434438
}

crates/networking/p2p/sync.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,8 @@ impl Syncer {
904904
}
905905
*METRICS.heal_end_time.lock().await = Some(SystemTime::now());
906906

907+
store.generate_flatkeyvalue()?;
908+
907909
debug_assert!(validate_state_root(store.clone(), pivot_header.state_root).await);
908910
debug_assert!(validate_storage_root(store.clone(), pivot_header.state_root).await);
909911

crates/storage/api.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,4 +375,6 @@ pub trait StoreEngine: Debug + Send + Sync + RefUnwindSafe {
375375

376376
/// Clear all headers downloaded during fullsync
377377
async fn clear_fullsync_headers(&self) -> Result<(), StoreError>;
378+
379+
fn generate_flatkeyvalue(&self) -> Result<(), StoreError>;
378380
}

crates/storage/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,6 @@ pub enum StoreError {
3838
TryInto(#[from] std::num::TryFromIntError),
3939
#[error("Update batch contains no blocks")]
4040
UpdateBatchNoBlocks,
41+
#[error("Pivot changed")]
42+
PivotChanged,
4143
}

crates/storage/store.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,6 +1358,10 @@ impl Store {
13581358
pub async fn clear_fullsync_headers(&self) -> Result<(), StoreError> {
13591359
self.engine.clear_fullsync_headers().await
13601360
}
1361+
1362+
pub fn generate_flatkeyvalue(&self) -> Result<(), StoreError> {
1363+
self.engine.generate_flatkeyvalue()
1364+
}
13611365
}
13621366

13631367
pub struct AccountProof {
@@ -1456,17 +1460,19 @@ mod tests {
14561460
F: FnOnce(Store) -> Fut,
14571461
Fut: std::future::Future<Output = ()>,
14581462
{
1463+
let nonce: u64 = H256::random().to_low_u64_be();
1464+
let path = format!("store-test-db-{nonce}");
14591465
// Remove preexistent DBs in case of a failed previous test
14601466
if !matches!(engine_type, EngineType::InMemory) {
1461-
remove_test_dbs("store-test-db");
1467+
remove_test_dbs(&path);
14621468
};
14631469
// Build a new store
1464-
let store = Store::new("store-test-db", engine_type).expect("Failed to create test db");
1470+
let store = Store::new(&path, engine_type).expect("Failed to create test db");
14651471
// Run the test
14661472
test_func(store).await;
14671473
// Remove store (if needed)
14681474
if !matches!(engine_type, EngineType::InMemory) {
1469-
remove_test_dbs("store-test-db");
1475+
remove_test_dbs(&path);
14701476
};
14711477
}
14721478

0 commit comments

Comments
 (0)