Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
662b214
build routers
Apr 28, 2026
da2a545
remove dual write test
Apr 28, 2026
865ef84
remove split write tests
Apr 28, 2026
879dac7
incremental progress
Apr 29, 2026
6c4927f
expand route API
Apr 29, 2026
1b7c9ab
add helper method to build a route to a migration manager
Apr 29, 2026
af35c76
Merge branch 'cjl/expanded-route-api' into cjl/migration-integration
Apr 29, 2026
fa89b45
cleanup
Apr 29, 2026
75a3b7c
made suggested change
Apr 29, 2026
3710f59
Merge branch 'cjl/expanded-route-api' into cjl/migration-integration
Apr 29, 2026
e0744b9
revert lots of changes
Apr 29, 2026
94c5e57
test utilities
Apr 29, 2026
78eb3bb
incremental progress on tests
Apr 29, 2026
2a6c03e
test evm migration
Apr 29, 2026
8a303e9
determinism
Apr 29, 2026
3900541
cleanup
Apr 29, 2026
d9fefc8
test post evm migration
Apr 29, 2026
eee79af
added next test
Apr 30, 2026
0b3cc6e
all migrated but bank
Apr 30, 2026
4f140de
final test
Apr 30, 2026
175b0f5
add thread safe wrapper
Apr 30, 2026
65c31dd
various fixes
Apr 30, 2026
2fc730a
Merge branch 'main' into cjl/migration-integration
May 1, 2026
97d0acc
implement thread safe router
May 1, 2026
ecd5a92
Add router based implementation of kvstore
May 1, 2026
8c9961c
made suggested changes
May 4, 2026
d0aead6
Merge branch 'cjl/thread-safe-router' into cjl/migration-integration
May 4, 2026
ee043b8
remove unused methods
May 4, 2026
ddafa97
Merge branch 'main' into cjl/migration-integration
May 4, 2026
9449881
test framework for migration tests
May 4, 2026
34d0dbe
made suggested changes
May 5, 2026
2f50f90
Merge branch 'cjl/migration-test-framework' into cjl/migration-integr…
May 5, 2026
cc367cd
Merge branch 'main' into cjl/migration-integration
May 5, 2026
247308f
Add replacement APIs for methods we intend to deprecate.
May 6, 2026
976c934
Merge branch 'main' into cjl/replacement-apis
May 6, 2026
0939d8d
fix tests
May 6, 2026
68a9dc1
Merge branch 'main' into cjl/migration-integration
May 6, 2026
4265c58
remove ctx
May 6, 2026
17915ce
Constants for migration code
May 6, 2026
d548214
made suggested change
May 6, 2026
5c2b89d
made suggested change
May 6, 2026
5e8524a
Merge branch 'cjl/migration-constants' into cjl/migration-integration
May 6, 2026
a864d0f
fix merge issue
May 6, 2026
01e41e2
Merge branch 'main' into cjl/migration-integration
May 7, 2026
76bfdf4
Merge branch 'cjl/replacement-apis' into cjl/migration-integration
May 7, 2026
95e7e03
add routers for steady state operation
May 7, 2026
bc1842c
add duplicating router
May 7, 2026
fd86181
add router for dual write mode
May 7, 2026
e218d1f
use routers in composite.Store
May 8, 2026
4a6c07c
fix compile issues
May 11, 2026
196524d
set initial version for flatKV
May 11, 2026
15d4415
nil checks
May 11, 2026
3a3db40
properly handle context lifecycle
May 11, 2026
91f1005
get version fixes
May 11, 2026
5f9c70f
init migration store in memiavl
May 11, 2026
818aee4
fix test store names
May 11, 2026
db7efd3
fixed unit tests
May 11, 2026
82f21df
Merge branch 'main' into cjl/composite-uses-routers-2
May 13, 2026
f432243
fix merge problems
May 13, 2026
cf22acc
fix build problems
May 13, 2026
782cb75
fix failing tests
May 13, 2026
99d44c3
add passthrough router
May 13, 2026
0bc546b
fix bug
May 13, 2026
70ac6ac
fix buggy test
May 14, 2026
dfabe19
fix migration manager construction after migration complete
May 14, 2026
1758c2b
Merge branch 'main' into cjl/composite-uses-routers-2
May 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions app/seidb.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ const (
FlagSCHistoricalProofRateLimit = "state-commit.sc-historical-proof-rate-limit"
FlagSCHistoricalProofBurst = "state-commit.sc-historical-proof-burst"
FlagSCWriteMode = "state-commit.sc-write-mode"
FlagSCReadMode = "state-commit.sc-read-mode"
FlagSCEnableLatticeHash = "state-commit.sc-enable-lattice-hash"

// SS Store configs
FlagSSEnable = "state-store.ss-enable"
Expand Down Expand Up @@ -111,15 +109,6 @@ func parseSCConfigs(appOpts servertypes.AppOptions) config.StateCommitConfig {
}
scConfig.WriteMode = parsedWM
}
if rm := cast.ToString(appOpts.Get(FlagSCReadMode)); rm != "" {
parsedRM, err := config.ParseReadMode(rm)
if err != nil {
panic(fmt.Sprintf("invalid EVM SS read mode %q: %s", rm, err))
}
scConfig.ReadMode = parsedRM
}

