Skip to content

Add balance support to flatKV - #4101

Open
cody-littley wants to merge 3 commits into
mainfrom
cjl/flatkv-balance
Open

Add balance support to flatKV#4101
cody-littley wants to merge 3 commits into
mainfrom
cjl/flatkv-balance

Conversation

@cody-littley

@cody-littley cody-littley commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Describe your changes and provide context

Support reading/writing account balances in FlatKV.

Note that SS does not currently support an EVM balance key. That's out of scope for this PR and still needs to be added. Nothing writes this key type yet, so it doesn't break production code.

@cody-littley cody-littley self-assigned this Sep 4, 2026
@cursor

cursor Bot commented Sep 4, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes EVM account merge, read, iterate, and import/export semantics for a new persisted field; mistakes could corrupt or mis-report balances once writers land, though production does not emit balance keys yet.

Overview
Adds a new EVM logical key family EVMKeyBalance (on-disk prefix 0x21, mirrored in x/evm/types via BalanceKey) and threads it through FlatKV so balances are stored alongside nonce and code hash in a single accountDB row.

Commit and import paths now merge balance changes with nonce/codehash updates (mergeAccountUpdates, readAccountsForMerge, ImportTranslator), route balance keys to accountDB, and project balance through Get, GetBalance, and a new account balance iterator lane (same physical 0x0a rows as other account fields). Zero balance is treated like deletion for presence semantics; deleting a nonce in tests/workloads also clears sibling codehash/balance keys so merged-row behavior stays consistent.

Tooling and tests extend the composite random oracle, export/import round-trips, snapshot rollback, and evm_logical_digest / flatkv_state_size classification so balance participates in the same invariants as other account fields. Per the PR note, state sync / app writers for this key are still out of scope—the key type exists but nothing in production emits it yet.

Reviewed by Cursor Bugbot for commit 1a086bc. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedSep 4, 2026, 7:12 PM

@codecov

codecov Bot commented Sep 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.00000% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.62%. Comparing base (0e7d002) to head (1a086bc).

Files with missing lines Patch % Lines
sei-db/state_db/sc/flatkv/store_iteration.go 64.70% 3 Missing and 3 partials ⚠️
...b/tools/cmd/seidb/operations/evm_logical_digest.go 37.50% 3 Missing and 2 partials ⚠️
sei-db/state_db/sc/flatkv/store_read.go 90.47% 2 Missing ⚠️
x/evm/types/keys.go 0.00% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4101      +/-   ##
==========================================
- Coverage   61.19%   60.62%   -0.57%     
==========================================
  Files        2196     2107      -89     
  Lines      193277   183335    -9942     
==========================================
- Hits       118272   111144    -7128     
+ Misses      63783    61704    -2079     
+ Partials    11222    10487     -735     
Flag Coverage Δ
sei-chain-pr 35.82% <61.11%> (?)
sei-db 69.80% <ø> (ø)
sei-db-state-db ?
sei-db-state-db-pr 74.80% <85.96%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
sei-db/common/keys/evm.go 80.35% <100.00%> (+2.35%) ⬆️
sei-db/state_db/sc/flatkv/import_translator.go 84.84% <100.00%> (+3.03%) ⬆️
sei-db/state_db/sc/flatkv/ktype/ktype.go 87.23% <100.00%> (ø)
sei-db/state_db/sc/flatkv/state_view.go 75.23% <100.00%> (-1.13%) ⬇️
sei-db/state_db/sc/flatkv/store.go 78.75% <100.00%> (ø)
sei-db/state_db/sc/flatkv/store_apply.go 88.51% <100.00%> (+3.22%) ⬆️
...db/tools/cmd/seidb/operations/flatkv_state_size.go 63.86% <100.00%> (ø)
sei-db/state_db/sc/flatkv/store_read.go 65.54% <90.47%> (+3.22%) ⬆️
x/evm/types/keys.go 95.38% <0.00%> (-3.03%) ⬇️
...b/tools/cmd/seidb/operations/evm_logical_digest.go 24.42% <37.50%> (+0.11%) ⬆️
... and 1 more

... and 131 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d7152b0. Configure here.

Comment thread sei-db/state_db/ss/evm/types.go Outdated
Comment thread sei-db/state_db/sc/flatkv/store_read.go

