Skip to content

Commit bf02bc3

Browse files
authored
feat: add format validation to era2-stats binary (#1555)
1 parent fd4a212 commit bf02bc3

File tree

1 file changed

+44
-5
lines changed

1 file changed

+44
-5
lines changed

e2store/src/bin/era2-stats.rs

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
use std::path::PathBuf;
22

3+
use alloy::primitives::{keccak256, B256};
34
use anyhow::bail;
45
use clap::Parser;
5-
use e2store::era2::{AccountOrStorageEntry, Era2Reader};
6+
use e2store::era2::{self, AccountOrStorageEntry, Era2Reader};
67
use tracing::info;
78

89
#[derive(Debug, Parser)]
910
#[command(
1011
name = "Era2 stats",
11-
about = "Reads the era2 file and prints stats about it."
12+
about = "Reads the era2 file, validates the format, and prints stats about it."
1213
)]
1314
struct Config {
1415
#[arg(help = "The path to the era2 file.")]
@@ -23,12 +24,12 @@ struct Stats {
2324
storage_item_count: usize,
2425
}
2526

26-
/// Reads the era2 file and prints stats about it.
27+
/// Reads the era2 file, validates the format, and prints stats about it.
2728
///
2829
/// It can be run with following command:
2930
///
3031
/// ```bash
31-
/// cargo run -p e2store --bin era2-stats --features era2-stats-binary -- <path>
32+
/// cargo run --release -p e2store --bin era2-stats --features era2-stats-binary -- <path>
3233
/// ```
3334
fn main() -> anyhow::Result<()> {
3435
trin_utils::log::init_tracing_logger();
@@ -41,18 +42,34 @@ fn main() -> anyhow::Result<()> {
4142
reader.header.header.number
4243
);
4344

45+
let mut last_address_hash = B256::ZERO;
46+
4447
let mut stats = Stats::default();
4548
while let Some(entry) = reader.next() {
4649
let AccountOrStorageEntry::Account(account) = entry else {
4750
bail!("Expected account entry");
4851
};
4952
stats.account_count += 1;
5053

54+
assert!(
55+
account.address_hash > last_address_hash,
56+
"Expected increasing order of accounts: {last_address_hash} is before {}",
57+
account.address_hash
58+
);
59+
last_address_hash = account.address_hash;
60+
61+
assert_eq!(
62+
keccak256(&account.bytecode),
63+
account.account_state.code_hash,
64+
"Invalid code hash",
65+
);
66+
5167
if !account.bytecode.is_empty() {
5268
stats.bytecode_count += 1;
5369
}
5470

55-
for _ in 0..account.storage_count {
71+
let mut last_storage_item = B256::ZERO;
72+
for index in 0..account.storage_count {
5673
let Some(AccountOrStorageEntry::Storage(storage)) = reader.next() else {
5774
bail!(
5875
"Expected storage entry for account: {}",
@@ -61,6 +78,28 @@ fn main() -> anyhow::Result<()> {
6178
};
6279
stats.storage_entry_count += 1;
6380
stats.storage_item_count += storage.len();
81+
82+
// Check that every storage entry is full (has 10M items), except the last one.
83+
if index + 1 < account.storage_count {
84+
assert_eq!(
85+
storage.len(),
86+
era2::MAX_STORAGE_ITEMS,
87+
"Non-final storage entry (address_hash: {}, index: {index}/{}) should be full, but has {} items instead",
88+
account.address_hash,
89+
account.storage_count,
90+
storage.len(),
91+
);
92+
}
93+
94+
for item in storage.iter() {
95+
assert!(
96+
item.storage_index_hash > last_storage_item,
97+
"Expected increasing order of storage items (address hash: {}): {last_storage_item} is before {}",
98+
account.address_hash,
99+
item.storage_index_hash,
100+
);
101+
last_storage_item = item.storage_index_hash;
102+
}
64103
}
65104

66105
if stats.account_count % 1_000_000 == 0 {

0 commit comments

Comments
 (0)