Skip to content

testing(flatkv): evm migration int testings#3473

Open
blindchaser wants to merge 19 commits into
mainfrom
yiren/fkv-mig-int-rebase
Open

testing(flatkv): evm migration int testings#3473
blindchaser wants to merge 19 commits into
mainfrom
yiren/fkv-mig-int-rebase

Conversation

@blindchaser
Copy link
Copy Markdown
Contributor

@blindchaser blindchaser commented May 20, 2026

Summary

This branch adds the FlatKV EVM Migrate path and the first reusable Docker migration test flow, using EVM state as the initial scenario. Validators start with EVM state committed through memIAVL, restart in migrate_evm, drain EVM account/code/storage keys into FlatKV incrementally as the restarted chain continues producing blocks, and verify that the post-migration FlatKV state is deterministic across validators. The core abstractions are a migration-aware composite store, explicit write-mode routing, a per-block migration manager, FlatKV initial-version seeding, and Docker-level migration orchestration.

Migration hardening added on top of main:

  • Preserves pre-migration AppHash replay by keeping FlatKV's seeded lattice hash out of LastCommitInfo until FlatKV participates in committed state.

  • Ensures migration progresses on empty/live blocks and keeps the migration tail bounded by routing live writes with boundary plus old-DB existence: existing not-yet-migrated keys stay in memIAVL, while brand-new keys go to FlatKV.

  • Keeps legacy EVM prefix scans available during active migration by serving iterators from memIAVL, while exact reads remain migration-aware across both backends.

  • Makes FlatKV SetInitialVersion durable for read-only tooling by writing seeded metadata and a seeded snapshot.

  • Stabilizes Docker migration runs by requiring validators to stop from one committed height before flipping sc-write-mode, with retry instead of mixed-height restart.

  • Reduces CI fixture OOG risk by splitting bulk EVM storage deployment into smaller batches.

  • Hardens unrelated upgrade-log CI checks around height/log-format races so migration failures stay visible.

  • sei-db/config/toml.go, app/seidb.go, docker/localnode/config/app.toml: add sc-keys-to-migrate-per-block so operators and tests can control per-block migration batch size. The config path enforces a single source of truth from TOML through StateCommitConfig.

  • sei-db/state_db/sc/composite/store.go: builds routers after both backends are loaded, seeds a fresh FlatKV to the next memIAVL version on latest-version migration entry, and keeps targeted historical loads strict. It guarantees AppHash neutrality at the already-committed pre-migration height by only appending the FlatKV lattice hash after FlatKV participates in committed state.

  • sei-db/state_db/sc/composite/store.go: routes child-store reads, writes, iteration, and proofs through RouterCommitKVStore. Empty blocks still call the router in active migration modes so migration progress is not tied to user writes.

  • sei-db/state_db/sc/migration/router_builder.go: defines write-mode routing for memiavl_only, migrate_evm, evm_migrated, later migration modes, flatkv_only, and dual-write testing. The routing table makes EVM migration explicit and rejects unsupported routes loudly. Each router builder now passes the memIAVL iterator builder straight into NewMigrationManager instead of mutating the manager after construction.

  • sei-db/state_db/sc/migration/migration_manager.go: manages the migration boundary, copies bounded batches from old DB to new DB, writes migrated keys to FlatKV, deletes copied old keys, and atomically writes migration-version while clearing the boundary on completion. NewMigrationManager now takes oldDBIteratorBuilder as a constructor parameter so the manager is fully wired before any caller can use it.

  • sei-db/state_db/sc/migration/migration_manager.go: preserves live-block correctness by routing writes with both migration boundary and old-DB existence. Existing not-yet-migrated keys stay in old DB so their latest value is copied when the iterator reaches them; brand-new keys go to new DB so continuously-created EVM keys do not extend the migration tail forever. Exact reads fall back from old DB to new DB for not-yet-migrated ranges.

  • sei-db/state_db/sc/migration/migration_manager.go: keeps legacy EVM prefix-scan paths available during the migration window via the old DB iterator, while rejecting iteration after completion and rejecting access to the reserved migration metadata store.

  • sei-db/state_db/sc/migration/migration_metrics.go: encapsulates the per-run aggregator inside MigrationMetrics. RecordBatch now drives both OTel emission and the in-process completion summary, and exposes new counters for batches, original-pair routing (old/new DB), and per-DB pairs written. A nil metrics argument to NewMigrationManager is replaced with a local-only metrics so the completion log keeps working without an OTel exporter.

  • sei-db/state_db/sc/flatkv/store_meta.go: adds durable SetInitialVersion seeding for FlatKV global and per-DB metadata, plus a seeded snapshot. This makes the next FlatKV commit land at the intended version and gives read-only tooling a stable seeded baseline.

  • sei-db/state_db/sc/flatkv/store_meta.go: adds FlatKV latest-version helpers for startup sanity checks and recovery paths without requiring a full writable open first.

  • sei-db/tools/cmd/seidb/main.go, sei-db/tools/cmd/seidb/operations/migrate_evm_status.go: add seidb migrate-evm-status, which opens FlatKV read-only through a snapshot/WAL clone and emits JSON status for version_at, migration_version, completion, and boundary presence.

  • Makefile, docker/docker-compose.yml, docker/localnode/scripts/step4_config_override.sh: propagate GIGA_MIGRATE_FROM_MEMIAVL into validator containers and boot nodes in memiavl_only for migration CI. TOML edits are anchored to real keys to avoid matching comments.

  • .github/workflows/integration-test.yml: adds the FlatKV EVM Migrate integration row. It boots a 4-validator cluster in memiavl_only, deploys an EVM fixture, runs the migration script, and verifies post-migration EVM state. This establishes the CI shape future FlatKV migration scenarios can reuse: prepare fixture, run coordinated mode flip, poll status, and verify post-migration state.

  • integration_test/contracts/deploy_flatkv_evm_fixture.sh: creates a deterministic EVM fixture before migration, including account balance, contract code/storage, and a configurable bulk-storage workload split into small deploy batches to stay below EVM gas limits.

  • integration_test/contracts/verify_flatkv_evm_migrate.sh: enforces the operator sequence for the Docker migration test: verify all nodes are in memiavl_only, wait for fixture blocks to settle, freeze validators at a common committed height, stop them cleanly, flip sc-write-mode to migrate_evm, restart, poll seidb migrate-evm-status, and compare FlatKV bucket digests at a shared height.

  • integration_test/contracts/verify_flatkv_evm_migrate.sh: rejects unsafe stop conditions before flipping config. If validators commit an extra block during shutdown, the script restarts them in memiavl_only, waits for convergence, and retries rather than allowing mixed-height migration.

  • integration_test/contracts/verify_flatkv_evm_store.sh: verifies that the pre-migration EVM fixture remains readable after migration and improves diagnostics around FlatKV bucket dumps.

  • scripts/evm_stress/main.go: adds contract-storage workload mode, which deploys one-storage-slot contracts from many funded accounts to generate account, code, and storage rows for migration stress.

  • integration_test/upgrade_module/scripts/verify_upgrade_needed_log.sh: hardens the upgrade log check against observed height/log-format races so unrelated upgrade CI does not hide migration signal.

