Skip to content

feat(sei-db): add flatkv store implementation#2793

Open
blindchaser wants to merge 4 commits intomainfrom
yiren/flatkv-impl-rebased
Open

feat(sei-db): add flatkv store implementation#2793
blindchaser wants to merge 4 commits intomainfrom
yiren/flatkv-impl-rebased

Conversation

@blindchaser
Copy link
Contributor

  • Multi-DB storage: storageDB, accountDB, codeDB, metadataDB
  • LtHash-based state commitment using internal key formats
  • Configurable write toggles per DB type
  • Iterator support for storage keys

Describe your changes and provide context

Testing performed to validate your change

@github-actions
Copy link

github-actions bot commented Feb 3, 2026

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

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedFeb 3, 2026, 8:35 PM

@codecov
Copy link

codecov bot commented Feb 3, 2026

Codecov Report

❌ Patch coverage is 58.78468% with 312 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.66%. Comparing base (4d7369c) to head (1883bfb).

Files with missing lines Patch % Lines
sei-db/state_db/sc/flatkv/store.go 61.74% 80 Missing and 47 partials ⚠️
sei-db/state_db/sc/flatkv/iterator.go 41.60% 61 Missing and 12 partials ⚠️
sei-db/state_db/sc/flatkv/store_read.go 56.42% 47 Missing and 14 partials ⚠️
sei-db/state_db/sc/composite/store.go 32.25% 16 Missing and 5 partials ⚠️
sei-db/state_db/sc/flatkv/store_lifecycle.go 57.14% 6 Missing and 6 partials ⚠️
sei-db/state_db/sc/flatkv/store_meta.go 67.56% 6 Missing and 6 partials ⚠️
sei-db/state_db/sc/flatkv/keys.go 84.00% 4 Missing ⚠️
sei-db/common/evm/keys.go 93.54% 1 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2793      +/-   ##
==========================================
+ Coverage   56.65%   56.66%   +0.01%     
==========================================
  Files        2031     2036       +5     
  Lines      165854   166570     +716     
==========================================
+ Hits        93959    94382     +423     
- Misses      63664    63867     +203     
- Partials     8231     8321      +90     
Flag Coverage Δ
sei-chain 41.59% <58.78%> (+0.08%) ⬆️
sei-cosmos 48.11% <ø> (ø)
sei-db 68.72% <ø> (ø)
sei-tendermint 58.03% <ø> (-0.04%) ⬇️

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

Files with missing lines Coverage Δ
sei-db/config/flatkv_config.go 100.00% <100.00%> (ø)
sei-db/config/sc_config.go 100.00% <100.00%> (ø)
sei-db/common/evm/keys.go 88.46% <93.54%> (+7.50%) ⬆️
sei-db/state_db/sc/flatkv/keys.go 95.29% <84.00%> (+23.00%) ⬆️
sei-db/state_db/sc/flatkv/store_lifecycle.go 57.14% <57.14%> (ø)
sei-db/state_db/sc/flatkv/store_meta.go 67.56% <67.56%> (ø)
sei-db/state_db/sc/composite/store.go 48.64% <32.25%> (-8.20%) ⬇️
sei-db/state_db/sc/flatkv/store_read.go 56.42% <56.42%> (ø)
sei-db/state_db/sc/flatkv/iterator.go 41.60% <41.60%> (ø)
sei-db/state_db/sc/flatkv/store.go 61.74% <61.74%> (ø)

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

Copy link

@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: 34a6fed4c3

ℹ️ 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 on lines +585 to +616
for _, pw := range s.codeWrites {
if pw.isDelete {
if err := batch.Delete(pw.key); err != nil {
return fmt.Errorf("codeDB delete: %w", err)
}
} else {
if err := batch.Set(pw.key, pw.value); err != nil {
return fmt.Errorf("codeDB set: %w", err)
}
}
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
Comment on lines +619 to +650
for _, pw := range s.storageWrites {
if pw.isDelete {
if err := batch.Delete(pw.key); err != nil {
return fmt.Errorf("storageDB delete: %w", err)
}
} else {
if err := batch.Set(pw.key, pw.value); err != nil {
return fmt.Errorf("storageDB set: %w", err)
}
}
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
- Multi-DB storage: storageDB, accountDB, codeDB, metadataDB
- LtHash-based state commitment using internal key formats
- Configurable write toggles per DB type
- Iterator support for storage keys
@blindchaser blindchaser force-pushed the yiren/flatkv-impl-rebased branch from 34a6fed to e3a525f Compare February 3, 2026 19:49
Comment on lines +570 to +583
for _, paw := range s.accountWrites {
key := AccountKey(paw.addr)
if paw.isDelete {
if err := batch.Delete(key); err != nil {
return fmt.Errorf("accountDB delete: %w", err)
}
} else {
// Encode AccountValue and store with addr as key
encoded := EncodeAccountValue(paw.value)
if err := batch.Set(key, encoded); err != nil {
return fmt.Errorf("accountDB set: %w", err)
}
}
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
package config

// FlatKVConfig defines configuration for the FlatKV (EVM) commit store.
type FlatKVConfig struct {
Copy link
Contributor

@yzang2019 yzang2019 Feb 5, 2026

Choose a reason for hiding this comment

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

Let's put this under flatkv package?

// EnableStorageWrites enables writes to storageDB and its LtHash contribution.
// When false, storage data is skipped entirely (no DB writes, no LtHash updates).
// Default: true
EnableStorageWrites bool `mapstructure:"enable-storage-writes"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure why we want these configs, as long as dual write is true, all EVM state should be written to flatkv, and we don't need to control which key to write or not

// When false (default): all writes use Sync=true for maximum durability.
// WAL and metaDB always use sync writes regardless of this setting.
// Default: false
AsyncWrites bool `mapstructure:"async-writes"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably better to split into Fsync: bool and AsyncWriteBuffer: int

// - 0 or 1: flush every block (safest, slowest)
// - N > 1: flush every N blocks (faster, recovers up to N blocks from WAL)
// Default: 100
FlushInterval int `mapstructure:"flush-interval"`
Copy link
Contributor

@yzang2019 yzang2019 Feb 5, 2026

Choose a reason for hiding this comment

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

I think we don't need this config today, since we have to flush every block, we can add in the future if we really need it

// TODO: initialize FlatKV store for evmSC when cfg.WriteMode != config.CosmosOnlyWrite
// Initialize FlatKV store struct if write mode is not cosmos_only
// Note: DB is NOT opened here, will be opened in LoadVersion
if cfg.WriteMode != config.CosmosOnlyWrite {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would recommend checking DualWrite or SplitWrite to determine whether we should initialize EMVCommitter

}

// Also load evmCommitter if enabled
if cs.config.WriteMode != config.CosmosOnlyWrite && cs.evmCommitter != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

We can remove this check cs.config.WriteMode != config.CosmosOnlyWrite since evmCommitter will be nil if write is not enabled

if cs.config.WriteMode != config.CosmosOnlyWrite && cs.evmCommitter != nil {
// Use LoadVersion on existing evmCommitter (matches memiavl pattern)
// This properly handles readOnly flag and avoids resource leaks
evmStore, err := cs.evmCommitter.LoadVersion(targetVersion, readOnly)
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure if we wanna call LoadVersion here, CMS will call LoadVersion as well, we need to make sure it's only called in one place

)

const (
// DB subdirectories
Copy link
Contributor

Choose a reason for hiding this comment

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

We need a legacyDB as well

metadataDir = "metadata"

// Metadata DB keys
MetaGlobalVersion = "v" // Global committed version watermark (8 bytes)
Copy link
Contributor

Choose a reason for hiding this comment

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

suggest metadata key stored with _meta/version, _meta/hash


// Get returns the value for the given memiavl key.
// Returns (value, true) if found, (nil, false) if not found.
func (s *CommitStore) Get(key []byte) ([]byte, bool) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we have store_read.go but not store_write.go? If we want to split, I was expecting to see read and write. Otherwise maybe we should just combine

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.

2 participants