Skip to content

Commit

Permalink
Revert "[dev] update SMT library"
Browse files Browse the repository at this point in the history
This reverts commit 1a37cc2.
  • Loading branch information
roysc committed Jun 2, 2022
1 parent 5c1b566 commit 5f83976
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 93 deletions.
3 changes: 0 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,3 @@ replace (
)

retract v0.43.0

// DEV
replace github.com/lazyledger/smt => ../smt
2 changes: 1 addition & 1 deletion store/v2alpha1/multi/proof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func keyPath(prefix, key string) string {
func TestVerifySMTStoreProof(t *testing.T) {
// Create main tree for testing.
txn := memdb.NewDB().ReadWriter()
store := smt.NewStore(smt.StoreParams{TreeData: txn})
store := smt.NewStore(txn)
store.Set([]byte("MYKEY"), []byte("MYVALUE"))
root := store.Root()

Expand Down
47 changes: 23 additions & 24 deletions store/v2alpha1/multi/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -504,27 +504,23 @@ func (rs *Store) getSubstore(key string) (*substore, error) {
pfx := substorePrefix(key)
stateRW := prefixdb.NewPrefixReadWriter(rs.stateTxn, pfx)
stateCommitmentRW := prefixdb.NewPrefixReadWriter(rs.stateCommitmentTxn, pfx)

var stateCommitmentStore *smt.Store
data := prefixdb.NewPrefixReadWriter(stateRW, dataPrefix)

rootHash, err := stateRW.Get(substoreMerkleRootKey)
if err != nil {
return nil, err
}
if rootHash != nil {
stateCommitmentStore = loadSMT(stateCommitmentRW, data, rootHash)
stateCommitmentStore = loadSMT(stateCommitmentRW, rootHash)
} else {
params := smt.StoreParams{
TreeData: prefixdb.NewPrefixReadWriter(stateCommitmentRW, smtPrefix),
ValueData: data,
}
stateCommitmentStore = smt.NewStore(params)
smtdb := prefixdb.NewPrefixReadWriter(stateCommitmentRW, smtPrefix)
stateCommitmentStore = smt.NewStore(smtdb)
}

return &substore{
root: rs,
name: key,
dataBucket: data,
dataBucket: prefixdb.NewPrefixReadWriter(stateRW, dataPrefix),
stateCommitmentStore: stateCommitmentStore,
}, nil
}
Expand All @@ -535,7 +531,7 @@ func (s *substore) refresh(rootHash []byte) {
stateRW := prefixdb.NewPrefixReadWriter(s.root.stateTxn, pfx)
stateCommitmentRW := prefixdb.NewPrefixReadWriter(s.root.stateCommitmentTxn, pfx)
s.dataBucket = prefixdb.NewPrefixReadWriter(stateRW, dataPrefix)
s.stateCommitmentStore = loadSMT(stateCommitmentRW, s.dataBucket, rootHash)
s.stateCommitmentStore = loadSMT(stateCommitmentRW, rootHash)
}

// Commit implements Committer.
Expand Down Expand Up @@ -587,20 +583,26 @@ func pruneVersions(current int64, opts pruningtypes.PruningOptions, prune func(i
}
}

// Calculates root hashes and commits to DB. Does not verify target version or perform pruning.
func (s *Store) commit(target uint64) (id *types.CommitID, err error) {
storeHashes := make(map[string][]byte, len(s.schema))
func (s *Store) getMerkleRoots() (ret map[string][]byte, err error) {
ret = map[string][]byte{}
for key := range s.schema {
sub, has := s.substoreCache[key.Name()]
if !has {
if sub, err = s.getSubstore(key.Name()); err != nil {
sub, err = s.getSubstore(key.Name())
if err != nil {
return
}
}
if err = sub.stateCommitmentStore.Commit(); err != nil {
return
}
storeHashes[key.Name()] = sub.stateCommitmentStore.Root()
ret[key.Name()] = sub.stateCommitmentStore.Root()
}
return
}

// Calculates root hashes and commits to DB. Does not verify target version or perform pruning.
func (s *Store) commit(target uint64) (id *types.CommitID, err error) {
storeHashes, err := s.getMerkleRoots()
if err != nil {
return
}
// Update substore Merkle roots
for key, storeHash := range storeHashes {
Expand Down Expand Up @@ -844,12 +846,9 @@ func (rs *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
return res
}

func loadSMT(sc, data dbm.DBReadWriter, root []byte) *smt.Store {
params := smt.StoreParams{
TreeData: prefixdb.NewPrefixReadWriter(sc, smtPrefix),
ValueData: data,
}
return smt.LoadStore(params, root)
func loadSMT(stateCommitmentTxn dbm.DBReadWriter, root []byte) *smt.Store {
smtdb := prefixdb.NewPrefixReadWriter(stateCommitmentTxn, smtPrefix)
return smt.LoadStore(smtdb, root)
}

// Returns closest index and whether it's a match
Expand Down
10 changes: 4 additions & 6 deletions store/v2alpha1/multi/view_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,11 @@ func (vs *viewStore) getSubstore(key string) (*viewSubstore, error) {
if err != nil {
return nil, err
}
data := prefixdb.NewPrefixReader(stateR, dataPrefix)
return &viewSubstore{
root: vs,
name: key,
dataBucket: data,
stateCommitmentStore: loadSMT(
dbm.ReaderAsReadWriter(stateCommitmentR), dbm.ReaderAsReadWriter(data), rootHash),
root: vs,
name: key,
dataBucket: prefixdb.NewPrefixReader(stateR, dataPrefix),
stateCommitmentStore: loadSMT(dbm.ReaderAsReadWriter(stateCommitmentR), rootHash),
}, nil
}

Expand Down
8 changes: 4 additions & 4 deletions store/v2alpha1/smt/ics23.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ import (
func createIcs23Proof(store *Store, key []byte) (*ics23.CommitmentProof, error) {
ret := &ics23.CommitmentProof{}
path := sha256.Sum256(key)
valueHash, err := store.tree.Get(key)
has, err := store.tree.Has(key)
if err != nil {
return nil, err
}
if valueHash != nil { // Membership proof
value, err := store.values.Get(key)
if has { // Membership proof
value, err := store.values.Get(path[:])
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -52,7 +52,7 @@ func toNonExistenceProof(store *Store, path [32]byte) (*ics23.NonExistenceProof,
getNext := func(it dbm.Iterator) (*ics23.ExistenceProof, error) {
defer it.Close()
if it.Next() {
value, err := store.values.Get(it.Value())
value, err := store.values.Get(it.Key())
if err != nil {
return nil, err
}
Expand Down
5 changes: 2 additions & 3 deletions store/v2alpha1/smt/ics23_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (

func TestProofICS23(t *testing.T) {
txn := memdb.NewDB().ReadWriter()
s := store.NewStore(store.StoreParams{TreeData: txn})
s := store.NewStore(txn)
// pick keys whose hashes begin with different bits
key00 := []byte("foo") // 00101100 = sha256(foo)[0]
key01 := []byte("bill") // 01100010
Expand Down Expand Up @@ -74,8 +74,7 @@ func TestProofICS23(t *testing.T) {

// Make sure proofs work with a loaded store
root := s.Root()
assert.NoError(t, s.Commit())
s = store.LoadStore(store.StoreParams{TreeData: txn}, root)
s = store.LoadStore(txn, root)
proof, err = s.GetProofICS23(key10)
assert.NoError(t, err)
nonexist = proof.GetNonexist()
Expand Down
93 changes: 93 additions & 0 deletions store/v2alpha1/smt/proof.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package smt

import (
"bytes"
"crypto/sha256"
"encoding/gob"
"hash"

"github.com/cosmos/cosmos-sdk/store/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/lazyledger/smt"
"github.com/tendermint/tendermint/crypto/merkle"
tmmerkle "github.com/tendermint/tendermint/proto/tendermint/crypto"
)

type HasherType byte

const (
SHA256 HasherType = iota
)

const (
ProofType = "smt"
)

type ProofOp struct {
Root []byte
Key []byte
Hasher HasherType
Proof smt.SparseMerkleProof
}

var _ merkle.ProofOperator = (*ProofOp)(nil)

// NewProofOp returns a ProofOp for a SparseMerkleProof.
func NewProofOp(root, key []byte, hasher HasherType, proof smt.SparseMerkleProof) *ProofOp {
return &ProofOp{
Root: root,
Key: key,
Hasher: hasher,
Proof: proof,
}
}

func (p *ProofOp) Run(args [][]byte) ([][]byte, error) {
switch len(args) {
case 0: // non-membership proof
if !smt.VerifyProof(p.Proof, p.Root, p.Key, []byte{}, getHasher(p.Hasher)) {
return nil, sdkerrors.Wrapf(types.ErrInvalidProof, "proof did not verify absence of key: %s", p.Key)
}
case 1: // membership proof
if !smt.VerifyProof(p.Proof, p.Root, p.Key, args[0], getHasher(p.Hasher)) {
return nil, sdkerrors.Wrapf(types.ErrInvalidProof, "proof did not verify existence of key %s with given value %x", p.Key, args[0])
}
default:
return nil, sdkerrors.Wrapf(types.ErrInvalidProof, "args must be length 0 or 1, got: %d", len(args))
}
return [][]byte{p.Root}, nil
}

func (p *ProofOp) GetKey() []byte {
return p.Key
}

func (p *ProofOp) ProofOp() tmmerkle.ProofOp {
var data bytes.Buffer
enc := gob.NewEncoder(&data)
enc.Encode(p)
return tmmerkle.ProofOp{
Type: "smt",
Key: p.Key,
Data: data.Bytes(),
}
}

func ProofDecoder(pop tmmerkle.ProofOp) (merkle.ProofOperator, error) {
dec := gob.NewDecoder(bytes.NewBuffer(pop.Data))
var proof ProofOp
err := dec.Decode(&proof)
if err != nil {
return nil, err
}
return &proof, nil
}

func getHasher(hasher HasherType) hash.Hash {
switch hasher {
case SHA256:
return sha256.New()
default:
return nil
}
}
Loading

0 comments on commit 5f83976

Please sign in to comment.