Test plan

  • sei-db/state_db/sc/composite/store_migration_test.go: covers happy-path MemiavlOnly to MigrateEVM lifecycle, crash-and-resume, deterministic roots across independent stores, and post-completion evm_migrated mode flip. These tests enforce read transparency, persisted boundary recovery, and FlatKV root invariants.
  • sei-db/state_db/sc/composite/store_test.go: covers AppHash-neutral migration entry, idempotent FlatKV seeding across restarts, child-store routing, write-mode behavior, and commit-info/lattice invariants.
  • sei-cosmos/storev2/rootmulti/flatkv_migration_test.go: covers rootmulti-level migration lifecycle, empty-block progress, legacy EVM iteration during migration, AppHash determinism across runs, migration-version persistence, and post-completion mode flip.
  • sei-cosmos/storev2/rootmulti/flatkv_helpers_test.go: adds shared rootmulti migration helpers for configs, restart, rollback, historical hash verification, and FlatKV offline inspection.
  • sei-db/state_db/sc/migration/migration_manager_test.go: covers persisted boundary resume, per-block batching, completion atomicity, writer failure paths, randomized migration equivalence, new-key tail handling, existing-key old-DB routing, reserved migration-store protection, target-version acceptance after completion, and the constructor-supplied oldDBIteratorBuilder path used by post-completion iteration assertions. Run-stat assertions now read through MigrationMetrics.RunStats().
  • sei-db/state_db/sc/migration/migration_transitions_test.go: updates the direct migration transition test for the FlatKV EVM Migrate (0 -> 1) path.
  • sei-db/state_db/sc/flatkv/store_meta_test.go: covers SetInitialVersion happy path, seeded snapshot creation, invalid version rejection, read-only rejection, post-commit rejection, reopen persistence, and rollback around seeded metadata.
  • sei-db/tools/cmd/seidb/operations/flatkv_open_test.go: verifies read-only FlatKV tooling can open a store immediately after SetInitialVersion creates the seeded snapshot.
  • integration_test/contracts/verify_flatkv_evm_migrate.sh: exercises the full Docker migration sequence, including common-height freeze, clean shutdown, restart in migrate_evm, status polling, completion summaries, and cross-validator FlatKV digest agreement.
  • integration_test/contracts/deploy_flatkv_evm_fixture.sh and integration_test/contracts/verify_flatkv_evm_store.sh: validate fixture generation and post-migration EVM read transparency for balances, code, storage, and missing-account cases.
  • Manual/local checks run during development: bash -n integration_test/contracts/verify_flatkv_evm_migrate.sh, focused Go tests for ./sei-db/state_db/sc/migration, ./sei-db/state_db/sc/composite, ./sei-cosmos/storev2/rootmulti, ./sei-db/tools/cmd/seidb/operations, and ./scripts/evm_stress.