scConfig.EnableLatticeHash = cast.ToBool(appOpts.Get(FlagSCEnableLatticeHash))

if v := appOpts.Get(FlagSCHistoricalProofMaxInFlight); v != nil {
scConfig.HistoricalProofMaxInFlight = cast.ToInt(v)
Expand Down
2 changes: 0 additions & 2 deletions app/seidb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ func (t TestSeiDBAppOpts) Get(s string) interface{} {
return defaultSCConfig.MemIAVLConfig.SnapshotPrefetchThreshold
case FlagSCSnapshotWriteRateMBps:
return defaultSCConfig.MemIAVLConfig.SnapshotWriteRateMBps
case FlagSCEnableLatticeHash:
return defaultSCConfig.EnableLatticeHash
case FlagSSEnable:
return defaultSSConfig.Enable
case FlagSSBackend:
Expand Down
24 changes: 7 additions & 17 deletions docker/localnode/scripts/step4_config_override.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,15 @@ if [ "$GIGA_STORAGE" = "true" ]; then
RECEIPT_BACKEND=${RECEIPT_BACKEND:-parquet}
echo "Enabling Giga Storage for node $NODE_ID..."

# --- SC layer: dual_write + split_read + lattice hash ---
# SC must use dual_write (not split_write) because block execution reads
# EVM data from the memiavl tree via GetChildStoreByName. With split_write,
# EVM data only goes to FlatKV and the memiavl tree becomes stale.
# dual_write keeps memiavl up-to-date for reads while also populating FlatKV.
# --- SC layer: test_only_dual_write ---
# SC must use test_only_dual_write because block execution reads EVM data
# from the memiavl tree via GetChildStoreByName. dual-write keeps memiavl
# up-to-date for reads while also populating FlatKV. This mode is for test
# clusters only — never deploy to testnet/mainnet.
if grep -q "sc-write-mode" ~/.sei/config/app.toml; then
sed -i 's/sc-write-mode = .*/sc-write-mode = "dual_write"/' ~/.sei/config/app.toml
sed -i 's/sc-write-mode = .*/sc-write-mode = "test_only_dual_write"/' ~/.sei/config/app.toml
else
sed -i '/^\[state-store\]/i sc-write-mode = "dual_write"' ~/.sei/config/app.toml
fi
if grep -q "sc-read-mode" ~/.sei/config/app.toml; then
sed -i 's/sc-read-mode = .*/sc-read-mode = "split_read"/' ~/.sei/config/app.toml
else
sed -i '/^\[state-store\]/i sc-read-mode = "split_read"' ~/.sei/config/app.toml
fi
if grep -q "sc-enable-lattice-hash" ~/.sei/config/app.toml; then
sed -i 's/sc-enable-lattice-hash = .*/sc-enable-lattice-hash = true/' ~/.sei/config/app.toml
else
sed -i '/^\[state-store\]/i sc-enable-lattice-hash = true' ~/.sei/config/app.toml
sed -i '/^\[state-store\]/i sc-write-mode = "test_only_dual_write"' ~/.sei/config/app.toml
fi

# --- SS layer: enable EVM split ---
Expand Down
16 changes: 3 additions & 13 deletions docker/rpcnode/scripts/step1_configure_init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,11 @@ if [ "$GIGA_STORAGE" = "true" ]; then
RECEIPT_BACKEND=${RECEIPT_BACKEND:-parquet}
echo "Enabling Giga Storage for RPC node..."

# SC layer: must match validators (dual_write + split_read + lattice hash)
# SC layer: must match validators (test_only_dual_write)
if grep -q "sc-write-mode" ~/.sei/config/app.toml; then
sed -i 's/sc-write-mode = .*/sc-write-mode = "dual_write"/' ~/.sei/config/app.toml
sed -i 's/sc-write-mode = .*/sc-write-mode = "test_only_dual_write"/' ~/.sei/config/app.toml
else
sed -i '/^\[state-store\]/i sc-write-mode = "dual_write"' ~/.sei/config/app.toml
fi
if grep -q "sc-read-mode" ~/.sei/config/app.toml; then
sed -i 's/sc-read-mode = .*/sc-read-mode = "split_read"/' ~/.sei/config/app.toml
else
sed -i '/^\[state-store\]/i sc-read-mode = "split_read"' ~/.sei/config/app.toml
fi
if grep -q "sc-enable-lattice-hash" ~/.sei/config/app.toml; then
sed -i 's/sc-enable-lattice-hash = .*/sc-enable-lattice-hash = true/' ~/.sei/config/app.toml
else
sed -i '/^\[state-store\]/i sc-enable-lattice-hash = true' ~/.sei/config/app.toml
sed -i '/^\[state-store\]/i sc-write-mode = "test_only_dual_write"' ~/.sei/config/app.toml
fi

# SS layer: enable EVM split
Expand Down
4 changes: 2 additions & 2 deletions sei-cosmos/baseapp/baseapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import (
)

var (
capKey1 = sdk.NewKVStoreKey("key1")
capKey2 = sdk.NewKVStoreKey("key2")
capKey1 = sdk.NewKVStoreKey("bank")
capKey2 = sdk.NewKVStoreKey("staking")
)

func newBaseApp(name string, options ...func(*BaseApp)) *BaseApp {
Expand Down
4 changes: 2 additions & 2 deletions sei-cosmos/baseapp/deliver_tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,11 +286,11 @@ func TestQuery(t *testing.T) {

app.InitChain(context.Background(), &abci.RequestInitChain{})

// NOTE: "/store/key1" tells us KVStore
// NOTE: "/store/bank" tells us KVStore
// and the final "/key" says to use the data as the
// key in the given KVStore ...
query := abci.RequestQuery{
Path: "/store/key1/key",
Path: "/store/bank/key",
Data: key,
}
tx := newTxCounter(0, 0)
Expand Down
8 changes: 3 additions & 5 deletions sei-cosmos/server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,11 +383,9 @@ func GetConfig(v *viper.Viper) (Config, error) {
SnapshotDirectory: v.GetString("state-sync.snapshot-directory"),
},
StateCommit: config.StateCommitConfig{
Enable: v.GetBool("state-commit.sc-enable"),
Directory: v.GetString("state-commit.sc-directory"),
WriteMode: config.WriteMode(v.GetString("state-commit.sc-write-mode")),
ReadMode: config.ReadMode(v.GetString("state-commit.sc-read-mode")),
EnableLatticeHash: v.GetBool("state-commit.sc-enable-lattice-hash"),
Enable: v.GetBool("state-commit.sc-enable"),
Directory: v.GetString("state-commit.sc-directory"),
WriteMode: config.WriteMode(v.GetString("state-commit.sc-write-mode")),
MemIAVLConfig: memiavl.Config{
AsyncCommitBuffer: v.GetInt("state-commit.sc-async-commit-buffer"),
SnapshotKeepRecent: v.GetUint32("state-commit.sc-keep-recent"),
Expand Down
12 changes: 3 additions & 9 deletions sei-cosmos/server/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,9 @@ func TestGetConfigStateCommit(t *testing.T) {
v.Set("minimum-gas-prices", DefaultMinGasPrices)
v.Set("telemetry.global-labels", []interface{}{})

// Set StateCommit values using the TOML key names (sc-* prefix)
v.Set("state-commit.sc-enable", true)
v.Set("state-commit.sc-directory", "/custom/path")
v.Set("state-commit.sc-write-mode", "dual_write")
v.Set("state-commit.sc-read-mode", "evm_first")
v.Set("state-commit.sc-write-mode", "test_only_dual_write")
v.Set("state-commit.sc-async-commit-buffer", 200)
v.Set("state-commit.sc-keep-recent", 5)
v.Set("state-commit.sc-snapshot-interval", 5000)
Expand All @@ -302,11 +300,9 @@ func TestGetConfigStateCommit(t *testing.T) {
cfg, err := GetConfig(v)
require.NoError(t, err)

// Verify StateCommit fields are correctly parsed
require.True(t, cfg.StateCommit.Enable)
require.Equal(t, "/custom/path", cfg.StateCommit.Directory)
require.Equal(t, seidbconfig.DualWrite, cfg.StateCommit.WriteMode)
require.Equal(t, seidbconfig.EVMFirstRead, cfg.StateCommit.ReadMode)
require.Equal(t, seidbconfig.TestOnlyDualWrite, cfg.StateCommit.WriteMode)

// Verify MemIAVLConfig fields
require.Equal(t, 200, cfg.StateCommit.MemIAVLConfig.AsyncCommitBuffer)
Expand Down Expand Up @@ -355,11 +351,9 @@ func TestGetConfigStateStore(t *testing.T) {
func TestDefaultStateCommitConfig(t *testing.T) {
cfg := DefaultConfig()

// Verify default StateCommit values
require.True(t, cfg.StateCommit.Enable)
require.Empty(t, cfg.StateCommit.Directory)
require.Equal(t, seidbconfig.CosmosOnlyWrite, cfg.StateCommit.WriteMode)
require.Equal(t, seidbconfig.CosmosOnlyRead, cfg.StateCommit.ReadMode)
require.Equal(t, seidbconfig.MemiavlOnly, cfg.StateCommit.WriteMode)
}

func TestDefaultStateStoreConfig(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions sei-cosmos/storev2/rootmulti/flatkv_hash_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ func TestFlatKVDualWriteHashConsistency(t *testing.T) {
// SplitWrite — hash consistency, EVM data not in memiavl tree
// ---------------------------------------------------------------------------

func TestFlatKVSplitWriteHashConsistency(t *testing.T) {
store, storeKeys := newTestRootMulti(t, t.TempDir(), splitWriteConfig())
func TestFlatKVEVMMigratedHashConsistency(t *testing.T) {
store, storeKeys := newTestRootMulti(t, t.TempDir(), evmMigratedConfig())
defer func() { require.NoError(t, store.Close()) }()

evmData := newEVMTestData(0xBB)
Expand Down
21 changes: 3 additions & 18 deletions sei-cosmos/storev2/rootmulti/flatkv_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,31 +40,16 @@ func withTestMemIAVL(cfg seidbconfig.StateCommitConfig) seidbconfig.StateCommitC

func dualWriteConfig() seidbconfig.StateCommitConfig {
cfg := seidbconfig.DefaultStateCommitConfig()
cfg.WriteMode = seidbconfig.DualWrite
cfg.EnableLatticeHash = true
cfg.WriteMode = seidbconfig.TestOnlyDualWrite
return withTestMemIAVL(cfg)
}

func splitWriteConfig() seidbconfig.StateCommitConfig {
func evmMigratedConfig() seidbconfig.StateCommitConfig {
cfg := seidbconfig.DefaultStateCommitConfig()
cfg.WriteMode = seidbconfig.SplitWrite
cfg.EnableLatticeHash = true
cfg.WriteMode = seidbconfig.EVMMigrated
return withTestMemIAVL(cfg)
}

func cosmosOnlyConfig() seidbconfig.StateCommitConfig {
cfg := seidbconfig.DefaultStateCommitConfig()
cfg.WriteMode = seidbconfig.CosmosOnlyWrite
cfg.EnableLatticeHash = false
return withTestMemIAVL(cfg)
}

func dualWriteNoLatticeConfig() seidbconfig.StateCommitConfig {
cfg := dualWriteConfig()
cfg.EnableLatticeHash = false
return cfg
}

// ---------------------------------------------------------------------------
// EVM test data and helpers
// ---------------------------------------------------------------------------
Expand Down
74 changes: 2 additions & 72 deletions sei-cosmos/storev2/rootmulti/flatkv_modes_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package rootmulti

// WriteMode / Query path coverage: Shadow, SS, proof, missing-key, async restart.
// WriteMode / Query path coverage: SS, proof, missing-key, async restart.

import (
"fmt"
Expand All @@ -9,82 +9,12 @@ import (
storerootmulti "github.com/sei-protocol/sei-chain/sei-cosmos/store/rootmulti"
"github.com/sei-protocol/sei-chain/sei-cosmos/store/types"
seidbconfig "github.com/sei-protocol/sei-chain/sei-db/config"
"github.com/sei-protocol/sei-chain/sei-db/state_db/sc/flatkv"
abci "github.com/sei-protocol/sei-chain/sei-tendermint/abci/types"
"github.com/stretchr/testify/require"
)

// ---------------------------------------------------------------------------
// Shadow mode — DualWrite + EnableLatticeHash=false
// ---------------------------------------------------------------------------

func TestFlatKVShadowModeNoLatticeInAppHash(t *testing.T) {
evmData := newEVMTestData(0x77)

// Store A: DualWrite with lattice *disabled* (shadow mode).
dirA := t.TempDir()
storeA, keysA := newTestRootMulti(t, dirA, dualWriteNoLatticeConfig())

// Store B: CosmosOnly baseline (used to verify consensus parity).
dirB := t.TempDir()
storeB, keysB := newTestRootMulti(t, dirB, cosmosOnlyConfig())

// Store C: DualWrite with lattice *enabled* on identical input. Used to
// verify that the FlatKV LtHash computed while shadowing is bit-equal to
// the LtHash computed when consensus actually uses it. This is the key
// correctness property for the shadow -> enable migration path: flipping
// EnableLatticeHash on a shadow node must not change the underlying hash
// state.
dirC := t.TempDir()
storeC, keysC := newTestRootMulti(t, dirC, dualWriteConfig())

// Drive each store with byte-identical input via simulateBlock.
for block := 1; block <= 5; block++ {
simulateBlock(t, storeA, keysA, block, evmData)
simulateBlock(t, storeB, keysB, block, evmData)
simulateBlock(t, storeC, keysC, block, evmData)

// App hashes must be identical (flatkv does not affect consensus).
require.Equalf(t, storeB.lastCommitInfo.Hash(), storeA.lastCommitInfo.Hash(),
"shadow mode app hash must match CosmosOnly at block %d", block)

// evm_lattice must NOT appear in Store A's CommitInfo.
latticeA := findStoreInfo(storeA.lastCommitInfo.StoreInfos, "evm_lattice")
require.Nilf(t, latticeA,
"evm_lattice must not appear with EnableLatticeHash=false (block %d)", block)

// Store C DOES include evm_lattice.
latticeC := findStoreInfo(storeC.lastCommitInfo.StoreInfos, "evm_lattice")
require.NotNilf(t, latticeC, "evm_lattice expected on lattice-enabled store (block %d)", block)
require.NotEmpty(t, latticeC.CommitId.Hash)
}

require.NoError(t, storeB.Close())
require.NoError(t, storeA.Close())
require.NoError(t, storeC.Close())

// Core shadow-mode guarantee: FlatKV's on-disk LtHash is identical
// whether or not it participates in consensus. If this ever diverges,
// flipping EnableLatticeHash=true on a shadow node will fork the chain.
cfgShadow := dualWriteNoLatticeConfig()
roShadow := openFlatKVReadOnly(t, dirA, cfgShadow, 0)
defer func() { require.NoError(t, roShadow.Close()) }()
require.NotEmpty(t, roShadow.RootHash(),
"flatkv should have non-empty RootHash even with lattice disabled")

cfgEnabled := dualWriteConfig()
roEnabled := openFlatKVReadOnly(t, dirC, cfgEnabled, 0)
defer func() { require.NoError(t, roEnabled.Close()) }()

require.Equal(t, roEnabled.CommittedRootHash(), roShadow.CommittedRootHash(),
"FlatKV CommittedRootHash must be identical under shadow and lattice-enabled modes for the same input")

require.NoError(t, flatkv.VerifyLtHash(roShadow), "full-scan LtHash failed in shadow mode")
require.NoError(t, flatkv.VerifyLtHash(roEnabled), "full-scan LtHash failed in lattice-enabled mode")
}

// ---------------------------------------------------------------------------
// Query with SS enabled and ReadMode
// Query with SS enabled
// ---------------------------------------------------------------------------

func TestFlatKVQueryWithSSAndReadMode(t *testing.T) {
Expand Down
8 changes: 4 additions & 4 deletions sei-cosmos/storev2/rootmulti/flatkv_recovery_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ func TestFlatKVCrashRecoveryThroughRootMulti(t *testing.T) {
// are only stored in FlatKV.
// ---------------------------------------------------------------------------

func TestFlatKVSplitWriteCrashRecovery(t *testing.T) {
func TestFlatKVEVMMigratedCrashRecovery(t *testing.T) {
dir := t.TempDir()
cfg := splitWriteConfig()
cfg := evmMigratedConfig()
evmData := newEVMTestData(0x33)

store1, keys1 := newTestRootMulti(t, dir, cfg)
Expand Down Expand Up @@ -208,9 +208,9 @@ func TestFlatKVReverseCrashRecoveryFlatKVAhead(t *testing.T) {
// the chain at v3 with the v3 EVM value still readable from FlatKV.
// ---------------------------------------------------------------------------

func TestFlatKVSplitWriteReverseCrashRecovery(t *testing.T) {
func TestFlatKVEVMMigratedReverseCrashRecovery(t *testing.T) {
dir := t.TempDir()
cfg := splitWriteConfig()
cfg := evmMigratedConfig()
evmData := newEVMTestData(0x78)

store1, keys1 := newTestRootMulti(t, dir, cfg)
Expand Down
32 changes: 15 additions & 17 deletions sei-cosmos/storev2/rootmulti/flatkv_snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ func TestFlatKVSnapshotRestoreWithLatticeHash(t *testing.T) {
// because the data path is different).
// ---------------------------------------------------------------------------

func TestFlatKVSplitWriteSnapshotRestore(t *testing.T) {
cfg := splitWriteConfig()
func TestFlatKVEVMMigratedSnapshotRestore(t *testing.T) {
cfg := evmMigratedConfig()
evmData := newEVMTestData(0x34)

// Source: drive 5 blocks under SplitWrite.
Expand All @@ -146,14 +146,13 @@ func TestFlatKVSplitWriteSnapshotRestore(t *testing.T) {
require.NotNil(t, srcLattice)
require.NotEmpty(t, srcLattice.CommitId.Hash)

// Source invariant: memiavl "evm" subtree is empty under SplitWrite —
// expected empty-tree hash, so the subsequent parity check against the
// restored node is meaningful only if FlatKV carried the data through
// the snapshot.
srcEVM := srcStore.scStore.GetChildStoreByName("evm")
require.NotNil(t, srcEVM)
require.Nilf(t, srcEVM.Get(evmData.storKey),
"memiavl evm subtree must be empty under SplitWrite on source")
// The pre-router "memiavl evm subtree must be empty" check used to be
// asserted here via scStore.GetChildStoreByName("evm"), but that
// accessor now returns a router-wrapped view that surfaces FlatKV
// data in EVMMigrated mode, so it can no longer distinguish "memiavl
// is empty" from "router routed to flatkv". The consensus-parity
// check on app hashes below carries the same load: if memiavl had
// drifted on either side, the per-block hashes would not match.

// Snapshot to buffer (keep srcStore open to continue the chain below).
var buf bytes.Buffer
Expand All @@ -174,13 +173,12 @@ func TestFlatKVSplitWriteSnapshotRestore(t *testing.T) {
require.NotNil(t, dstLattice, "evm_lattice must be present after restore")
require.NotEmpty(t, dstLattice.CommitId.Hash, "restored lattice hash must be non-empty")

// Destination invariant: memiavl "evm" subtree stays empty on the
// restored SplitWrite store. If it has any value for evmData.storKey,
// the snapshot pipeline misrouted evm data into memiavl.
dstEVM := dstStore.scStore.GetChildStoreByName("evm")
require.NotNil(t, dstEVM)
require.Nilf(t, dstEVM.Get(evmData.storKey),
"memiavl evm subtree must remain empty under SplitWrite on restored store")
// The pre-router "restored memiavl evm subtree stays empty" check used
// to be asserted here; it relied on GetChildStoreByName("evm")
// returning a memiavl-direct view. That view is now router-wrapped
// (see the matching comment on the source side), so the check is
// pinned by the consensus-parity guarantee further down: drift on
// either backend on either side would show up as a hash mismatch.

// Extract destination store keys for the continuation below.
dstKeys := make(map[string]*types.KVStoreKey)
Expand Down
Loading
Loading