You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 5776c3b
Browse filesBrowse the repository at this point in the historyBrowse files
docs: Adds a new seidb evm-logical-digest command that computes a backend-independent digest of EVM logical state (account/code/storage) so memiavl and flatkv nodes can be compared at the same height. (sei-protocol/sei-chain#3611)
Copy file name to clipboardExpand all lines: node/technical-reference.mdx
+42Lines changed: 42 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -71,6 +71,48 @@ The emitted JSON contains the following fields:
71
71
72
72
73
73
74
+
#### Comparing EVM State Across Backends
75
+
76
+
The `evm-logical-digest` subcommand computes a backend-independent digest of the EVM logical state (the account, code, and storage buckets) so that a memIAVL node and a FlatKV node can be compared at the same chain height. Because a freshly migrated FlatKV node stamps a per-key `blockHeight` into each value that differs from the memIAVL leaf versions, a raw byte-for-byte digest would diverge even when the underlying EVM state is identical. This command strips the serialization-version and `blockHeight` header on both sides and digests only the height-independent logical payload (storage word, bytecode, or balance+nonce+codehash), producing a comparable `FINAL_DIGEST` per backend.
77
+
78
+
```bash
79
+
# FlatKV digest at a height (WAL-replays to it). Prints per-bucket
80
+
# bucket_digest values and one FINAL_DIGEST line for backend comparison.
Two backends match when the FlatKV `FINAL_DIGEST` equals the memIAVL `FINAL_DIGEST`. FlatKV also writes an internal migration-version marker row that a memiavl-only node never owns, so the command omits that row from the final comparison automatically.
98
+
99
+
The command accepts the following flags:
100
+
101
+
-`--backend` — backend to read: `flatkv` or `memiavl`.
102
+
-`--db-dir` (`-d`) — for FlatKV, the FlatKV data directory; for memIAVL, the memIAVL root directory containing `current/` and `snapshot-*`.
103
+
-`--height` — target version. FlatKV WAL-replays to it; memIAVL resolves `snapshot-<height>/evm` (`0` selects the `current` symlink).
104
+
-`--memiavl-normalization` — memIAVL normalization mode: `semantic`/`independent` (raw EVM key/value decoder, the default `semantic`) or `translator` (current migration mapping).
105
+
-`--inspect-bucket` — inspect one normalized bucket (`account`, `code`, `storage`, or `legacy`) instead of printing the global digest.
106
+
-`--key-offset` — inspect mode: byte offset into the physical key before applying `--key-prefix` or sharding.
107
+
-`--key-prefix` — inspect mode: hex prefix, relative to `--key-offset`, used to filter physical keys.
108
+
-`--shard-next-bytes` — inspect mode: group matching keys by this many bytes after `--key-prefix`.
109
+
-`--list` — inspect mode: list matching key/logical-value pairs instead of shard `bucket_digest` values.
110
+
-`--list-limit` — inspect mode: maximum pairs to print with `--list` (default `1000`; a value `<= 0` means unlimited).
111
+
-`--details` — inspect list mode: include backend-specific version metadata.
112
+
-`--find-hash` — optional 32-byte hex per-entry hash to hunt for. When two `bucket_digest` values differ by exactly one entry, their XOR is that entry's hash; this prints every matching entry so a single diverging row can be located.
113
+
114
+
115
+
74
116
### Autobahn (GigaRouter) Config Generation
75
117
76
118
When running with the Autobahn (GigaRouter) networking layer, you can generate the Autobahn JSON config from a set of node directories. Each directory must contain `validator_pubkey.txt`, `node_pubkey.txt`, `autobahn_address.txt`, and `evmrpc_url.txt`.
### Comparing EVM State Between memIAVL and FlatKV
128
+
129
+
When debugging an AppHash mismatch that involves EVM state, a byte-for-byte physical dump can diverge between backends even when the underlying state is identical. This is because every FlatKV value embeds a per-key block-height stamp (the height the key was last written or migrated), which differs from the memIAVL leaf versions on a freshly migrated node.
130
+
131
+
The `evm-logical-digest` command works around this by computing a backend-independent digest of the EVM *logical* state — it strips the serialization-version and block-height header on both sides and digests only the logical payload (account balance/nonce/code hash, bytecode, and storage words). This lets a memIAVL node and a FlatKV node be compared at the same chain height:
Each run prints per-bucket `bucket_digest` values and a single `FINAL_DIGEST` line covering the `account`, `code`, `storage`, and `legacy` buckets. Compare the `FINAL_DIGEST` lines from both backends at the same height — they should match. Because FlatKV can contain a FlatKV-only migration-version marker that a memIAVL-only node never owns, that row is automatically omitted from the FlatKV final result so the comparison is apples-to-apples.
144
+
145
+
The `evm-logical-digest` command accepts the following flags:
146
+
147
+
-`--backend`: backend to read (`flatkv` or `memiavl`).
148
+
-`--db-dir` / `-d`: for FlatKV, the FlatKV data directory; for memIAVL, the memIAVL root directory (containing `current/` and `snapshot-*`).
149
+
-`--height`: target version. FlatKV WAL-replays to it; memIAVL resolves `snapshot-<height>/evm` (`0` selects the `current` symlink).
150
+
-`--memiavl-normalization`: memIAVL normalization mode — `semantic`/`independent` (raw EVM key/value decoder, the default) or `translator` (routes each leaf through the current migration mapping).
151
+
152
+
For targeted debugging, the command also supports inspecting a single normalized bucket instead of printing the global digest:
153
+
154
+
-`--inspect-bucket`: inspect one bucket (`account`, `code`, `storage`, or `legacy`) instead of the global digest.
155
+
-`--key-offset`: byte offset into the physical key before applying `--key-prefix` and sharding.
156
+
-`--key-prefix`: hex prefix, relative to `--key-offset`, used to filter physical keys.
157
+
-`--shard-next-bytes`: group matching keys by this many bytes after `--key-prefix`.
158
+
-`--list`: list matching key/logical-value pairs instead of shard digests.
159
+
-`--list-limit`: maximum pairs to print with `--list` (default `1000`; `<=0` means unlimited).
160
+
-`--details`: include backend-specific version metadata in list mode.
161
+
-`--find-hash`: a 32-byte hex per-entry hash to hunt for. When two `bucket_digest` values differ by exactly one entry, their XOR is that entry's hash; passing it prints every matching entry as a `FOUND-HASH` line.
162
+
163
+
For example, to list the first 50 `account` rows with version metadata, or to shard the `storage` bucket under a key prefix by the next 2 bytes:
**The legacy IAVL backend has been fully removed and SeiDB State Commit (SC) is now mandatory.** SC must be enabled via `sc-enable = true` in the `[state-commit]` section of `app.toml`. If SC is not enabled, the node no longer falls back to IAVL — it panics at startup with:
0 commit comments