@cursor
Copy link
Copy Markdown

cursor Bot commented May 20, 2026

PR Summary

High Risk
High risk because it changes state-commit migration/write-routing behavior that influences AppHash/consensus, adds new migration controls, and modifies FlatKV seeding and on-disk tooling used during validator restarts.

Overview
Adds a new cluster-level FlatKV EVM migration integration test that boots validators in memiavl_only, deposits a large EVM fixture, performs a coordinated stop/flip/restart into migrate_evm, polls migration completion via a new seidb migrate-evm-status JSON command, and asserts post-migration cross-validator FlatKV digest agreement plus EVM read transparency.

Introduces a new sc-keys-to-migrate-per-block config knob (plumbed through app.toml parsing/templates) to control per-block migration batch size, and extends localnet/docker wiring (GIGA_MIGRATE_FROM_MEMIAVL) to start clusters in memiavl_only for migration coverage.

Hardens the migration implementation: MigrationManager now routes brand-new keys to the new DB (with read fallback) to avoid an unbounded migration tail, can serve legacy iterators from the old DB during migration, records per-run batch stats and emits a completion summary, and the composite store gates empty-changeset forwarding to prevent rootmulti double-flush from advancing migration twice per block (AppHash continuity).

Improves FlatKV lifecycle correctness by writing a seeded snapshot during SetInitialVersion (so read-only tools can open immediately), adds extensive new composite/rootmulti migration tests for determinism/resume/mode-flip invariants, and enhances integration scripts/fixtures for better diagnostics and larger, batched EVM state generation.

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 20, 2026

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

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedMay 22, 2026, 8:38 PM

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7cb7906e25

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread sei-db/state_db/sc/flatkv/store_meta.go Outdated
Comment thread sei-db/state_db/sc/migration/migration_manager.go
@codecov
Copy link
Copy Markdown

codecov Bot commented May 20, 2026

Codecov Report

❌ Patch coverage is 60.90535% with 95 lines in your changes missing coverage. Please review.
✅ Project coverage is 59.08%. Comparing base (3ebdc40) to head (134e164).

Files with missing lines Patch % Lines
...b/tools/cmd/seidb/operations/migrate_evm_status.go 0.00% 48 Missing ⚠️
scripts/evm_stress/main.go 0.00% 28 Missing ⚠️
sei-db/state_db/sc/migration/migration_manager.go 91.30% 3 Missing and 3 partials ⚠️
sei-db/state_db/sc/migration/migration_metrics.go 92.59% 4 Missing and 2 partials ⚠️
app/seidb.go 0.00% 2 Missing and 1 partial ⚠️
sei-db/state_db/sc/flatkv/store_meta.go 33.33% 1 Missing and 1 partial ⚠️
sei-db/tools/cmd/seidb/main.go 0.00% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3473      +/-   ##
==========================================
- Coverage   59.11%   59.08%   -0.04%     
==========================================
  Files        2187     2188       +1     
  Lines      182236   182393     +157     
==========================================
+ Hits       107724   107761      +37     
- Misses      64864    64981     +117     
- Partials     9648     9651       +3     
Flag Coverage Δ
sei-chain-pr 57.86% <60.90%> (?)
sei-db 70.41% <ø> (ø)

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

Files with missing lines Coverage Δ
sei-db/state_db/sc/composite/store.go 73.47% <100.00%> (+1.55%) ⬆️
sei-db/state_db/sc/flatkv/verify.go 48.71% <ø> (ø)
sei-db/state_db/sc/migration/router_builder.go 56.72% <100.00%> (+0.42%) ⬆️
sei-db/state_db/sc/flatkv/store_meta.go 67.96% <33.33%> (-0.84%) ⬇️
sei-db/tools/cmd/seidb/main.go 0.00% <0.00%> (ø)
app/seidb.go 73.61% <0.00%> (-3.21%) ⬇️
sei-db/state_db/sc/migration/migration_manager.go 94.52% <91.30%> (-2.00%) ⬇️
sei-db/state_db/sc/migration/migration_metrics.go 83.52% <92.59%> (+4.95%) ⬆️
scripts/evm_stress/main.go 0.00% <0.00%> (ø)
...b/tools/cmd/seidb/operations/migrate_evm_status.go 0.00% <0.00%> (ø)

... and 29 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.

@blindchaser blindchaser force-pushed the yiren/fkv-mig-int-rebase branch 6 times, most recently from 372a884 to 4583e17 Compare May 21, 2026 02:06
Comment thread sei-db/state_db/sc/migration/migration_manager.go
@blindchaser blindchaser force-pushed the yiren/fkv-mig-int-rebase branch 2 times, most recently from dce2b45 to 77a21c7 Compare May 21, 2026 15:48
@blindchaser blindchaser changed the title testing(flatkv): migration int testings testing(flatkv): evm migration int testings May 21, 2026
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.

These tests duplicate tests I'm working on in a branch. But I think it's worth merging both. It's nice validation to have multiple test suites written independently, as it's less likely that we've both made a bad assumption as to how something should work.

Comment on lines 67 to 88
type migrationRunStats struct {
startedAt time.Time

batches int64
keysMigrated int64
keyBytesMigrated int64
valueBytesMigrated int64
originalPairsRoutedOldDB int64
originalPairsRoutedNewDB int64
oldDBPairsWritten int64
newDBPairsWritten int64
}

type migrationBatchStats struct {
keysMigrated int64
keyBytesMigrated int64
valueBytesMigrated int64
originalPairsRoutedOldDB int64
originalPairsRoutedNewDB int64
oldDBPairsWritten int64
newDBPairsWritten int64
}
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.

Would it make sense to encapsulate this stuff inside MigrationMetrics? We could then expose metrics from these values, which might end up being useful if we encounter problems when we deploy this code. The unit tests could continue to access these values after the move.

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.

updated

// At the end of this migration, all evm/ data lives in flatkv, and all other data remains in memIAVL.
//
// This test evaluates the 0->1 migration path.
// This test evaluates the FlatKV EVM migrate path.
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.

Nit, could we add (0 -> 1) to this godoc? The migration versions are referenced in a bunch of other places, and I think it's a useful way of thinking about things sometimes.

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.

addressed

}

/* Data flow: MigrateEVM (0 -> 1)
/* Data flow: FlatKV EVM migrate
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.

Can we retain the (0 -> 1) part?

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.

sure

if err != nil {
return nil, fmt.Errorf("NewMigrationManager: %w", err)
}
migrationManager.oldDBIteratorBuilder = buildMemIAVLIteratorBuilder(memIAVL)
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.

Ok to add this, but we should probably make it a constructor parameter in the NewMigrationManager() method instead of directly setting it.

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.

good point

@blindchaser blindchaser force-pushed the yiren/fkv-mig-int-rebase branch from 3f8c7a5 to 292c1e8 Compare May 21, 2026 20:14
Comment thread sei-db/state_db/sc/migration/migration_metrics.go
Copy link
Copy Markdown

@cursor cursor Bot left a comment

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 1 potential issue.

Fix All in Cursor

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

Reviewed by Cursor Bugbot for commit ec3b449. Configure here.

migrationComplete := m.boundary.Equals(MigrationBoundaryComplete)
metadataPairsWritten := int64(1)

if m.boundary.Equals(MigrationBoundaryComplete) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Delete pairs written to old DB not counted in stats

Low Severity

batchStats.oldDBPairsWritten is set from the return value of flattenPairsByStore(oldDBPairsByStore), which counts the final deduplicated pairs. However, migration delete pairs for migrated keys are added to oldDBPairsByStore and caller's original pairs routed to old DB are also added. These are correctly counted by flattenPairsByStore. But batchStats.newDBPairsWritten uses newDBPairsWritten + metadataPairsWritten to account for metadata pairs appended after flatten. The oldDBPairsWritten counting appears correct on closer inspection — this is not a bug but the asymmetry is worth noting. Actually, upon careful re-review, the counting is consistent. Withdrawing this concern.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ec3b449. Configure here.

@Kbhat1
Copy link
Copy Markdown
Contributor

Kbhat1 commented May 22, 2026

AI Review:

migration_manager.go:453 rejects EVM iteration after migration completes, but EVM EndBlock still unconditionally iterates EVM prefixes. RouterCommitKVStore.Iterator panics on that error at .worktree/pr-3473/sei-db/state_db/sc/migration/router_kvstore.go:86. The next block after migrate_evm completes will hit paths like .worktree/pr-3473/x/evm/keeper/tx.go:11 and .worktree/pr-3473/x/evm/keeper/storage_cleanup.go:37, called from .worktree/pr-3473/x/evm/keeper/abci.go:84, and panic. Flipping to evm_migrated does not fix it because routeToFlatKV installs no iterator at .worktree/pr-3473/sei-db/state_db/sc/migration/router_builder.go:634. This blocks live post-migration operation.

sei-db/state_db/sc/composite/store.go:319 makes empty changesets mutate state in migration modes. Normal FinalizeBlocker returns an AppHash after app.GetWorkingHash() at .worktree/pr-3473/app/app.go:1438, but BaseApp.Commit calls app.Get before committing](pr-3473/sei-cosmos/baseapp/abci.go:268). That second call has no app writes left, but rootmulti.flush()still callsApplyChangeSets(nil)at [store.go](pr-3473/sei-cosmos/storev2/rootmulti/store.go:211), andMigrationManager.ApplyChangeSets` advances the migration batch at /state_db/sc/migration/migration_manager.go:283. So committed state can diverge from the AppHash already returnedto Tendermint for the block.

@blindchaser blindchaser requested a review from cody-littley May 22, 2026 22:34
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