Skip to content

Commit

Permalink
feat(store/v2): support queries via RootStore (#18169)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderbez authored Oct 20, 2023
1 parent 912c742 commit 5cd5003
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 21 deletions.
26 changes: 22 additions & 4 deletions store/root/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"slices"

"github.com/cockroachdb/errors"
ics23 "github.com/cosmos/ics23/go"

"cosmossdk.io/log"
"cosmossdk.io/store/v2"
Expand Down Expand Up @@ -150,9 +149,28 @@ func (s *Store) GetLatestVersion() (uint64, error) {
return lastCommitID.Version, nil
}

// GetProof delegates the GetProof to the store's underlying SC backend.
func (s *Store) GetProof(_ string, version uint64, key []byte) (*ics23.CommitmentProof, error) {
return s.stateCommitment.GetProof(version, key)
func (s *Store) Query(storeKey string, version uint64, key []byte, prove bool) (store.QueryResult, error) {
val, err := s.stateStore.Get(storeKey, version, key)
if err != nil {
return store.QueryResult{}, err
}

result := store.QueryResult{
Key: key,
Value: val,
Version: version,
}

if prove {
proof, err := s.stateCommitment.GetProof(version, key)
if err != nil {
return store.QueryResult{}, err
}

result.Proof = proof
}

return result, nil
}

// LoadVersion loads a specific version returning an error upon failure.
Expand Down
13 changes: 6 additions & 7 deletions store/root/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,9 @@ func (s *RootStoreTestSuite) TestGetBranchedKVStore() {
s.Require().Empty(bs.GetChangeset().Pairs)
}

func (s *RootStoreTestSuite) TestGetProof() {
p, err := s.rootStore.GetProof("", 1, []byte("foo"))
func (s *RootStoreTestSuite) TestQuery() {
_, err := s.rootStore.Query("", 1, []byte("foo"), true)
s.Require().Error(err)
s.Require().Nil(p)

// write and commit a changeset
bs := s.rootStore.GetBranchedKVStore("")
Expand All @@ -88,11 +87,11 @@ func (s *RootStoreTestSuite) TestGetProof() {
s.Require().Equal(workingHash, commitHash)

// ensure the proof is non-nil for the corresponding version
p, err = s.rootStore.GetProof("", 1, []byte("foo"))
result, err := s.rootStore.Query("", 1, []byte("foo"), true)
s.Require().NoError(err)
s.Require().NotNil(p)
s.Require().Equal([]byte("foo"), p.GetExist().Key)
s.Require().Equal([]byte("bar"), p.GetExist().Value)
s.Require().NotNil(result.Proof)
s.Require().Equal([]byte("foo"), result.Proof.GetExist().Key)
s.Require().Equal([]byte("bar"), result.Proof.GetExist().Value)
}

func (s *RootStoreTestSuite) TestBranch() {
Expand Down
57 changes: 47 additions & 10 deletions store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (
ics23 "github.com/cosmos/ics23/go"
)

// TODO: Move relevant types to the 'core' package.

// StoreType defines a type of KVStore.
type StoreType int

Expand All @@ -21,32 +19,63 @@ const (
// RootStore defines an abstraction layer containing a State Storage (SS) engine
// and one or more State Commitment (SC) engines.
type RootStore interface {
// GetSCStore should return the SC backend for the given store key. A RootStore
// implementation may choose to ignore the store key in cases where only a single
// SC backend is used.
GetSCStore(storeKey string) Tree
// MountSCStore should mount the given SC backend for the given store key. For
// implementations that utilize a single SC backend, this method may be optional
// or a no-op.
MountSCStore(storeKey string, sc Tree) error
// GetKVStore returns the KVStore for the given store key. If an implementation
// chooses to have a single SS backend, the store key may be ignored.
GetKVStore(storeKey string) KVStore
// GetBranchedKVStore returns the KVStore for the given store key. If an
// implementation chooses to have a single SS backend, the store key may be
// ignored.
GetBranchedKVStore(storeKey string) BranchedKVStore

GetProof(storeKey string, version uint64, key []byte) (*ics23.CommitmentProof, error)
// Query performs a query on the RootStore for a given store key, version (height),
// and key tuple. Queries should be routed to the underlying SS engine.
Query(storeKey string, version uint64, key []byte, prove bool) (QueryResult, error)

// Branch should branch the entire RootStore, i.e. a copy of the original RootStore
// except with all internal KV store(s) branched.
Branch() BranchedRootStore

// SetTracingContext sets the tracing context, i.e tracing metadata, on the
// RootStore.
SetTracingContext(tc TraceContext)
// SetTracer sets the tracer on the RootStore, such that any calls to GetKVStore
// or GetBranchedKVStore, will have tracing enabled.
SetTracer(w io.Writer)
// TracingEnabled returns true if tracing is enabled on the RootStore.
TracingEnabled() bool

LoadVersion(version uint64) error
LoadLatestVersion() error

// GetLatestVersion returns the latest version, i.e. height, committed.
GetLatestVersion() (uint64, error)

WorkingHash() ([]byte, error)
// SetCommitHeader sets the commit header for the next commit. This call and
// implementation is optional. However, it must be supported in cases where
// queries based on block time need to be supported.
SetCommitHeader(h CommitHeader)
Commit() ([]byte, error)

// TODO:
//
// - Queries
//
// Ref: https://github.com/cosmos/cosmos-sdk/issues/17314
// WorkingHash returns the current WIP commitment hash. Depending on the underlying
// implementation, this may need to take the current changeset and write it to
// the SC backend(s). In such cases, Commit() would return this hash and flush
// writes to disk. This means that WorkingHash mutates the RootStore and must
// be called prior to Commit().
WorkingHash() ([]byte, error)
// Commit should be responsible for taking the current changeset and flushing
// it to disk. Note, depending on the implementation, the changeset, at this
// point, may already be written to the SC backends. Commit() should ensure
// the changeset is committed to all SC and SC backends and flushed to disk.
// It must return a hash of the merkle-ized committed state. This hash should
// be the same as the hash returned by WorkingHash() prior to calling Commit().
Commit() ([]byte, error)

io.Closer
}
Expand Down Expand Up @@ -121,3 +150,11 @@ type BranchedKVStore interface {
// BranchWithTrace recursively wraps with tracing enabled.
BranchWithTrace(w io.Writer, tc TraceContext) BranchedKVStore
}

// QueryResult defines the response type to performing a query on a RootStore.
type QueryResult struct {
Key []byte
Value []byte
Version uint64
Proof *ics23.CommitmentProof
}

0 comments on commit 5cd5003

Please sign in to comment.