@seidroid seidroid Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Wires the new 0x21 balance key kind through flatkv's read, write, iterate, import/export, SS-split and digest paths; the merge/zero-is-absent semantics are consistent with the existing codehash handling and are well covered by tests. One non-blocking upgrade concern: adding StoreBalance to AllEVMStoreTypes changes the on-disk sub-DB set in SS separate-DB mode.

Findings: 0 blocking | 1 non-blocking | 1 posted inline

Blockers

  • None at the file/PR level.

Non-blocking

  • None at the file/PR level.
  • 1 suggestion(s)/nit(s) flagged inline on specific lines.

Comment thread sei-db/state_db/ss/evm/types.go Outdated
Comment thread sei-db/state_db/ss/evm/types.go Outdated
StoreMisc = commonevm.EVMKeyMisc // Catch-all: codesize, address mappings, receipts, etc.
// StoreBalance is reserved for future migration; balances currently use tendermint store
StoreBalance EVMStoreType = 100
StoreBalance = commonevm.EVMKeyBalance

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

openDBs creates a fresh balance/ Pebble DB at version 0 whenever SeparateEVMSubDBs is on. GetLatestVersion is the minimum across managedDBs, so a store that was at height N reports 0 after upgrade with this change.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

All SS changes have been removed in this PR

@cody-littley

Copy link
Copy Markdown
Contributor Author

@seidroid review

seidroid[bot]
seidroid Bot previously requested changes Sep 4, 2026

@seidroid seidroid Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The flatkv side of the new 0x21 balance kind is thorough and well tested (read/write/merge/iterate/import-export/digest all covered). However, ParseEVMKey is a repo-wide router, and two of its consumers in the SS/composite layer were not updated for the new kind: the SS EVM store has no sub-DB for EVMKeyBalance and silently drops it, and convertFlatKVNodes drops the balance field when translating flatkv account rows into snapshot nodes.

Findings: 2 blocking | 2 non-blocking | 1 posted inline

Blockers

  • convertFlatKVNodes (sei-db/state_db/ss/composite/store.go:509-533) drops balances. A flatkv account row arrives with physical prefix 0x0a, so ParseEVMKey classifies it EVMKeyNonce, and that branch emits a nonce node plus a codehash node when the hash is non-zero — but nothing for the balance field, which this PR makes writable. On a state-sync restore that feeds a flatkv snapshot into the composite SS store (Import → convertFlatKVNodes, store.go:619), every account balance is silently lost; the restored SS has correct nonces and codehashes and zero balances. The mirrored helper collectFlatKVEVM in sei-cosmos/storev2/rootmulti/flatkv_helpers_test.go:454 replicates the same conversion for the flatkv↔memiavl equivalence assertions and would need the same addition, otherwise that test keeps passing against the lossy conversion. No writer produces 0x21 keys yet, so this is latent today — but it is silent data loss the moment one lands.
  • 1 blocking issue(s) flagged inline on specific lines.

Non-blocking

  • [suggestion] Balance-only accounts widen the phantom-nonce divergence. buildAccountNonceLane (store_iteration.go:380) emits a zero nonce for every live row, unlike the codehash and new balance lanes which skip their zero value — so an account held up only by its balance yields a 0x0a||addr → 0 entry that memiavl does not have. addBalanceOnlyAccount in store_iteration_test.go now asserts exactly that. Today this is harmless because codehash-only-with-zero-nonce accounts are rare, but once balances are written a funded EOA that has never sent a transaction is the common case, and each one becomes a phantom nonce row in iteration, in the exporter, and in convertFlatKVNodes output. The composite random framework never generates the case (newRandomEVMEntry case 0 always writes a nonce), so nothing currently catches it. Worth settling the intended semantics before a balance writer lands rather than after.
  • 1 non-blocking pre-existing issue(s) listed below under pre-existing issues.

Pre-existing issues

  • [suggestion] GetBlockHeightModified (sei-db/state_db/sc/flatkv/store_read.go:113-121) answers with the merged account row's block height for whichever field the key names, so a nonce-only update at height N reports the codehash as modified at N too — and now the balance as well. The same branch returns found=true for a field that is zero, while Get on that key returns found=false for the same row, so the two reads disagree on existence. This already applied to codehash on the base branch; the PR extends the existing behaviour to a third field rather than introducing it, and no test covers the cross-field case for either.

Comment thread sei-db/common/keys/evm.go
@cody-littley

Copy link
Copy Markdown
Contributor Author

@seidroid review

@cody-littley
cody-littley added this pull request to the merge queue Sep 4, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants