Skip to content

Commit

Permalink
feat(store/v2): remove cosmos-db depdency from store (#19229)
Browse files Browse the repository at this point in the history
  • Loading branch information
cool-develope authored Jan 29, 2024
1 parent 7d66bb3 commit 14fd0ce
Show file tree
Hide file tree
Showing 27 changed files with 1,572 additions and 79 deletions.
31 changes: 31 additions & 0 deletions store/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,34 @@ type Batch interface {
// Reset resets the batch.
Reset()
}

// RawBatch represents a group of writes. They may or may not be written atomically depending on the
// backend. Callers must call Close on the batch when done.
//
// As with RawDB, given keys and values should be considered read-only, and must not be modified after
// passing them to the batch.
type RawBatch interface {
// Set sets a key/value pair.
// CONTRACT: key, value readonly []byte
Set(key, value []byte) error

// Delete deletes a key/value pair.
// CONTRACT: key readonly []byte
Delete(key []byte) error

// Write writes the batch, possibly without flushing to disk. Only Close() can be called after,
// other methods will error.
Write() error

// WriteSync writes the batch and flushes it to disk. Only Close() can be called after, other
// methods will error.
WriteSync() error

// Close closes the batch. It is idempotent, but calls to other methods afterwards will error.
Close() error

// GetByteSize that returns the current size of the batch in bytes. Depending on the implementation,
// this may return the size of the underlying LSM batch, including the size of additional metadata
// on top of the expected key and value total byte count.
GetByteSize() (int, error)
}
7 changes: 4 additions & 3 deletions store/commitment/iavl/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package iavl
import (
"fmt"

dbm "github.com/cosmos/cosmos-db"
"github.com/cosmos/iavl"
ics23 "github.com/cosmos/ics23/go"

log "cosmossdk.io/log"
"cosmossdk.io/store/v2"
"cosmossdk.io/store/v2/commitment"
dbm "cosmossdk.io/store/v2/db"
)

var _ commitment.Tree = (*IavlTree)(nil)
Expand All @@ -19,8 +20,8 @@ type IavlTree struct {
}

// NewIavlTree creates a new IavlTree instance.
func NewIavlTree(db dbm.DB, logger log.Logger, cfg *Config) *IavlTree {
tree := iavl.NewMutableTree(db, cfg.CacheSize, cfg.SkipFastStorageUpgrade, logger)
func NewIavlTree(db store.RawDB, logger log.Logger, cfg *Config) *IavlTree {
tree := iavl.NewMutableTree(dbm.NewWrapper(db), cfg.CacheSize, cfg.SkipFastStorageUpgrade, logger)
return &IavlTree{
tree: tree,
}
Expand Down
5 changes: 3 additions & 2 deletions store/commitment/iavl/tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@ package iavl
import (
"testing"

dbm "github.com/cosmos/cosmos-db"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"

"cosmossdk.io/log"
"cosmossdk.io/store/v2"
"cosmossdk.io/store/v2/commitment"
dbm "cosmossdk.io/store/v2/db"
)

func TestCommitterSuite(t *testing.T) {
s := &commitment.CommitStoreTestSuite{
NewStore: func(db dbm.DB, storeKeys []string, logger log.Logger) (*commitment.CommitStore, error) {
NewStore: func(db store.RawDB, storeKeys []string, logger log.Logger) (*commitment.CommitStore, error) {
multiTrees := make(map[string]commitment.Tree)
cfg := DefaultConfig()
for _, storeKey := range storeKeys {
Expand Down
44 changes: 22 additions & 22 deletions store/commitment/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import (
"io"
"math"

dbm "github.com/cosmos/cosmos-db"
protoio "github.com/cosmos/gogoproto/io"

"cosmossdk.io/log"
"cosmossdk.io/store/v2"
"cosmossdk.io/store/v2/internal/encoding"
"cosmossdk.io/store/v2/proof"
"cosmossdk.io/store/v2/snapshots"
snapshotstypes "cosmossdk.io/store/v2/snapshots/types"
)
Expand All @@ -34,12 +34,12 @@ var (
// and trees.
type CommitStore struct {
logger log.Logger
db dbm.DB
db store.RawDB
multiTrees map[string]Tree
}

// NewCommitStore creates a new CommitStore instance.
func NewCommitStore(multiTrees map[string]Tree, db dbm.DB, logger log.Logger) (*CommitStore, error) {
func NewCommitStore(multiTrees map[string]Tree, db store.RawDB, logger log.Logger) (*CommitStore, error) {
return &CommitStore{
logger: logger,
db: db,
Expand Down Expand Up @@ -67,19 +67,19 @@ func (c *CommitStore) WriteBatch(cs *store.Changeset) error {
return nil
}

func (c *CommitStore) WorkingCommitInfo(version uint64) *store.CommitInfo {
storeInfos := make([]store.StoreInfo, 0, len(c.multiTrees))
func (c *CommitStore) WorkingCommitInfo(version uint64) *proof.CommitInfo {
storeInfos := make([]proof.StoreInfo, 0, len(c.multiTrees))
for storeKey, tree := range c.multiTrees {
storeInfos = append(storeInfos, store.StoreInfo{
storeInfos = append(storeInfos, proof.StoreInfo{
Name: storeKey,
CommitID: store.CommitID{
CommitID: proof.CommitID{
Version: version,
Hash: tree.WorkingHash(),
},
})
}

return &store.CommitInfo{
return &proof.CommitInfo{
Version: version,
StoreInfos: storeInfos,
}
Expand Down Expand Up @@ -129,15 +129,15 @@ func (c *CommitStore) LoadVersion(targetVersion uint64) error {

// If the target version is greater than the latest version, it is the snapshot
// restore case, we should create a new commit info for the target version.
var cInfo *store.CommitInfo
var cInfo *proof.CommitInfo
if targetVersion > latestVersion {
cInfo = c.WorkingCommitInfo(targetVersion)
}

return c.flushCommitInfo(targetVersion, cInfo)
}

func (c *CommitStore) GetCommitInfo(version uint64) (*store.CommitInfo, error) {
func (c *CommitStore) GetCommitInfo(version uint64) (*proof.CommitInfo, error) {
key := []byte(fmt.Sprintf(commitInfoKeyFmt, version))
value, err := c.db.Get(key)
if err != nil {
Expand All @@ -147,15 +147,15 @@ func (c *CommitStore) GetCommitInfo(version uint64) (*store.CommitInfo, error) {
return nil, nil
}

cInfo := &store.CommitInfo{}
cInfo := &proof.CommitInfo{}
if err := cInfo.Unmarshal(value); err != nil {
return nil, err
}

return cInfo, nil
}

func (c *CommitStore) flushCommitInfo(version uint64, cInfo *store.CommitInfo) error {
func (c *CommitStore) flushCommitInfo(version uint64, cInfo *proof.CommitInfo) error {
batch := c.db.NewBatch()
if cInfo != nil {
cInfoKey := []byte(fmt.Sprintf(commitInfoKeyFmt, version))
Expand All @@ -180,14 +180,14 @@ func (c *CommitStore) flushCommitInfo(version uint64, cInfo *store.CommitInfo) e
return batch.WriteSync()
}

func (c *CommitStore) Commit(version uint64) (*store.CommitInfo, error) {
storeInfos := make([]store.StoreInfo, 0, len(c.multiTrees))
func (c *CommitStore) Commit(version uint64) (*proof.CommitInfo, error) {
storeInfos := make([]proof.StoreInfo, 0, len(c.multiTrees))

for storeKey, tree := range c.multiTrees {
// If a commit event execution is interrupted, a new iavl store's version
// will be larger than the RMS's metadata, when the block is replayed, we
// should avoid committing that iavl store again.
var commitID store.CommitID
var commitID proof.CommitID
if tree.GetLatestVersion() >= version {
commitID.Version = version
commitID.Hash = tree.Hash()
Expand All @@ -196,18 +196,18 @@ func (c *CommitStore) Commit(version uint64) (*store.CommitInfo, error) {
if err != nil {
return nil, err
}
commitID = store.CommitID{
commitID = proof.CommitID{
Version: version,
Hash: hash,
}
}
storeInfos = append(storeInfos, store.StoreInfo{
storeInfos = append(storeInfos, proof.StoreInfo{
Name: storeKey,
CommitID: commitID,
})
}

cInfo := &store.CommitInfo{
cInfo := &proof.CommitInfo{
Version: version,
StoreInfos: storeInfos,
}
Expand All @@ -229,13 +229,13 @@ func (c *CommitStore) SetInitialVersion(version uint64) error {
return nil
}

func (c *CommitStore) GetProof(storeKey string, version uint64, key []byte) ([]store.CommitmentOp, error) {
func (c *CommitStore) GetProof(storeKey string, version uint64, key []byte) ([]proof.CommitmentOp, error) {
tree, ok := c.multiTrees[storeKey]
if !ok {
return nil, fmt.Errorf("store %s not found", storeKey)
}

proof, err := tree.GetProof(version, key)
iProof, err := tree.GetProof(version, key)
if err != nil {
return nil, err
}
Expand All @@ -246,13 +246,13 @@ func (c *CommitStore) GetProof(storeKey string, version uint64, key []byte) ([]s
if cInfo == nil {
return nil, fmt.Errorf("commit info not found for version %d", version)
}
commitOp := store.NewIAVLCommitmentOp(key, proof)
commitOp := proof.NewIAVLCommitmentOp(key, iProof)
_, storeCommitmentOp, err := cInfo.GetStoreProof(storeKey)
if err != nil {
return nil, err
}

return []store.CommitmentOp{commitOp, *storeCommitmentOp}, nil
return []proof.CommitmentOp{commitOp, *storeCommitmentOp}, nil
}

func (c *CommitStore) Get(storeKey string, version uint64, key []byte) ([]byte, error) {
Expand Down
4 changes: 2 additions & 2 deletions store/commitment/store_test_suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import (
"io"
"sync"

dbm "github.com/cosmos/cosmos-db"
"github.com/stretchr/testify/suite"

"cosmossdk.io/log"
"cosmossdk.io/store/v2"
dbm "cosmossdk.io/store/v2/db"
"cosmossdk.io/store/v2/snapshots"
snapshotstypes "cosmossdk.io/store/v2/snapshots/types"
)
Expand All @@ -23,7 +23,7 @@ const (
type CommitStoreTestSuite struct {
suite.Suite

NewStore func(db dbm.DB, storeKeys []string, logger log.Logger) (*CommitStore, error)
NewStore func(db store.RawDB, storeKeys []string, logger log.Logger) (*CommitStore, error)
}

func (s *CommitStoreTestSuite) TestSnapshotter() {
Expand Down
57 changes: 53 additions & 4 deletions store/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"io"

corestore "cosmossdk.io/core/store"
"cosmossdk.io/store/v2/proof"
)

// Reader wraps the Has and Get method of a backing data store.
Expand Down Expand Up @@ -71,7 +72,7 @@ type Committer interface {
WriteBatch(cs *Changeset) error

// WorkingCommitInfo returns the CommitInfo for the working tree.
WorkingCommitInfo(version uint64) *CommitInfo
WorkingCommitInfo(version uint64) *proof.CommitInfo

// GetLatestVersion returns the latest version.
GetLatestVersion() (uint64, error)
Expand All @@ -80,10 +81,10 @@ type Committer interface {
LoadVersion(targetVersion uint64) error

// Commit commits the working tree to the database.
Commit(version uint64) (*CommitInfo, error)
Commit(version uint64) (*proof.CommitInfo, error)

// GetProof returns the proof of existence or non-existence for the given key.
GetProof(storeKey string, version uint64, key []byte) ([]CommitmentOp, error)
GetProof(storeKey string, version uint64, key []byte) ([]proof.CommitmentOp, error)

// Get returns the value for the given key at the given version.
//
Expand All @@ -95,7 +96,7 @@ type Committer interface {
SetInitialVersion(version uint64) error

// GetCommitInfo returns the CommitInfo for the given version.
GetCommitInfo(version uint64) (*CommitInfo, error)
GetCommitInfo(version uint64) (*proof.CommitInfo, error)

// Prune attempts to prune all versions up to and including the provided
// version argument. The operation should be idempotent. An error should be
Expand All @@ -106,3 +107,51 @@ type Committer interface {
// only be called once and any call after may panic.
io.Closer
}

// RawDB is the main interface for all key-value database backends. DBs are concurrency-safe.
// Callers must call Close on the database when done.
//
// Keys cannot be nil or empty, while values cannot be nil. Keys and values should be considered
// read-only, both when returned and when given, and must be copied before they are modified.
type RawDB interface {
// Get fetches the value of the given key, or nil if it does not exist.
// CONTRACT: key, value readonly []byte
Get([]byte) ([]byte, error)

// Has checks if a key exists.
// CONTRACT: key, value readonly []byte
Has(key []byte) (bool, error)

// Iterator returns an iterator over a domain of keys, in ascending order. The caller must call
// Close when done. End is exclusive, and start must be less than end. A nil start iterates
// from the first key, and a nil end iterates to the last key (inclusive). Empty keys are not
// valid.
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
// CONTRACT: start, end readonly []byte
Iterator(start, end []byte) (corestore.Iterator, error)

// ReverseIterator returns an iterator over a domain of keys, in descending order. The caller
// must call Close when done. End is exclusive, and start must be less than end. A nil end
// iterates from the last key (inclusive), and a nil start iterates to the first key (inclusive).
// Empty keys are not valid.
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
// CONTRACT: start, end readonly []byte
ReverseIterator(start, end []byte) (corestore.Iterator, error)

// Close closes the database connection.
Close() error

// NewBatch creates a batch for atomic updates. The caller must call Batch.Close.
NewBatch() RawBatch

// NewBatchWithSize create a new batch for atomic updates, but with pre-allocated size.
// This will does the same thing as NewBatch if the batch implementation doesn't support pre-allocation.
NewBatchWithSize(int) RawBatch
}

type (
// Options defines the interface of a database options.
Options interface {
Get(string) interface{}
}
)
Loading

0 comments on commit 14fd0ce

Please sign in to comment.