Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions app/receipt_store_config.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package app

import (
"path/filepath"

seidbconfig "github.com/sei-protocol/sei-chain/sei-db/config"

"github.com/sei-protocol/sei-chain/sei-db/common/utils"
)

const (
Expand All @@ -20,7 +20,7 @@ func readReceiptStoreConfig(homePath string, appOpts seidbconfig.AppOptions) (se
return receiptConfig, err
}
if receiptConfig.DBDirectory == "" {
receiptConfig.DBDirectory = filepath.Join(homePath, "data", "receipt.db")
receiptConfig.DBDirectory = utils.GetReceiptStorePath(homePath, receiptConfig.Backend)
}
return receiptConfig, nil
}
3 changes: 2 additions & 1 deletion app/seidb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ func TestReadReceiptStoreConfigUsesDefaultDirectoryWhenUnset(t *testing.T) {
homePath := t.TempDir()
receiptConfig, err := readReceiptStoreConfig(homePath, mapAppOpts{})
require.NoError(t, err)
assert.Equal(t, filepath.Join(homePath, "data", "receipt.db"), receiptConfig.DBDirectory)
// New nodes (no legacy data/receipt.db) get the new ledger/ layout with backend
assert.Equal(t, filepath.Join(homePath, "data", "ledger", "receipt", "pebbledb"), receiptConfig.DBDirectory)
}

// TestFullAppPathWithParquetReceiptStore exercises the full app.New path with rs-backend = "parquet"
Expand Down
70 changes: 66 additions & 4 deletions sei-db/common/utils/path.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,75 @@
package utils

import "path/filepath"
import (
"os"
"path/filepath"
)

func GetCommitStorePath(homePath string) string {
return filepath.Join(homePath, "data", "committer.db")
// DirExists returns true if path exists and is a directory.
func DirExists(path string) bool {
info, err := os.Stat(path)
return err == nil && info.IsDir()
}

// FileExists returns true if path exists and is a regular file.
func FileExists(path string) bool {
info, err := os.Stat(path)
return err == nil && !info.IsDir()
}

// GetCosmosSCStorePath returns the path for the memiavl state commitment store.
// New nodes use data/state_commit/memiavl; existing nodes with data/committer.db
// continue using the legacy path for backward compatibility.
func GetCosmosSCStorePath(homePath string) string {
legacyPath := filepath.Join(homePath, "data", "committer.db")
if DirExists(legacyPath) {
return legacyPath
}
return filepath.Join(homePath, "data", "state_commit", "memiavl")
}

// GetFlatKVPath returns the path for the FlatKV EVM commit store.
// New nodes use data/state_commit/flatkv; existing nodes with data/flatkv
// continue using the legacy path for backward compatibility.
func GetFlatKVPath(homePath string) string {
legacyPath := filepath.Join(homePath, "data", "flatkv")
if DirExists(legacyPath) {
return legacyPath
}
return filepath.Join(homePath, "data", "state_commit", "flatkv")
}

// GetStateStorePath returns the path for the Cosmos state store (SS).
// New nodes use data/state_store/cosmos/{backend}; existing nodes with
// data/{backend} continue using the legacy path for backward compatibility.
func GetStateStorePath(homePath string, backend string) string {
return filepath.Join(homePath, "data", backend)
legacyPath := filepath.Join(homePath, "data", backend)
if DirExists(legacyPath) {
return legacyPath
}
return filepath.Join(homePath, "data", "state_store", "cosmos", backend)
}

// GetEVMStateStorePath returns the path for the EVM state store.
// New nodes use data/state_store/evm/{backend}; existing nodes with
// data/evm_ss continue using the legacy path for backward compatibility.
func GetEVMStateStorePath(homePath string, backend string) string {
legacyPath := filepath.Join(homePath, "data", "evm_ss")
if DirExists(legacyPath) {
return legacyPath
}
return filepath.Join(homePath, "data", "state_store", "evm", backend)
}

// GetReceiptStorePath returns the path for the receipt store.
// New nodes use data/ledger/receipt/{backend}; existing nodes with
// data/receipt.db continue using the legacy path for backward compatibility.
func GetReceiptStorePath(homePath string, backend string) string {
legacyPath := filepath.Join(homePath, "data", "receipt.db")
if DirExists(legacyPath) {
return legacyPath
}
return filepath.Join(homePath, "data", "ledger", "receipt", backend)
}

func GetChangelogPath(dbPath string) string {
Expand Down
192 changes: 192 additions & 0 deletions sei-db/common/utils/path_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
package utils

import (
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestDirExists(t *testing.T) {
dir := t.TempDir()
assert.True(t, DirExists(dir))
assert.False(t, DirExists(filepath.Join(dir, "nonexistent")))

f := filepath.Join(dir, "file.txt")
require.NoError(t, os.WriteFile(f, []byte("hi"), 0644))
assert.False(t, DirExists(f), "regular file should not match DirExists")
}

func TestFileExists(t *testing.T) {
dir := t.TempDir()
assert.False(t, FileExists(dir), "directory should not match FileExists")
assert.False(t, FileExists(filepath.Join(dir, "nonexistent")))

f := filepath.Join(dir, "file.txt")
require.NoError(t, os.WriteFile(f, []byte("hi"), 0644))
assert.True(t, FileExists(f))
}

// --- GetCosmosSCStorePath ---

func TestGetCosmosSCStorePath_NewNode(t *testing.T) {
home := t.TempDir()
got := GetCosmosSCStorePath(home)
assert.Equal(t, filepath.Join(home, "data", "state_commit", "memiavl"), got)
}

func TestGetCosmosSCStorePath_LegacyExists(t *testing.T) {
home := t.TempDir()
legacy := filepath.Join(home, "data", "committer.db")
require.NoError(t, os.MkdirAll(legacy, 0755))

got := GetCosmosSCStorePath(home)
assert.Equal(t, legacy, got)
}

// --- GetFlatKVPath ---

func TestGetFlatKVPath_NewNode(t *testing.T) {
home := t.TempDir()
got := GetFlatKVPath(home)
assert.Equal(t, filepath.Join(home, "data", "state_commit", "flatkv"), got)
}

func TestGetFlatKVPath_LegacyExists(t *testing.T) {
home := t.TempDir()
legacy := filepath.Join(home, "data", "flatkv")
require.NoError(t, os.MkdirAll(legacy, 0755))

got := GetFlatKVPath(home)
assert.Equal(t, legacy, got)
}

// --- GetStateStorePath ---

func TestGetStateStorePath_NewNode_Pebble(t *testing.T) {
home := t.TempDir()
got := GetStateStorePath(home, "pebbledb")
assert.Equal(t, filepath.Join(home, "data", "state_store", "cosmos", "pebbledb"), got)
}

func TestGetStateStorePath_NewNode_RocksDB(t *testing.T) {
home := t.TempDir()
got := GetStateStorePath(home, "rocksdb")
assert.Equal(t, filepath.Join(home, "data", "state_store", "cosmos", "rocksdb"), got)
}

func TestGetStateStorePath_LegacyExists(t *testing.T) {
home := t.TempDir()
legacy := filepath.Join(home, "data", "pebbledb")
require.NoError(t, os.MkdirAll(legacy, 0755))

got := GetStateStorePath(home, "pebbledb")
assert.Equal(t, legacy, got)
}

func TestGetStateStorePath_LegacyForDifferentBackend(t *testing.T) {
home := t.TempDir()
// Legacy rocksdb dir exists but we ask for pebbledb — no legacy match
require.NoError(t, os.MkdirAll(filepath.Join(home, "data", "rocksdb"), 0755))

got := GetStateStorePath(home, "pebbledb")
assert.Equal(t, filepath.Join(home, "data", "state_store", "cosmos", "pebbledb"), got)
}

// --- GetEVMStateStorePath ---

func TestGetEVMStateStorePath_NewNode_Pebble(t *testing.T) {
home := t.TempDir()
got := GetEVMStateStorePath(home, "pebbledb")
assert.Equal(t, filepath.Join(home, "data", "state_store", "evm", "pebbledb"), got)
}

func TestGetEVMStateStorePath_NewNode_RocksDB(t *testing.T) {
home := t.TempDir()
got := GetEVMStateStorePath(home, "rocksdb")
assert.Equal(t, filepath.Join(home, "data", "state_store", "evm", "rocksdb"), got)
}

func TestGetEVMStateStorePath_LegacyExists(t *testing.T) {
home := t.TempDir()
legacy := filepath.Join(home, "data", "evm_ss")
require.NoError(t, os.MkdirAll(legacy, 0755))

got := GetEVMStateStorePath(home, "pebbledb")
assert.Equal(t, legacy, got)
}

// --- GetReceiptStorePath ---

func TestGetReceiptStorePath_NewNode_Pebble(t *testing.T) {
home := t.TempDir()
got := GetReceiptStorePath(home, "pebbledb")
assert.Equal(t, filepath.Join(home, "data", "ledger", "receipt", "pebbledb"), got)
}

func TestGetReceiptStorePath_NewNode_Parquet(t *testing.T) {
home := t.TempDir()
got := GetReceiptStorePath(home, "parquet")
assert.Equal(t, filepath.Join(home, "data", "ledger", "receipt", "parquet"), got)
}

func TestGetReceiptStorePath_LegacyExists(t *testing.T) {
home := t.TempDir()
legacy := filepath.Join(home, "data", "receipt.db")
require.NoError(t, os.MkdirAll(legacy, 0755))

got := GetReceiptStorePath(home, "pebbledb")
assert.Equal(t, legacy, got)
}

// --- GetChangelogPath (unchanged, but verify) ---

func TestGetChangelogPath(t *testing.T) {
assert.Equal(t, "/foo/bar/changelog", GetChangelogPath("/foo/bar"))
}

// --- Edge: new path already has data (second run of new node) ---

func TestGetCosmosSCStorePath_NewDataAlreadyExists(t *testing.T) {
home := t.TempDir()
newPath := filepath.Join(home, "data", "state_commit", "memiavl")
require.NoError(t, os.MkdirAll(newPath, 0755))

got := GetCosmosSCStorePath(home)
assert.Equal(t, newPath, got, "should use new path when legacy is absent even if new path already exists")
}

func TestGetStateStorePath_NewDataAlreadyExists(t *testing.T) {
home := t.TempDir()
newPath := filepath.Join(home, "data", "state_store", "cosmos", "pebbledb")
require.NoError(t, os.MkdirAll(newPath, 0755))

got := GetStateStorePath(home, "pebbledb")
assert.Equal(t, newPath, got, "should use new path when legacy is absent even if new path already exists")
}

// --- Edge: both legacy and new exist (legacy wins) ---

func TestGetCosmosSCStorePath_BothExist(t *testing.T) {
home := t.TempDir()
legacy := filepath.Join(home, "data", "committer.db")
require.NoError(t, os.MkdirAll(legacy, 0755))
newPath := filepath.Join(home, "data", "state_commit", "memiavl")
require.NoError(t, os.MkdirAll(newPath, 0755))

got := GetCosmosSCStorePath(home)
assert.Equal(t, legacy, got, "legacy should take precedence when both exist")
}

func TestGetReceiptStorePath_BothExist(t *testing.T) {
home := t.TempDir()
legacy := filepath.Join(home, "data", "receipt.db")
require.NoError(t, os.MkdirAll(legacy, 0755))
newPath := filepath.Join(home, "data", "ledger", "receipt", "pebbledb")
require.NoError(t, os.MkdirAll(newPath, 0755))

got := GetReceiptStorePath(home, "pebbledb")
assert.Equal(t, legacy, got, "legacy should take precedence when both exist")
}
2 changes: 1 addition & 1 deletion sei-db/config/ss_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ type StateStoreConfig struct {
ReadMode ReadMode `mapstructure:"read-mode"`

// EVMDBDirectory defines the directory for EVM state store db files.
// If not set, defaults to <home>/data/evm_ss
// If not set, defaults to <home>/data/state_store/evm/{backend}
EVMDBDirectory string `mapstructure:"evm-db-directory"`
}

Expand Down
2 changes: 1 addition & 1 deletion sei-db/config/toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ const ReceiptStoreConfigTemplate = `
# defaults to pebbledb
rs-backend = "{{ .ReceiptStore.Backend }}"

# Defines the receipt store directory. If unset, defaults to <home>/data/receipt.db
# Defines the receipt store directory. If unset, defaults to <home>/data/ledger/receipt/{backend}
db-directory = "{{ .ReceiptStore.DBDirectory }}"

# AsyncWriteBuffer defines the async queue length for commits to be applied to receipt store.
Expand Down
4 changes: 2 additions & 2 deletions sei-db/state_db/sc/composite/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import (
"context"
"fmt"
"math"
"path/filepath"

commonerrors "github.com/sei-protocol/sei-chain/sei-db/common/errors"
commonevm "github.com/sei-protocol/sei-chain/sei-db/common/evm"
"github.com/sei-protocol/sei-chain/sei-db/common/utils"
"github.com/sei-protocol/sei-chain/sei-db/config"
"github.com/sei-protocol/sei-chain/sei-db/proto"
"github.com/sei-protocol/sei-chain/sei-db/state_db/sc/flatkv"
Expand Down Expand Up @@ -72,7 +72,7 @@ func NewCompositeCommitStore(
// Initialize FlatKV store struct if write mode requires it
// Note: DB is NOT opened here, will be opened in LoadVersion
if cfg.WriteMode == config.DualWrite || cfg.WriteMode == config.SplitWrite {
cfg.FlatKVConfig.DataDir = filepath.Join(homeDir, "data", "flatkv")
cfg.FlatKVConfig.DataDir = utils.GetFlatKVPath(homeDir)
var err error
store.evmCommitter, err = flatkv.NewCommitStore(ctx, &cfg.FlatKVConfig)
if err != nil {
Expand Down
8 changes: 5 additions & 3 deletions sei-db/state_db/sc/composite/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
errorutils "github.com/sei-protocol/sei-chain/sei-db/common/errors"
"github.com/sei-protocol/sei-chain/sei-db/common/evm"
"github.com/sei-protocol/sei-chain/sei-db/common/metrics"
"github.com/sei-protocol/sei-chain/sei-db/common/utils"
"github.com/sei-protocol/sei-chain/sei-db/config"
"github.com/sei-protocol/sei-chain/sei-db/proto"
"github.com/sei-protocol/sei-chain/sei-db/state_db/sc/flatkv"
Expand Down Expand Up @@ -715,8 +716,9 @@ func TestReconcileVersionsAfterCrash(t *testing.T) {
// Simulate crash: rollback FlatKV to version 2 independently, leaving
// cosmos at version 3. This mirrors a crash after cosmos Commit but
// before FlatKV Commit completes.

flatkvCfg := cfg.FlatKVConfig
flatkvCfg.DataDir = dir + "/data/flatkv"
flatkvCfg.DataDir = utils.GetFlatKVPath(dir)
evmStore, err := flatkv.NewCommitStore(t.Context(), &flatkvCfg)
require.NoError(t, err)
_, err = evmStore.LoadVersion(0, false)
Expand Down Expand Up @@ -776,7 +778,7 @@ func TestReconcileVersionsThenContinueCommitting(t *testing.T) {

// Simulate crash: roll FlatKV back to version 2.
flatkvCfg := cfg.FlatKVConfig
flatkvCfg.DataDir = dir + "/data/flatkv"
flatkvCfg.DataDir = utils.GetFlatKVPath(dir)
evmStore, err := flatkv.NewCommitStore(t.Context(), &flatkvCfg)
require.NoError(t, err)
_, err = evmStore.LoadVersion(0, false)
Expand Down Expand Up @@ -873,7 +875,7 @@ func TestReconcileVersionsCosmosAheadByMultiple(t *testing.T) {

// Rollback FlatKV to version 3 (simulating 2 lost commits)
flatkvCfg := cfg.FlatKVConfig
flatkvCfg.DataDir = dir + "/data/flatkv"
flatkvCfg.DataDir = utils.GetFlatKVPath(dir)
evmStore, err := flatkv.NewCommitStore(t.Context(), &flatkvCfg)
require.NoError(t, err)
_, err = evmStore.LoadVersion(0, false)
Expand Down
2 changes: 1 addition & 1 deletion sei-db/state_db/sc/memiavl/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type CommitStore struct {
}

func NewCommitStore(homeDir string, config Config) *CommitStore {
commitDBPath := utils.GetCommitStorePath(homeDir)
commitDBPath := utils.GetCosmosSCStorePath(homeDir)
opts := Options{
Config: config, // Embed the config directly
Dir: commitDBPath,
Expand Down
Loading
Loading