From baea45177d5c404709d9d30c3458978f66d9d00e Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 3 Feb 2018 02:02:40 -0500 Subject: [PATCH] example/dummy: remove iavl dep - just use raw db --- example/dummy/dummy.go | 81 +++++++++++++++++++++---------- example/dummy/dummy_test.go | 9 ---- example/dummy/persistent_dummy.go | 41 +++++----------- glide.lock | 8 ++- glide.yaml | 2 - 5 files changed, 71 insertions(+), 70 deletions(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 1d4eb1777..79aa43978 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -2,30 +2,70 @@ package dummy import ( "bytes" + "encoding/binary" + "encoding/json" "fmt" "github.com/tendermint/abci/example/code" "github.com/tendermint/abci/types" - "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" ) +var ( + stateKey = []byte("stateKey") + kvPairPrefixKey = []byte("kvPairKey:") +) + +type State struct { + db dbm.DB + Size int64 `json:"size"` + Height int64 `json:"height"` + AppHash []byte `json:"app_hash"` +} + +func loadState(db dbm.DB) State { + stateBytes := db.Get(stateKey) + var state State + if len(stateBytes) != 0 { + err := json.Unmarshal(stateBytes, &state) + if err != nil { + panic(err) + } + } + state.db = db + return state +} + +func saveState(state State) { + stateBytes, err := json.Marshal(state) + if err != nil { + panic(err) + } + state.db.Set(stateKey, stateBytes) +} + +func prefixKey(key []byte) []byte { + return append(kvPairPrefixKey, key...) +} + +//--------------------------------------------------- + var _ types.Application = (*DummyApplication)(nil) type DummyApplication struct { types.BaseApplication - state *iavl.VersionedTree + state State } func NewDummyApplication() *DummyApplication { - state := iavl.NewVersionedTree(dbm.NewMemDB(), 0) + state := loadState(dbm.NewMemDB()) return &DummyApplication{state: state} } func (app *DummyApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { - return types.ResponseInfo{Data: fmt.Sprintf("{\"size\":%v}", app.state.Size())} + return types.ResponseInfo{Data: fmt.Sprintf("{\"size\":%v}", app.state.Size)} } // tx is either "key=value" or just arbitrary bytes @@ -37,7 +77,8 @@ func (app *DummyApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { } else { key, value = tx, tx } - app.state.Set(key, value) + app.state.db.Set(prefixKey(key), value) + app.state.Size += 1 tags := []cmn.KVPair{ {[]byte("app.creator"), []byte("jae")}, @@ -51,32 +92,21 @@ func (app *DummyApplication) CheckTx(tx []byte) types.ResponseCheckTx { } func (app *DummyApplication) Commit() types.ResponseCommit { - // Save a new version - var hash []byte - var err error - - if app.state.Size() > 0 { - hash, _, err = app.state.SaveVersion() - if err != nil { - // if this wasn't a dummy app, we'd do something smarter - panic(err) - } - } - - return types.ResponseCommit{Data: hash} + // Using a memdb - just return the big endian size of the db + appHash := make([]byte, 8) + binary.PutVarint(appHash, app.state.Size) + app.state.AppHash = appHash + app.state.Height += 1 + saveState(app.state) + return types.ResponseCommit{Data: appHash} } func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { if reqQuery.Prove { - value, proof, err := app.state.GetWithProof(reqQuery.Data) - // if this wasn't a dummy app, we'd do something smarter - if err != nil { - panic(err) - } + value := app.state.db.Get(prefixKey(reqQuery.Data)) resQuery.Index = -1 // TODO make Proof return index resQuery.Key = reqQuery.Data resQuery.Value = value - resQuery.Proof = proof.Bytes() if value != nil { resQuery.Log = "exists" } else { @@ -84,8 +114,7 @@ func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types. } return } else { - index, value := app.state.Get(reqQuery.Data) - resQuery.Index = int64(index) + value := app.state.db.Get(prefixKey(reqQuery.Data)) resQuery.Value = value if value != nil { resQuery.Log = "exists" diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 42ac931c9..2affe7c03 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/require" - "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" @@ -41,10 +40,6 @@ func testDummy(t *testing.T, app types.Application, tx []byte, key, value string }) require.EqualValues(t, code.CodeTypeOK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) - proof, err := iavl.ReadKeyProof(resQuery.Proof) - require.Nil(t, err) - err = proof.Verify([]byte(key), resQuery.Value, proof.Root()) - require.Nil(t, err, "%+v", err) // NOTE: we have no way to verify the RootHash } func TestDummyKV(t *testing.T) { @@ -310,8 +305,4 @@ func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) require.Nil(t, err) require.Equal(t, code.CodeTypeOK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) - proof, err := iavl.ReadKeyProof(resQuery.Proof) - require.Nil(t, err) - err = proof.Verify([]byte(key), resQuery.Value, proof.Root()) - require.Nil(t, err, "%+v", err) // NOTE: we have no way to verify the RootHash } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 9bde85fdc..54548a471 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -10,7 +10,6 @@ import ( "github.com/tendermint/abci/example/code" "github.com/tendermint/abci/types" crypto "github.com/tendermint/go-crypto" - "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" "github.com/tendermint/tmlibs/log" @@ -40,11 +39,10 @@ func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { panic(err) } - stateTree := iavl.NewVersionedTree(db, 500) - stateTree.Load() + state := loadState(db) return &PersistentDummyApplication{ - app: &DummyApplication{state: stateTree}, + app: &DummyApplication{state: state}, logger: log.NewNopLogger(), } } @@ -55,8 +53,8 @@ func (app *PersistentDummyApplication) SetLogger(l log.Logger) { func (app *PersistentDummyApplication) Info(req types.RequestInfo) types.ResponseInfo { res := app.app.Info(req) - res.LastBlockHeight = app.app.state.Version64() - res.LastBlockAppHash = app.app.state.Hash() + res.LastBlockHeight = app.app.state.Height + res.LastBlockAppHash = app.app.state.AppHash return res } @@ -84,20 +82,7 @@ func (app *PersistentDummyApplication) CheckTx(tx []byte) types.ResponseCheckTx // Commit will panic if InitChain was not called func (app *PersistentDummyApplication) Commit() types.ResponseCommit { - - // Save a new version for next height - var height int64 - var appHash []byte - var err error - - appHash, height, err = app.app.state.SaveVersion() - if err != nil { - // if this wasn't a dummy app, we'd do something smarter - panic(err) - } - - app.logger.Info("Commit block", "height", height, "root", appHash) - return types.ResponseCommit{Data: appHash} + return app.app.Commit() } func (app *PersistentDummyApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { @@ -131,17 +116,17 @@ func (app *PersistentDummyApplication) EndBlock(req types.RequestEndBlock) types // update validators func (app *PersistentDummyApplication) Validators() (validators []types.Validator) { - app.app.state.Iterate(func(key, value []byte) bool { - if isValidatorTx(key) { + itr := app.app.state.db.Iterator(nil, nil) + for ; itr.Valid(); itr.Next() { + if isValidatorTx(itr.Key()) { validator := new(types.Validator) - err := types.ReadMessage(bytes.NewBuffer(value), validator) + err := types.ReadMessage(bytes.NewBuffer(itr.Value()), validator) if err != nil { panic(err) } validators = append(validators, *validator) } - return false - }) + } return } @@ -197,12 +182,12 @@ func (app *PersistentDummyApplication) updateValidator(v types.Validator) types. key := []byte("val:" + string(v.PubKey)) if v.Power == 0 { // remove validator - if !app.app.state.Has(key) { + if !app.app.state.db.Has(key) { return types.ResponseDeliverTx{ Code: code.CodeTypeUnauthorized, Log: fmt.Sprintf("Cannot remove non-existent validator %X", key)} } - app.app.state.Remove(key) + app.app.state.db.Delete(key) } else { // add or update validator value := bytes.NewBuffer(make([]byte, 0)) @@ -211,7 +196,7 @@ func (app *PersistentDummyApplication) updateValidator(v types.Validator) types. Code: code.CodeTypeEncodingError, Log: fmt.Sprintf("Error encoding validator: %v", err)} } - app.app.state.Set(key, value.Bytes()) + app.app.state.db.Set(key, value.Bytes()) } // we only update the changes array if we successfully updated the tree diff --git a/glide.lock b/glide.lock index c4b7c8125..96ee37852 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: faee2e6d7d388ab8c0425f97b3c628bc952e72b76c9d233762a69071c4819e44 -updated: 2018-02-03T00:14:01.357884929-05:00 +hash: 68167c37a0b261e0adc172c3d92d943da89ff41112043d59ac60844ef8edd882 +updated: 2018-02-03T02:00:50.200133389-05:00 imports: - name: github.com/btcsuite/btcd version: 2e60448ffcc6bf78332d1fe590260095f554dd78 @@ -74,10 +74,8 @@ imports: version: 4fc3055dbd17aa1203d0abc64b9293f378da22ec - name: github.com/tendermint/go-wire version: dec83f641903b22f039da3974607859715d0377e -- name: github.com/tendermint/iavl - version: 1a59ec0c82dc940c25339dd7c834df5cb76a95cb - name: github.com/tendermint/tmlibs - version: 1d7fc78ea171587e9e63da566d3da1b127bfd14c + version: deaaf014d8b8d1095054380a38b1b00e293f725f subpackages: - common - db diff --git a/glide.yaml b/glide.yaml index c0b23c037..47876621d 100644 --- a/glide.yaml +++ b/glide.yaml @@ -12,8 +12,6 @@ import: version: develop - package: github.com/tendermint/go-wire version: develop -- package: github.com/tendermint/iavl - version: develop - package: github.com/tendermint/tmlibs version: develop subpackages: