Get abci commit hash/height working
This commit is contained in:
parent
e85854fa83
commit
e0604baad5
|
@ -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")
|
||||
}
|
||||
|
|
84
app/store.go
84
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,21 +68,10 @@ 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")
|
||||
}
|
||||
|
@ -109,57 +79,49 @@ func NewStore(dbName string, cacheSize int, logger log.Logger) (*Store, error) {
|
|||
|
||||
res := &Store{
|
||||
State: state.NewState(tree),
|
||||
height: chainState.Height,
|
||||
hash: chainState.Hash,
|
||||
persisted: true,
|
||||
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
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue