diff --git a/app/app_test.go b/app/app_test.go index fca03e15e..1cf983459 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - abci "github.com/tendermint/abci/types" sdk "github.com/cosmos/cosmos-sdk" "github.com/cosmos/cosmos-sdk/modules/auth" "github.com/cosmos/cosmos-sdk/modules/base" @@ -18,6 +17,7 @@ import ( "github.com/cosmos/cosmos-sdk/modules/roles" "github.com/cosmos/cosmos-sdk/stack" "github.com/cosmos/cosmos-sdk/state" + abci "github.com/tendermint/abci/types" wire "github.com/tendermint/go-wire" "github.com/tendermint/tmlibs/log" ) @@ -294,9 +294,10 @@ func TestQuery(t *testing.T) { res = at.app.Commit() assert.True(res.IsOK(), res) + key := stack.PrefixedKey(coin.NameCoin, at.acctIn.Address()) resQueryPostCommit := at.app.Query(abci.RequestQuery{ - Path: "/account", - Data: at.acctIn.Address(), + Path: "/key", + Data: key, }) assert.NotEqual(resQueryPreCommit, resQueryPostCommit, "Query should change before/after commit") } diff --git a/app/store.go b/app/store.go index 1f4442004..ee933fab9 100644 --- a/app/store.go +++ b/app/store.go @@ -1,7 +1,6 @@ package app import ( - "bytes" "fmt" "path" "path/filepath" @@ -9,7 +8,6 @@ import ( "github.com/pkg/errors" abci "github.com/tendermint/abci/types" - "github.com/tendermint/go-wire" "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" @@ -21,21 +19,9 @@ import ( // Store contains the merkle tree, and all info to handle abci requests type Store struct { state.State - height uint64 - hash []byte - persisted bool - logger log.Logger } -var stateKey = []byte("merkle:state") // Database key for merkle tree save value db values - -// ChainState contains the latest Merkle root hash and the number of times `Commit` has been called -type ChainState struct { - Hash []byte - Height uint64 -} - // MockStore returns an in-memory store only intended for testing func MockStore() *Store { res, err := NewStore("", 0, log.NewNopLogger()) @@ -49,11 +35,7 @@ func MockStore() *Store { // NewStore initializes an in-memory iavl.VersionedTree, or attempts to load a // persistant tree from disk func NewStore(dbName string, cacheSize int, logger log.Logger) (*Store, error) { - // start at 1 so the height returned by query is for the - // next block, ie. the one that includes the AppHash for our current state - initialHeight := uint64(1) - - // Non-persistent case + // memory backed case, just for testing if dbName == "" { tree := iavl.NewVersionedTree( 0, @@ -61,7 +43,6 @@ func NewStore(dbName string, cacheSize int, logger log.Logger) (*Store, error) { ) store := &Store{ State: state.NewState(tree), - height: initialHeight, logger: logger, } return store, nil @@ -87,79 +68,60 @@ func NewStore(dbName string, cacheSize int, logger log.Logger) (*Store, error) { db := dbm.NewDB(name, dbm.LevelDBBackendStr, dir) tree := iavl.NewVersionedTree(cacheSize, db) - var chainState ChainState if empty { logger.Info("no existing db, creating new db") - chainState = ChainState{ - Hash: nil, - Height: initialHeight, - } - db.Set(stateKey, wire.BinaryBytes(chainState)) } else { logger.Info("loading existing db") - eyesStateBytes := db.Get(stateKey) - - if err = wire.ReadBinaryBytes(eyesStateBytes, &chainState); err != nil { - return nil, errors.Wrap(err, "Reading MerkleEyesState") - } if err = tree.Load(); err != nil { return nil, errors.Wrap(err, "Loading tree") } } res := &Store{ - State: state.NewState(tree), - height: chainState.Height, - hash: chainState.Hash, - persisted: true, - logger: logger, + State: state.NewState(tree), + logger: logger, } return res, nil } +func (s *Store) Height() uint64 { + return s.State.Committed().Tree.LatestVersion() +} + +func (s *Store) Hash() []byte { + return s.State.Committed().Tree.Hash() +} + // Info implements abci.Application. It returns the height, hash and size (in the data). // The height is the block that holds the transactions, not the apphash itself. func (s *Store) Info() abci.ResponseInfo { s.logger.Info("Info synced", - "height", s.height, - "hash", fmt.Sprintf("%X", s.hash)) + "height", s.Height(), + "hash", fmt.Sprintf("%X", s.Hash())) return abci.ResponseInfo{ Data: cmn.Fmt("size:%v", s.State.Size()), - LastBlockHeight: s.height - 1, - LastBlockAppHash: s.hash, + LastBlockHeight: s.Height() - 1, + LastBlockAppHash: s.Hash(), } } // Commit implements abci.Application func (s *Store) Commit() abci.Result { - var err error - s.height++ - s.hash, err = s.State.Hash() + height := s.Height() + 1 + + hash, err := s.State.Commit(height) if err != nil { return abci.NewError(abci.CodeType_InternalError, err.Error()) } - s.logger.Debug("Commit synced", - "height", s.height, - "hash", fmt.Sprintf("%X", s.hash)) - - s.State.BatchSet(stateKey, wire.BinaryBytes(ChainState{ - Hash: s.hash, - Height: s.height, - })) - - hash, err := s.State.Commit(s.height) - if err != nil { - return abci.NewError(abci.CodeType_InternalError, err.Error()) - } - if !bytes.Equal(hash, s.hash) { - return abci.NewError(abci.CodeType_InternalError, "AppHash is incorrect") - } + "height", height, + "hash", fmt.Sprintf("%X", hash), + ) if s.State.Size() == 0 { return abci.NewResultOK(nil, "Empty hash for empty tree") } - return abci.NewResultOK(s.hash, "") + return abci.NewResultOK(hash, "") } // Query implements abci.Application @@ -169,10 +131,10 @@ func (s *Store) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) height := reqQuery.Height if height == 0 { - if tree.Tree.VersionExists(s.height - 1) { - height = s.height - 1 + if tree.Tree.VersionExists(s.Height() - 1) { + height = s.Height() - 1 } else { - height = s.height + height = s.Height() } } resQuery.Height = height diff --git a/state/merkle.go b/state/merkle.go index a097b9431..f23be1cc7 100644 --- a/state/merkle.go +++ b/state/merkle.go @@ -37,21 +37,6 @@ func (s State) Check() SimpleDB { return s.checkTx } -// Hash applies deliverTx to committed and calculates hash -// -// Note the usage: -// Hash -> gets the calculated hash but doesn't save -// BatchSet -> adds some out-of-bounds data -// Commit -> Save everything to disk and the same hash -func (s *State) Hash() ([]byte, error) { - err := s.committed.Commit(s.deliverTx) - if err != nil { - return nil, err - } - s.deliverTx = s.committed.Checkpoint() - return s.committed.Tree.Hash(), nil -} - // BatchSet is used for some weird magic in storing the new height func (s *State) BatchSet(key, value []byte) { if s.persistent {