From 9aff9f94dde85528686856815405d92f47b8fbb3 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Oct 2017 12:46:51 +0200 Subject: [PATCH 1/9] dummy app now uses iavl --- example/dummy/dummy.go | 23 ++++++---- example/dummy/dummy_test.go | 12 ++--- example/dummy/persistent_dummy.go | 74 +++++++++++++------------------ glide.lock | 16 +++---- glide.yaml | 4 +- 5 files changed, 59 insertions(+), 70 deletions(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 5db71f96..82927ca6 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -4,19 +4,20 @@ import ( "strings" "github.com/tendermint/abci/types" - "github.com/tendermint/merkleeyes/iavl" + wire "github.com/tendermint/go-wire" + "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" - "github.com/tendermint/tmlibs/merkle" + dbm "github.com/tendermint/tmlibs/db" ) type DummyApplication struct { types.BaseApplication - state merkle.Tree + state *iavl.VersionedTree } func NewDummyApplication() *DummyApplication { - state := iavl.NewIAVLTree(0, nil) + state := iavl.NewVersionedTree(0, dbm.NewMemDB()) return &DummyApplication{state: state} } @@ -46,22 +47,26 @@ func (app *DummyApplication) Commit() types.Result { func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { if reqQuery.Prove { - value, proof, exists := app.state.Proof(reqQuery.Data) + value, proof, err := app.state.GetWithProof(reqQuery.Data) + // be stupid here + if err != nil { + panic(err) + } resQuery.Index = -1 // TODO make Proof return index resQuery.Key = reqQuery.Data resQuery.Value = value - resQuery.Proof = proof - if exists { + resQuery.Proof = wire.BinaryBytes(proof) + if value == nil { resQuery.Log = "exists" } else { resQuery.Log = "does not exist" } return } else { - index, value, exists := app.state.Get(reqQuery.Data) + index, value := app.state.Get(reqQuery.Data) resQuery.Index = int64(index) resQuery.Value = value - if exists { + if value != nil { resQuery.Log = "exists" } else { resQuery.Log = "does not exist" diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index fa9d531b..41e033bc 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -11,7 +11,7 @@ import ( "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" crypto "github.com/tendermint/go-crypto" - "github.com/tendermint/merkleeyes/iavl" + "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" ) @@ -39,9 +39,10 @@ func testDummy(t *testing.T, app types.Application, tx []byte, key, value string }) require.Equal(t, types.CodeType_OK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) - proof, err := iavl.ReadProof(resQuery.Proof) + proof, err := iavl.ReadKeyExistsProof(resQuery.Proof) require.Nil(t, err) - require.True(t, proof.Verify([]byte(key), resQuery.Value, proof.RootHash)) // NOTE: we have no way to verify the RootHash + err = proof.Verify([]byte(key), resQuery.Value, proof.RootHash) + require.Nil(t, err, "%+v", err) // NOTE: we have no way to verify the RootHash } func TestDummyKV(t *testing.T) { @@ -309,7 +310,8 @@ func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) require.Nil(t, err) require.Equal(t, types.CodeType_OK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) - proof, err := iavl.ReadProof(resQuery.Proof) + proof, err := iavl.ReadKeyExistsProof(resQuery.Proof) require.Nil(t, err) - require.True(t, proof.Verify([]byte(key), resQuery.Value, proof.RootHash)) // NOTE: we have no way to verify the RootHash + err = proof.Verify([]byte(key), resQuery.Value, proof.RootHash) + 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 a8bfbcf0..89bc6e72 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -3,13 +3,12 @@ package dummy import ( "bytes" "encoding/hex" + "path" "strconv" "strings" - "github.com/pkg/errors" "github.com/tendermint/abci/types" - wire "github.com/tendermint/go-wire" - "github.com/tendermint/merkleeyes/iavl" + "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" "github.com/tendermint/tmlibs/log" @@ -23,11 +22,11 @@ const ( type PersistentDummyApplication struct { app *DummyApplication - db dbm.DB // latest received // TODO: move to merkle tree? blockHeader *types.Header + height uint64 // validator set changes []*types.Validator @@ -36,17 +35,22 @@ type PersistentDummyApplication struct { } func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { - db := dbm.NewDB("dummy", "leveldb", dbDir) - lastBlock := LoadLastBlock(db) + name := "dummy" + dbPath := path.Join(dbDir, name+".db") + empty, _ := cmn.IsDirEmpty(dbPath) - stateTree := iavl.NewIAVLTree(0, db) - stateTree.Load(lastBlock.AppHash) + db, err := dbm.NewGoLevelDB(name, dbDir) + if err != nil { + panic(err) + } - // log.Notice("Loaded state", "block", lastBlock.Height, "root", stateTree.Hash()) + stateTree := iavl.NewVersionedTree(500, db) + if !empty { + stateTree.Load() + } return &PersistentDummyApplication{ app: &DummyApplication{state: stateTree}, - db: db, logger: log.NewNopLogger(), } } @@ -57,9 +61,8 @@ func (app *PersistentDummyApplication) SetLogger(l log.Logger) { func (app *PersistentDummyApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { resInfo = app.app.Info(req) - lastBlock := LoadLastBlock(app.db) - resInfo.LastBlockHeight = lastBlock.Height - resInfo.LastBlockAppHash = lastBlock.AppHash + resInfo.LastBlockHeight = app.height + resInfo.LastBlockAppHash = app.app.state.Hash() return resInfo } @@ -86,18 +89,26 @@ func (app *PersistentDummyApplication) CheckTx(tx []byte) types.Result { } func (app *PersistentDummyApplication) Commit() types.Result { - // Save - appHash := app.app.state.Save() - app.logger.Info("Saved state", "root", appHash) + app.height = app.blockHeader.Height + + // Save a new version + var appHash []byte + var err error + if app.app.state.Size() > 0 { + appHash, err = app.app.state.SaveVersion(app.height) + if err != nil { + // if this wasn't a dummy app, we'd do something smarter + panic(err) + } + app.logger.Info("Saved state", "root", appHash) + } lastBlock := LastBlockInfo{ - Height: app.blockHeader.Height, + Height: app.height, AppHash: appHash, // this hash will be in the next block header } app.logger.Info("Saving block", "height", lastBlock.Height, "root", lastBlock.AppHash) - SaveLastBlock(app.db, lastBlock) - return types.NewResultOK(appHash, "") } @@ -139,31 +150,6 @@ type LastBlockInfo struct { AppHash []byte } -// Get the last block from the db -func LoadLastBlock(db dbm.DB) (lastBlock LastBlockInfo) { - buf := db.Get(lastBlockKey) - if len(buf) != 0 { - r, n, err := bytes.NewReader(buf), new(int), new(error) - wire.ReadBinaryPtr(&lastBlock, r, 0, n, err) - if *err != nil { - cmn.PanicCrisis(errors.Wrap(*err, "cannot load last block (data has been corrupted or its spec has changed)")) - } - // TODO: ensure that buf is completely read. - } - - return lastBlock -} - -func SaveLastBlock(db dbm.DB, lastBlock LastBlockInfo) { - buf, n, err := new(bytes.Buffer), new(int), new(error) - wire.WriteBinary(lastBlock, buf, n, err) - if *err != nil { - // TODO - cmn.PanicCrisis(errors.Wrap(*err, "cannot save last block")) - } - db.Set(lastBlockKey, buf.Bytes()) -} - //--------------------------------------------- // update validators diff --git a/glide.lock b/glide.lock index 7b79f0e5..d2dfc9a6 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: f9c2ddad16bf8652076a93bd9f398bb498eefb2f5bd2c89a77d966ebd12feec8 -updated: 2017-09-22T10:34:17.228026799-04:00 +hash: 876bc65024f66612325ebafcedeb3e4d5014d46b339cf7583f1c00c6bac6e32c +updated: 2017-10-18T11:59:44.724549502+02:00 imports: - name: github.com/btcsuite/btcd version: b8df516b4b267acf2de46be593a9d948d1d2c420 @@ -57,17 +57,15 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-crypto - version: e6ea9499ff958479e4a921850d2382eb599f204c + version: 8e7f0e7701f92206679ad093d013b9b162427631 - name: github.com/tendermint/go-wire - version: 5f88da3dbc1a72844e6dfaf274ce87f851d488eb + version: 26ee079df7fca1958da8995c727b59759b197534 subpackages: - data -- name: github.com/tendermint/merkleeyes - version: 2f6e5d31e7a35045d8d0a5895cb1fec33dd4d32b - subpackages: - - iavl +- name: github.com/tendermint/iavl + version: ff4ffa531df48509d51f0c16c2432f986eed9fcc - name: github.com/tendermint/tmlibs - version: bffe6744ec277d60f707ab442e25513617842f8e + version: 8e5266a9ef2527e68a1571f932db8228a331b556 subpackages: - common - db diff --git a/glide.yaml b/glide.yaml index 11379aad..e8cf8302 100644 --- a/glide.yaml +++ b/glide.yaml @@ -8,10 +8,8 @@ import: version: develop - package: github.com/tendermint/go-wire version: develop -- package: github.com/tendermint/merkleeyes +- package: github.com/tendermint/iavl version: develop - subpackages: - - iavl - package: github.com/tendermint/tmlibs version: develop subpackages: From bae4e4acce1c364c76c95663788f9fa8c2abc312 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Oct 2017 13:13:18 +0200 Subject: [PATCH 2/9] Fix up commits, debug cli tests --- example/dummy/dummy.go | 17 ++++++++++++++++- example/dummy/persistent_dummy.go | 8 ++------ tests/test_cli/ex1.abci.out | 18 +++++++++--------- tests/test_cli/test.sh | 1 + 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 82927ca6..89f997a4 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -1,6 +1,7 @@ package dummy import ( + "fmt" "strings" "github.com/tendermint/abci/types" @@ -33,6 +34,7 @@ func (app *DummyApplication) DeliverTx(tx []byte) types.Result { } else { app.state.Set(tx, tx) } + fmt.Println("set data") return types.OK } @@ -41,7 +43,20 @@ func (app *DummyApplication) CheckTx(tx []byte) types.Result { } func (app *DummyApplication) Commit() types.Result { - hash := app.state.Hash() + // Save a new version + var hash []byte + var err error + + if app.state.Size() > 0 { + // just add one more to height (kind of arbitrarily stupid) + height := app.state.LatestVersion() + 1 + hash, err = app.state.SaveVersion(height) + if err != nil { + // if this wasn't a dummy app, we'd do something smarter + panic(err) + } + } + return types.NewResultOK(hash, "") } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 89bc6e72..cc2d2d40 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -94,6 +94,7 @@ func (app *PersistentDummyApplication) Commit() types.Result { // Save a new version var appHash []byte var err error + if app.app.state.Size() > 0 { appHash, err = app.app.state.SaveVersion(app.height) if err != nil { @@ -103,12 +104,7 @@ func (app *PersistentDummyApplication) Commit() types.Result { app.logger.Info("Saved state", "root", appHash) } - lastBlock := LastBlockInfo{ - Height: app.height, - AppHash: appHash, // this hash will be in the next block header - } - - app.logger.Info("Saving block", "height", lastBlock.Height, "root", lastBlock.AppHash) + app.logger.Info("Commit block", "height", app.height, "root", appHash) return types.NewResultOK(appHash, "") } diff --git a/tests/test_cli/ex1.abci.out b/tests/test_cli/ex1.abci.out index e434944a..c3a62d55 100644 --- a/tests/test_cli/ex1.abci.out +++ b/tests/test_cli/ex1.abci.out @@ -2,21 +2,21 @@ -> data: hello -> data.hex: 68656C6C6F -> info +> info -> data: {"size":0} -> data.hex: 7B2273697A65223A307D -> commit +> commit > deliver_tx "abc" -> info +> info -> data: {"size":1} -> data.hex: 7B2273697A65223A317D -> commit --> data: uü~„»×ˆíX–$ðlú‡EÑ --> data.hex: 750502FC7E84BBD788ED589624F06CFA871845D1 +> commit +-> data: IßÑ\ͬޮ—(ËûµèhŒ¥‹‘ +-> data.hex: 49DFD15CCDACDEAE9728CB01FBB5E8688CA58B91 > query "abc" -> log: exists @@ -26,9 +26,9 @@ > deliver_tx "def=xyz" -> commit --> data: v9;Š.E†°iLbžËQ²†ïÕ --> data.hex: 76393B8A182E450286B0694C629ECB51B286EFD5 +> commit +-> data: p-³"€7?¿?Ÿ‰Ú* Î,Ö+ +-> data.hex: 70102DB32280373FBF3F9F89DA2A20CE2CD62B0B > query "def" -> log: exists diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh index 4266dd16..8ea8d545 100644 --- a/tests/test_cli/test.sh +++ b/tests/test_cli/test.sh @@ -15,6 +15,7 @@ function testExample() { echo "Example $N" $APP &> /dev/null & + # $APP &> ./app.out & sleep 2 abci-cli --verbose batch < "$INPUT" > "${INPUT}.out.new" killall "$APP" From d236e0eef9a6ecc12a736fdae85f635238053e24 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Oct 2017 13:28:24 +0200 Subject: [PATCH 3/9] Fix trailing whitespace in tutorial test --- tests/test_cli/ex1.abci.out | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_cli/ex1.abci.out b/tests/test_cli/ex1.abci.out index c3a62d55..21c778c7 100644 --- a/tests/test_cli/ex1.abci.out +++ b/tests/test_cli/ex1.abci.out @@ -2,19 +2,19 @@ -> data: hello -> data.hex: 68656C6C6F -> info +> info -> data: {"size":0} -> data.hex: 7B2273697A65223A307D -> commit +> commit > deliver_tx "abc" -> info +> info -> data: {"size":1} -> data.hex: 7B2273697A65223A317D -> commit +> commit -> data: IßÑ\ͬޮ—(ËûµèhŒ¥‹‘ -> data.hex: 49DFD15CCDACDEAE9728CB01FBB5E8688CA58B91 @@ -26,7 +26,7 @@ > deliver_tx "def=xyz" -> commit +> commit -> data: p-³"€7?¿?Ÿ‰Ú* Î,Ö+ -> data.hex: 70102DB32280373FBF3F9F89DA2A20CE2CD62B0B From 46e1f1ae653a49f18ae813fc3a441edf219f0ce5 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 19 Oct 2017 14:43:34 +0200 Subject: [PATCH 4/9] Cleaup based on Antons PR comments --- example/dummy/dummy.go | 6 ++---- example/dummy/persistent_dummy.go | 7 ++++--- tests/test_cli/test.sh | 1 - 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 89f997a4..7e95c859 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -1,7 +1,6 @@ package dummy import ( - "fmt" "strings" "github.com/tendermint/abci/types" @@ -34,7 +33,6 @@ func (app *DummyApplication) DeliverTx(tx []byte) types.Result { } else { app.state.Set(tx, tx) } - fmt.Println("set data") return types.OK } @@ -63,7 +61,7 @@ func (app *DummyApplication) Commit() types.Result { func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { if reqQuery.Prove { value, proof, err := app.state.GetWithProof(reqQuery.Data) - // be stupid here + // if this wasn't a dummy app, we'd do something smarter if err != nil { panic(err) } @@ -71,7 +69,7 @@ func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types. resQuery.Key = reqQuery.Data resQuery.Value = value resQuery.Proof = wire.BinaryBytes(proof) - if value == nil { + if value != nil { resQuery.Log = "exists" } else { resQuery.Log = "does not exist" diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index cc2d2d40..94ce85ad 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -89,14 +89,14 @@ func (app *PersistentDummyApplication) CheckTx(tx []byte) types.Result { } func (app *PersistentDummyApplication) Commit() types.Result { - app.height = app.blockHeader.Height + h := app.blockHeader.Height // Save a new version var appHash []byte var err error if app.app.state.Size() > 0 { - appHash, err = app.app.state.SaveVersion(app.height) + appHash, err = app.app.state.SaveVersion(h) if err != nil { // if this wasn't a dummy app, we'd do something smarter panic(err) @@ -104,7 +104,8 @@ func (app *PersistentDummyApplication) Commit() types.Result { app.logger.Info("Saved state", "root", appHash) } - app.logger.Info("Commit block", "height", app.height, "root", appHash) + app.height = h + app.logger.Info("Commit block", "height", h, "root", appHash) return types.NewResultOK(appHash, "") } diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh index 8ea8d545..4266dd16 100644 --- a/tests/test_cli/test.sh +++ b/tests/test_cli/test.sh @@ -15,7 +15,6 @@ function testExample() { echo "Example $N" $APP &> /dev/null & - # $APP &> ./app.out & sleep 2 abci-cli --verbose batch < "$INPUT" > "${INPUT}.out.new" killall "$APP" From 7aa00e9ddd0ecb7e5dc3f003d61a834795c532d8 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 19 Oct 2017 14:48:07 +0200 Subject: [PATCH 5/9] Fix metalinter errors --- Makefile | 2 +- example/dummy/persistent_dummy.go | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/Makefile b/Makefile index d097ae72..8b621a9a 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,6 @@ metalinter: tools metalinter_test: tools @gometalinter --install gometalinter --vendor --deadline=600s --disable-all \ - --enable=aligncheck \ --enable=deadcode \ --enable=gas \ --enable=goconst \ @@ -71,6 +70,7 @@ metalinter_test: tools --enable=vetshadow \ ./... + # --enable=aligncheck \ <== disabled as not installed #--enable=dupl \ #--enable=errcheck \ #--enable=gocyclo \ diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 94ce85ad..20b68b9a 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -137,16 +137,6 @@ func (app *PersistentDummyApplication) EndBlock(height uint64) (resEndBlock type return types.ResponseEndBlock{Diffs: app.changes} } -//----------------------------------------- -// persist the last block info - -var lastBlockKey = []byte("lastblock") - -type LastBlockInfo struct { - Height uint64 - AppHash []byte -} - //--------------------------------------------- // update validators From 5162ed1b2b4e7c0cea98be442210b43a0b6b94b9 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 19 Oct 2017 15:12:27 +0200 Subject: [PATCH 6/9] Remove gotype from metalinter so it passes (need newer go on circleci) --- Makefile | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 8b621a9a..6c72d063 100644 --- a/Makefile +++ b/Makefile @@ -52,12 +52,12 @@ metalinter: tools metalinter_test: tools @gometalinter --install gometalinter --vendor --deadline=600s --disable-all \ + --enable=maligned \ --enable=deadcode \ --enable=gas \ --enable=goconst \ --enable=goimports \ --enable=gosimple \ - --enable=gotype \ --enable=ineffassign \ --enable=megacheck \ --enable=misspell \ @@ -70,13 +70,13 @@ metalinter_test: tools --enable=vetshadow \ ./... - # --enable=aligncheck \ <== disabled as not installed - #--enable=dupl \ - #--enable=errcheck \ - #--enable=gocyclo \ - #--enable=golint \ <== comments on anything exported - #--enable=interfacer \ - #--enable=unparam \ - #--enable=vet \ + #--enable=dupl \ + #--enable=errcheck \ + #--enable=gocyclo \ + #--enable=golint \ <== comments on anything exported + #--enable=gotype \ + #--enable=interfacer \ + #--enable=unparam \ + #--enable=vet \ .PHONY: all build test fmt get_deps tools From a4443ddb0c29227c619c03c660acc4b4bdf2ec38 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 23 Oct 2017 00:06:50 -0400 Subject: [PATCH 7/9] update persistent dummy for versioned iavl --- example/dummy/dummy_test.go | 12 +++++++++--- example/dummy/persistent_dummy.go | 28 +++++++++------------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 41e033bc..fbc095e6 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -81,6 +81,8 @@ func TestPersistentDummyInfo(t *testing.T) { dummy := NewPersistentDummyApplication(dir) height := uint64(0) + dummy.InitChain(types.RequestInitChain{[]*types.Validator{randVal(0)}}) + resInfo := dummy.Info(types.RequestInfo{}) if resInfo.LastBlockHeight != height { t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) @@ -103,6 +105,12 @@ func TestPersistentDummyInfo(t *testing.T) { } +func randVal(i int) *types.Validator { + pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(cmn.Fmt("test%d", i))).PubKey().Bytes() + power := cmn.RandInt() + return &types.Validator{pubkey, uint64(power)} +} + // add a validator, remove a validator, update a validator func TestValSetChanges(t *testing.T) { dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO @@ -116,9 +124,7 @@ func TestValSetChanges(t *testing.T) { nInit := 5 vals := make([]*types.Validator, total) for i := 0; i < total; i++ { - pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(cmn.Fmt("test%d", i))).PubKey().Bytes() - power := cmn.RandInt() - vals[i] = &types.Validator{pubkey, uint64(power)} + vals[i] = randVal(i) } // iniitalize with the first nInit dummy.InitChain(types.RequestInitChain{vals[:nInit]}) diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 20b68b9a..de4aaa56 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -23,11 +23,6 @@ const ( type PersistentDummyApplication struct { app *DummyApplication - // latest received - // TODO: move to merkle tree? - blockHeader *types.Header - height uint64 - // validator set changes []*types.Validator @@ -61,7 +56,7 @@ func (app *PersistentDummyApplication) SetLogger(l log.Logger) { func (app *PersistentDummyApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { resInfo = app.app.Info(req) - resInfo.LastBlockHeight = app.height + resInfo.LastBlockHeight = app.app.state.LatestVersion() resInfo.LastBlockAppHash = app.app.state.Hash() return resInfo } @@ -88,24 +83,21 @@ func (app *PersistentDummyApplication) CheckTx(tx []byte) types.Result { return app.app.CheckTx(tx) } +// Commit will panic if InitChain was not called func (app *PersistentDummyApplication) Commit() types.Result { - h := app.blockHeader.Height - // Save a new version + // Save a new version for next height + height := app.app.state.LatestVersion() + 1 var appHash []byte var err error - if app.app.state.Size() > 0 { - appHash, err = app.app.state.SaveVersion(h) - if err != nil { - // if this wasn't a dummy app, we'd do something smarter - panic(err) - } - app.logger.Info("Saved state", "root", appHash) + appHash, err = app.app.state.SaveVersion(height) + if err != nil { + // if this wasn't a dummy app, we'd do something smarter + panic(err) } - app.height = h - app.logger.Info("Commit block", "height", h, "root", appHash) + app.logger.Info("Commit block", "height", height, "root", appHash) return types.NewResultOK(appHash, "") } @@ -125,8 +117,6 @@ func (app *PersistentDummyApplication) InitChain(params types.RequestInitChain) // Track the block hash and header information func (app *PersistentDummyApplication) BeginBlock(params types.RequestBeginBlock) { - // update latest block info - app.blockHeader = params.Header // reset valset changes app.changes = make([]*types.Validator, 0) From e7ebf62092705e144a05882f7622622153333848 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 14:08:36 +0200 Subject: [PATCH 8/9] Remove empty check after iavl fixup --- example/dummy/persistent_dummy.go | 9 +-------- glide.lock | 8 ++++---- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index de4aaa56..15fe150d 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -3,7 +3,6 @@ package dummy import ( "bytes" "encoding/hex" - "path" "strconv" "strings" @@ -31,18 +30,13 @@ type PersistentDummyApplication struct { func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { name := "dummy" - dbPath := path.Join(dbDir, name+".db") - empty, _ := cmn.IsDirEmpty(dbPath) - db, err := dbm.NewGoLevelDB(name, dbDir) if err != nil { panic(err) } stateTree := iavl.NewVersionedTree(500, db) - if !empty { - stateTree.Load() - } + stateTree.Load() return &PersistentDummyApplication{ app: &DummyApplication{state: stateTree}, @@ -117,7 +111,6 @@ func (app *PersistentDummyApplication) InitChain(params types.RequestInitChain) // Track the block hash and header information func (app *PersistentDummyApplication) BeginBlock(params types.RequestBeginBlock) { - // reset valset changes app.changes = make([]*types.Validator, 0) } diff --git a/glide.lock b/glide.lock index d2dfc9a6..cc94dbd5 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 876bc65024f66612325ebafcedeb3e4d5014d46b339cf7583f1c00c6bac6e32c -updated: 2017-10-18T11:59:44.724549502+02:00 +updated: 2017-10-23T14:04:02.596189966+02:00 imports: - name: github.com/btcsuite/btcd version: b8df516b4b267acf2de46be593a9d948d1d2c420 @@ -63,7 +63,7 @@ imports: subpackages: - data - name: github.com/tendermint/iavl - version: ff4ffa531df48509d51f0c16c2432f986eed9fcc + version: 721710e7aa59f61dbfbf558943a207ba3fe6b926 - name: github.com/tendermint/tmlibs version: 8e5266a9ef2527e68a1571f932db8228a331b556 subpackages: @@ -73,7 +73,7 @@ imports: - merkle - process - name: github.com/urfave/cli - version: d70f47eeca3afd795160003bc6e28b001d60c67c + version: 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c - name: golang.org/x/crypto version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e subpackages: @@ -121,7 +121,7 @@ imports: - tap - transport - name: gopkg.in/go-playground/validator.v9 - version: d529ee1b0f30352444f507cc6cdac96bfd12decc + version: 6d8c18553ea1ac493d049edd6f102f52e618f085 testImports: - name: github.com/davecgh/go-spew version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 From 446e50ca9ee8ed3fbea9e5418282acf8b5842dbf Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 14:20:15 +0200 Subject: [PATCH 9/9] Moved RandVal into test helper functions, as needed in other repos for testing --- example/dummy/dummy_test.go | 15 ++------------- example/dummy/helpers.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 13 deletions(-) create mode 100644 example/dummy/helpers.go diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index fbc095e6..751a2e91 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -10,7 +10,6 @@ import ( abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - crypto "github.com/tendermint/go-crypto" "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" @@ -79,10 +78,9 @@ func TestPersistentDummyInfo(t *testing.T) { t.Fatal(err) } dummy := NewPersistentDummyApplication(dir) + InitDummy(dummy) height := uint64(0) - dummy.InitChain(types.RequestInitChain{[]*types.Validator{randVal(0)}}) - resInfo := dummy.Info(types.RequestInfo{}) if resInfo.LastBlockHeight != height { t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) @@ -105,12 +103,6 @@ func TestPersistentDummyInfo(t *testing.T) { } -func randVal(i int) *types.Validator { - pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(cmn.Fmt("test%d", i))).PubKey().Bytes() - power := cmn.RandInt() - return &types.Validator{pubkey, uint64(power)} -} - // add a validator, remove a validator, update a validator func TestValSetChanges(t *testing.T) { dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO @@ -122,10 +114,7 @@ func TestValSetChanges(t *testing.T) { // init with some validators total := 10 nInit := 5 - vals := make([]*types.Validator, total) - for i := 0; i < total; i++ { - vals[i] = randVal(i) - } + vals := RandVals(total) // iniitalize with the first nInit dummy.InitChain(types.RequestInitChain{vals[:nInit]}) diff --git a/example/dummy/helpers.go b/example/dummy/helpers.go new file mode 100644 index 00000000..55c464de --- /dev/null +++ b/example/dummy/helpers.go @@ -0,0 +1,34 @@ +package dummy + +import ( + "github.com/tendermint/abci/types" + crypto "github.com/tendermint/go-crypto" + cmn "github.com/tendermint/tmlibs/common" +) + +// RandVal creates one random validator, with a key derived +// from the input value +func RandVal(i int) *types.Validator { + pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(cmn.Fmt("test%d", i))).PubKey().Bytes() + power := cmn.RandUint16() + 1 + return &types.Validator{pubkey, uint64(power)} +} + +// RandVals returns a list of cnt validators for initializing +// the application. Note that the keys are deterministically +// derived from the index in the array, while the power is +// random (Change this if not desired) +func RandVals(cnt int) []*types.Validator { + res := make([]*types.Validator, cnt) + for i := 0; i < cnt; i++ { + res[i] = RandVal(i) + } + return res +} + +// InitDummy initializes the dummy app with some data, +// which allows tests to pass and is fine as long as you +// don't make any tx that modify the validator state +func InitDummy(app *PersistentDummyApplication) { + app.InitChain(types.RequestInitChain{RandVals(1)}) +}