cosmos-sdk/store/v2/smt/store.go

117 lines
2.5 KiB
Go

package smt
import (
"crypto/sha256"
"errors"
dbm "github.com/cosmos/cosmos-sdk/db"
"github.com/cosmos/cosmos-sdk/store/types"
"github.com/lazyledger/smt"
tmcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto"
)
var (
_ types.BasicKVStore = (*Store)(nil)
_ smt.MapStore = (dbMapStore{})
)
var (
errKeyEmpty = errors.New("key is empty or nil")
errValueNil = errors.New("value is nil")
)
// Store Implements types.KVStore and CommitKVStore.
type Store struct {
tree *smt.SparseMerkleTree
}
// An smt.MapStore that wraps Get to raise smt.InvalidKeyError;
// smt.SparseMerkleTree expects this error to be returned when a key is not found
type dbMapStore struct{ dbm.DBReadWriter }
func NewStore(nodes, values dbm.DBReadWriter) *Store {
return &Store{
tree: smt.NewSparseMerkleTree(dbMapStore{nodes}, dbMapStore{values}, sha256.New()),
}
}
func LoadStore(nodes, values dbm.DBReadWriter, root []byte) *Store {
return &Store{
tree: smt.ImportSparseMerkleTree(dbMapStore{nodes}, dbMapStore{values}, sha256.New(), root),
}
}
func (s *Store) GetProof(key []byte) (*tmcrypto.ProofOps, error) {
proof, err := s.tree.Prove(key)
if err != nil {
return nil, err
}
op := NewProofOp(s.tree.Root(), key, SHA256, proof)
return &tmcrypto.ProofOps{Ops: []tmcrypto.ProofOp{op.ProofOp()}}, nil
}
func (s *Store) Root() []byte { return s.tree.Root() }
// BasicKVStore interface below:
// Get returns nil iff key doesn't exist. Panics on nil key.
func (s *Store) Get(key []byte) []byte {
if len(key) == 0 {
panic(errKeyEmpty)
}
val, err := s.tree.Get(key)
if err != nil {
panic(err)
}
return val
}
// Has checks if a key exists. Panics on nil key.
func (s *Store) Has(key []byte) bool {
if len(key) == 0 {
panic(errKeyEmpty)
}
has, err := s.tree.Has(key)
if err != nil {
panic(err)
}
return has
}
// Set sets the key. Panics on nil key or value.
func (s *Store) Set(key []byte, value []byte) {
if len(key) == 0 {
panic(errKeyEmpty)
}
if value == nil {
panic(errValueNil)
}
_, err := s.tree.Update(key, value)
if err != nil {
panic(err)
}
}
// Delete deletes the key. Panics on nil key.
func (s *Store) Delete(key []byte) {
if len(key) == 0 {
panic(errKeyEmpty)
}
_, err := s.tree.Delete(key)
if err != nil {
panic(err)
}
}
func (ms dbMapStore) Get(key []byte) ([]byte, error) {
val, err := ms.DBReadWriter.Get(key)
if err != nil {
return nil, err
}
if val == nil {
return nil, &smt.InvalidKeyError{key}
}
return val, nil
}