From 422e67b382bee923ceb8048db639754a26bee184 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Oct 2017 14:32:22 +0200 Subject: [PATCH 01/15] Update deps: tendermint/abci/iavl, fix code --- client/commands/query/get.go | 4 ++- client/query.go | 2 +- glide.lock | 53 +++++++++++++++++------------------- glide.yaml | 6 ++-- modules/ibc/test_helpers.go | 6 ++-- state/bonsai.go | 2 +- 6 files changed, 36 insertions(+), 37 deletions(-) diff --git a/client/commands/query/get.go b/client/commands/query/get.go index 01740b63af..08bbc45ed6 100644 --- a/client/commands/query/get.go +++ b/client/commands/query/get.go @@ -12,6 +12,7 @@ import ( "github.com/tendermint/go-wire/data" "github.com/tendermint/iavl" "github.com/tendermint/light-client/proofs" + rpcclient "github.com/tendermint/tendermint/rpc/client" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/commands" @@ -47,7 +48,8 @@ func GetParsed(key []byte, data interface{}, prove bool) (uint64, error) { func Get(key []byte, prove bool) (data.Bytes, uint64, error) { if !prove { node := commands.GetNode() - resp, err := node.ABCIQuery("/key", key, false) + resp, err := node.ABCIQueryWithOptions("/key", key, + rpcclient.ABCIQueryOptions{Trusted: true}) return data.Bytes(resp.Value), resp.Height, err } val, h, _, err := GetWithProof(key) diff --git a/client/query.go b/client/query.go index a4f4ff1ea0..70184bea63 100644 --- a/client/query.go +++ b/client/query.go @@ -20,7 +20,7 @@ import ( func GetWithProof(key []byte, node client.Client, cert certifiers.Certifier) ( val data.Bytes, height uint64, proof iavl.KeyProof, err error) { - resp, err := node.ABCIQuery("/key", key, true) + resp, err := node.ABCIQuery("/key", key) if err != nil { return } diff --git a/glide.lock b/glide.lock index ad7e4e7c69..54c597f601 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 738b6ed5402dee4f77a7063db84011a2ef776cda203a9c843a9830c9d0458a89 -updated: 2017-10-11T17:06:42.651532377-04:00 +hash: fa04e2d0e8764d44c0f8e3400d7d12118b0f05aac6c12e5ff0d3dd1940c03100 +updated: 2017-10-18T13:44:50.561421607+02:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -11,10 +11,6 @@ imports: version: 637e656429416087660c84436a2a035d69d54e2e - name: github.com/BurntSushi/toml version: a368813c5e648fee92e5f6c30e3944ff9d5e8895 -- name: github.com/davecgh/go-spew - version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 - subpackages: - - spew - name: github.com/ebuchman/fail-test version: 95f809107225be108efcf10a3509e4ea6ceef3c4 - name: github.com/fsnotify/fsnotify @@ -79,10 +75,6 @@ imports: version: 13d49d4606eb801b8f01ae542b4afc4c6ee3d84a - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d -- name: github.com/pmezard/go-difflib - version: d8ed2627bdf02c080bf22230dbb337003b7aba2d - subpackages: - - difflib - name: github.com/rcrowley/go-metrics version: 1f30fe9094a513ce4c700b9a54458bbb0c96996c - name: github.com/spf13/afero @@ -99,11 +91,6 @@ imports: version: e57e3eeb33f795204c1ca35f56c44f83227c6e66 - name: github.com/spf13/viper version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2 -- name: github.com/stretchr/testify - version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 - subpackages: - - assert - - require - name: github.com/syndtr/goleveldb version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 subpackages: @@ -120,7 +107,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: 15cd7fb1e3b75c436b6dee89a44db35f3d265bd0 + version: 3c16b313dd2342bb576844ade3acca3010928908 subpackages: - client - example/dummy @@ -132,8 +119,9 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-crypto - version: 0418d32276d7d0f080e4c0e58b49c6ba2f717954 + version: 8e7f0e7701f92206679ad093d013b9b162427631 subpackages: + - bcrypt - keys - keys/cryptostore - keys/storage/filestorage @@ -145,20 +133,16 @@ imports: - data - data/base58 - name: github.com/tendermint/iavl - version: 9233811d241ac8d4441a7223a4e79b83931dfae0 + version: ff4ffa531df48509d51f0c16c2432f986eed9fcc - name: github.com/tendermint/light-client - version: ac2e4bf47b31aaf5d3d336691ac786ec751bfc32 + version: 79125bb4dfe173fe8a7208327ac4ec4c73d1a8a7 subpackages: - certifiers - certifiers/client - certifiers/files - proofs -- name: github.com/tendermint/merkleeyes - version: 2f6e5d31e7a35045d8d0a5895cb1fec33dd4d32b - subpackages: - - iavl - name: github.com/tendermint/tendermint - version: d4634dc6832a7168c2536e7c71bfba4a8ca857be + version: b234f7aba2e6c39f0023be8712be23f7a78e1b11 subpackages: - blockchain - cmd/tendermint/commands @@ -186,7 +170,7 @@ imports: - types - version - name: github.com/tendermint/tmlibs - version: 7166252a521951eb8b6bd26db28b2b90586941a9 + version: 8e5266a9ef2527e68a1571f932db8228a331b556 subpackages: - autofile - cli @@ -199,10 +183,10 @@ imports: - log - logger - merkle - - test - name: golang.org/x/crypto version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e subpackages: + - blowfish - curve25519 - nacl/box - nacl/secretbox @@ -253,7 +237,20 @@ imports: - tap - transport - name: gopkg.in/go-playground/validator.v9 - version: 6d8c18553ea1ac493d049edd6f102f52e618f085 + version: d529ee1b0f30352444f507cc6cdac96bfd12decc - name: gopkg.in/yaml.v2 version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b -testImports: [] +testImports: +- name: github.com/davecgh/go-spew + version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 + subpackages: + - spew +- name: github.com/pmezard/go-difflib + version: d8ed2627bdf02c080bf22230dbb337003b7aba2d + subpackages: + - difflib +- name: github.com/stretchr/testify + version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 + subpackages: + - assert + - require diff --git a/glide.yaml b/glide.yaml index ebf2ebc0dc..03ad9bf18f 100644 --- a/glide.yaml +++ b/glide.yaml @@ -7,7 +7,7 @@ import: - package: github.com/spf13/pflag - package: github.com/spf13/viper - package: github.com/tendermint/abci - version: develop + version: feature/merkleeyes-to-iavl subpackages: - server - types @@ -20,7 +20,7 @@ import: subpackages: - data - package: github.com/tendermint/light-client - version: develop + version: feature/merkleeyes-to-iavl subpackages: - proofs - certifiers @@ -29,7 +29,7 @@ import: - package: github.com/tendermint/iavl version: develop - package: github.com/tendermint/tendermint - version: 0.11.1 + version: develop subpackages: - config - node diff --git a/modules/ibc/test_helpers.go b/modules/ibc/test_helpers.go index d29ea72690..7219ecc544 100644 --- a/modules/ibc/test_helpers.go +++ b/modules/ibc/test_helpers.go @@ -18,7 +18,7 @@ import ( type MockChain struct { keys certifiers.ValKeys chainID string - tree *iavl.IAVLTree + tree *iavl.Tree } // NewMockChain initializes a teststore and test validators @@ -26,7 +26,7 @@ func NewMockChain(chainID string, numKeys int) MockChain { return MockChain{ keys: certifiers.GenValKeys(numKeys), chainID: chainID, - tree: iavl.NewIAVLTree(0, nil), + tree: iavl.NewTree(0, nil), } } @@ -56,7 +56,7 @@ func genEmptySeed(keys certifiers.ValKeys, chain string, h int, return certifiers.Seed{cp, vals} } -func makePostPacket(tree *iavl.IAVLTree, packet Packet, fromID string, fromHeight int) PostPacketTx { +func makePostPacket(tree *iavl.Tree, packet Packet, fromID string, fromHeight int) PostPacketTx { key := []byte(fmt.Sprintf("some-long-prefix-%06d", packet.Sequence)) tree.Set(key, packet.Bytes()) _, proof, err := tree.GetWithProof(key) diff --git a/state/bonsai.go b/state/bonsai.go index b816c876fa..2ab75b2df8 100644 --- a/state/bonsai.go +++ b/state/bonsai.go @@ -31,7 +31,7 @@ func NewBonsai(tree *iavl.VersionedTree) *Bonsai { // Get matches the signature of KVStore func (b *Bonsai) Get(key []byte) []byte { - _, value, _ := b.Tree.Get(key) + _, value := b.Tree.Get(key) return value } From 3b7020520caa7a895425a054cda5149c80920657 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Oct 2017 15:21:25 +0200 Subject: [PATCH 02/15] Clean up store versions after a limit --- app/store.go | 11 +++++++---- state/merkle.go | 22 +++++++++++++++------- state/merkle_test.go | 2 +- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/app/store.go b/app/store.go index 2ad14915ab..a19aa968c9 100644 --- a/app/store.go +++ b/app/store.go @@ -17,6 +17,9 @@ import ( sm "github.com/cosmos/cosmos-sdk/state" ) +// DefaultHistorySize is how many blocks of history to store for ABCI queries +const DefaultHistorySize = 10 + // StoreApp contains a data store and all info needed // to perform queries and handshakes. // @@ -41,7 +44,7 @@ type StoreApp struct { // NewStoreApp creates a data store to handle queries func NewStoreApp(appName, dbName string, cacheSize int, logger log.Logger) (*StoreApp, error) { - state, err := loadState(dbName, cacheSize) + state, err := loadState(dbName, cacheSize, DefaultHistorySize) if err != nil { return nil, err } @@ -234,11 +237,11 @@ func pubKeyIndex(val *abci.Validator, list []*abci.Validator) int { return -1 } -func loadState(dbName string, cacheSize int) (*sm.State, error) { +func loadState(dbName string, cacheSize int, historySize uint64) (*sm.State, error) { // memory backed case, just for testing if dbName == "" { tree := iavl.NewVersionedTree(0, dbm.NewMemDB()) - return sm.NewState(tree), nil + return sm.NewState(tree, historySize), nil } // Expand the path fully @@ -267,5 +270,5 @@ func loadState(dbName string, cacheSize int) (*sm.State, error) { } } - return sm.NewState(tree), nil + return sm.NewState(tree, historySize), nil } diff --git a/state/merkle.go b/state/merkle.go index 2373d27d3b..b301438305 100644 --- a/state/merkle.go +++ b/state/merkle.go @@ -5,17 +5,19 @@ import "github.com/tendermint/iavl" // State represents the app states, separating the commited state (for queries) // from the working state (for CheckTx and AppendTx) type State struct { - committed *Bonsai - deliverTx SimpleDB - checkTx SimpleDB + committed *Bonsai + deliverTx SimpleDB + checkTx SimpleDB + historySize uint64 } -func NewState(tree *iavl.VersionedTree) *State { +func NewState(tree *iavl.VersionedTree, historySize uint64) *State { base := NewBonsai(tree) return &State{ - committed: base, - deliverTx: base.Checkpoint(), - checkTx: base.Checkpoint(), + committed: base, + deliverTx: base.Checkpoint(), + checkTx: base.Checkpoint(), + historySize: historySize, } } @@ -51,6 +53,7 @@ func (s *State) Commit(version uint64) ([]byte, error) { return nil, err } + // store a new version var hash []byte if s.committed.Tree.Size() > 0 || s.committed.Tree.LatestVersion() > 0 { hash, err = s.committed.Tree.SaveVersion(version) @@ -59,6 +62,11 @@ func (s *State) Commit(version uint64) ([]byte, error) { } } + // release an old version + if version > s.historySize { + s.committed.Tree.DeleteVersion(version - s.historySize) + } + s.deliverTx = s.committed.Checkpoint() s.checkTx = s.committed.Checkpoint() return hash, nil diff --git a/state/merkle_test.go b/state/merkle_test.go index 9866195b4e..3e4fdb724b 100644 --- a/state/merkle_test.go +++ b/state/merkle_test.go @@ -66,7 +66,7 @@ func TestStateCommitHash(t *testing.T) { // make the store... tree := iavl.NewVersionedTree(0, db.NewMemDB()) - store := NewState(tree) + store := NewState(tree, 2) for n, r := range tc.rounds { // start the cache From c4ead8b8a373202034260fa78c958656b74540a4 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Oct 2017 18:20:22 +0200 Subject: [PATCH 03/15] Expose height flag in all queries --- app/store.go | 11 ++++++----- client/commands/query/get.go | 18 +++++++++++------- client/commands/query/state.go | 2 +- client/query.go | 11 +++++++++-- client/query_test.go | 12 ++++++++++-- .../counter/cmd/countercli/commands/query.go | 2 +- modules/coin/commands/query.go | 2 +- modules/coin/rest/handlers.go | 17 ++++++++++++++--- modules/eyes/commands/query.go | 2 +- modules/ibc/commands/query.go | 12 ++++++------ modules/nonce/commands/query.go | 2 +- modules/nonce/rest/handlers.go | 14 +++++++++++++- modules/roles/commands/query.go | 2 +- 13 files changed, 75 insertions(+), 32 deletions(-) diff --git a/app/store.go b/app/store.go index a19aa968c9..24b465ee9d 100644 --- a/app/store.go +++ b/app/store.go @@ -146,11 +146,12 @@ func (app *StoreApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQu // we must retrun most recent, even if apphash // is not yet in the blockchain - // if tree.Tree.VersionExists(app.height - 1) { - // height = app.height - 1 - // } else { - height = app.CommittedHeight() - // } + withProof := app.CommittedHeight() - 1 + if tree.Tree.VersionExists(withProof) { + height = withProof + } else { + height = app.CommittedHeight() + } } resQuery.Height = height diff --git a/client/commands/query/get.go b/client/commands/query/get.go index 08bbc45ed6..8e1284c48d 100644 --- a/client/commands/query/get.go +++ b/client/commands/query/get.go @@ -25,8 +25,8 @@ import ( // It will try to get the proof for the given key. If it is successful, // it will return the height and also unserialize proof.Data into the data // argument (so pass in a pointer to the appropriate struct) -func GetParsed(key []byte, data interface{}, prove bool) (uint64, error) { - bs, h, err := Get(key, prove) +func GetParsed(key []byte, data interface{}, height int, prove bool) (uint64, error) { + bs, h, err := Get(key, height, prove) if err != nil { return 0, err } @@ -45,27 +45,31 @@ func GetParsed(key []byte, data interface{}, prove bool) (uint64, error) { // we just repeat whatever any (potentially malicious) node gives us. // Only use that if you are running the full node yourself, // and it is localhost or you have a secure connection (not HTTP) -func Get(key []byte, prove bool) (data.Bytes, uint64, error) { +func Get(key []byte, height int, prove bool) (data.Bytes, uint64, error) { + if height < 0 { + return nil, 0, fmt.Errorf("Height cannot be negative") + } + if !prove { node := commands.GetNode() resp, err := node.ABCIQueryWithOptions("/key", key, - rpcclient.ABCIQueryOptions{Trusted: true}) + rpcclient.ABCIQueryOptions{Trusted: true, Height: uint64(height)}) return data.Bytes(resp.Value), resp.Height, err } - val, h, _, err := GetWithProof(key) + val, h, _, err := GetWithProof(key, height) return val, h, err } // GetWithProof returns the values stored under a given key at the named // height as in Get. Additionally, it will return a validated merkle // proof for the key-value pair if it exists, and all checks pass. -func GetWithProof(key []byte) (data.Bytes, uint64, iavl.KeyProof, error) { +func GetWithProof(key []byte, height int) (data.Bytes, uint64, iavl.KeyProof, error) { node := commands.GetNode() cert, err := commands.GetCertifier() if err != nil { return nil, 0, nil, err } - return client.GetWithProof(key, node, cert) + return client.GetWithProof(key, height, node, cert) } // ParseHexKey parses the key flag as hex and converts to bytes or returns error diff --git a/client/commands/query/state.go b/client/commands/query/state.go index 13dae0ea85..4412d3e100 100644 --- a/client/commands/query/state.go +++ b/client/commands/query/state.go @@ -28,7 +28,7 @@ func keyQueryCmd(cmd *cobra.Command, args []string) error { } prove := !viper.GetBool(commands.FlagTrustNode) - val, h, err := Get(key, prove) + val, h, err := Get(key, GetHeight(), prove) if err != nil { return err } diff --git a/client/query.go b/client/query.go index 70184bea63..c6c0589438 100644 --- a/client/query.go +++ b/client/query.go @@ -17,10 +17,17 @@ import ( // If there is any error in checking, returns an error. // If val is non-empty, proof should be KeyExistsProof // If val is empty, proof should be KeyMissingProof -func GetWithProof(key []byte, node client.Client, cert certifiers.Certifier) ( +func GetWithProof(key []byte, reqHeight int, node client.Client, + cert certifiers.Certifier) ( val data.Bytes, height uint64, proof iavl.KeyProof, err error) { - resp, err := node.ABCIQuery("/key", key) + if reqHeight < 0 { + err = errors.Errorf("Height cannot be negative") + return + } + + resp, err := node.ABCIQueryWithOptions("/key", key, + client.ABCIQueryOptions{Height: uint64(reqHeight)}) if err != nil { return } diff --git a/client/query_test.go b/client/query_test.go index f8031ee838..8faff5599b 100644 --- a/client/query_test.go +++ b/client/query_test.go @@ -56,6 +56,7 @@ func TestAppProofs(t *testing.T) { require.NoError(err, "%+v", err) require.EqualValues(0, br.CheckTx.Code, "%#v", br.CheckTx) require.EqualValues(0, br.DeliverTx.Code) + brh := br.Height // This sets up our trust on the node based on some past point. source := certclient.New(cl) @@ -71,7 +72,14 @@ func TestAppProofs(t *testing.T) { // Test existing key. var data eyes.Data - bs, height, proof, err := GetWithProof(k, cl, cert) + // verify a query before the tx block has no data (and valid non-exist proof) + bs, height, proof, err := GetWithProof(k, brh-1, cl, cert) + require.NotNil(err) + require.True(lc.IsNoDataErr(err)) + require.Nil(bs) + + // but given that block it is good + bs, height, proof, err = GetWithProof(k, brh, cl, cert) require.NoError(err, "%+v", err) require.NotNil(proof) require.True(height >= uint64(latest.Header.Height)) @@ -89,7 +97,7 @@ func TestAppProofs(t *testing.T) { // Test non-existing key. missing := []byte("my-missing-key") - bs, _, proof, err = GetWithProof(missing, cl, cert) + bs, _, proof, err = GetWithProof(missing, 0, cl, cert) require.True(lc.IsNoDataErr(err)) require.Nil(bs) require.NotNil(proof) diff --git a/examples/counter/cmd/countercli/commands/query.go b/examples/counter/cmd/countercli/commands/query.go index d55f6db487..40a42df725 100644 --- a/examples/counter/cmd/countercli/commands/query.go +++ b/examples/counter/cmd/countercli/commands/query.go @@ -23,7 +23,7 @@ func counterQueryCmd(cmd *cobra.Command, args []string) error { prove := !viper.GetBool(commands.FlagTrustNode) key := stack.PrefixedKey(counter.NameCounter, counter.StateKey()) - h, err := query.GetParsed(key, &cp, prove) + h, err := query.GetParsed(key, &cp, query.GetHeight(), prove) if err != nil { return err } diff --git a/modules/coin/commands/query.go b/modules/coin/commands/query.go index ca0cced013..c1e0d9f550 100644 --- a/modules/coin/commands/query.go +++ b/modules/coin/commands/query.go @@ -34,7 +34,7 @@ func accountQueryCmd(cmd *cobra.Command, args []string) error { acc := coin.Account{} prove := !viper.GetBool(commands.FlagTrustNode) - height, err := query.GetParsed(key, &acc, prove) + height, err := query.GetParsed(key, &acc, query.GetHeight(), prove) if lc.IsNoDataErr(err) { return errors.Errorf("Account bytes are empty for address %s ", addr) } else if err != nil { diff --git a/modules/coin/rest/handlers.go b/modules/coin/rest/handlers.go index 49250d5e2e..443cc94080 100644 --- a/modules/coin/rest/handlers.go +++ b/modules/coin/rest/handlers.go @@ -3,6 +3,7 @@ package rest import ( "fmt" "net/http" + "strconv" "strings" "github.com/gorilla/mux" @@ -32,7 +33,7 @@ type SendInput struct { To *sdk.Actor `json:"to"` From *sdk.Actor `json:"from"` - Amount coin.Coins `json:"amount"` + Amount coin.Coins `json:"amount"` } // doQueryAccount is the HTTP handlerfunc to query an account @@ -45,11 +46,22 @@ func doQueryAccount(w http.ResponseWriter, r *http.Request) { common.WriteError(w, err) return } + + var h int + qHeight := args["height"] + if qHeight != "" { + h, err = strconv.Atoi(qHeight) + if err != nil { + common.WriteError(w, err) + return + } + } + actor = coin.ChainAddr(actor) key := stack.PrefixedKey(coin.NameCoin, actor.Bytes()) account := new(coin.Account) prove := !viper.GetBool(commands.FlagTrustNode) - height, err := query.GetParsed(key, account, prove) + height, err := query.GetParsed(key, account, h, prove) if lightclient.IsNoDataErr(err) { err := fmt.Errorf("account bytes are empty for address: %q", signature) common.WriteError(w, err) @@ -152,4 +164,3 @@ func RegisterAll(r *mux.Router) error { } // End of mux.Router registrars - diff --git a/modules/eyes/commands/query.go b/modules/eyes/commands/query.go index 6e71e88c6b..aa6865d923 100644 --- a/modules/eyes/commands/query.go +++ b/modules/eyes/commands/query.go @@ -35,7 +35,7 @@ func eyesQueryCmd(cmd *cobra.Command, args []string) error { key = stack.PrefixedKey(eyes.Name, key) prove := !viper.GetBool(commands.FlagTrustNode) - height, err := query.GetParsed(key, &res, prove) + height, err := query.GetParsed(key, &res, query.GetHeight(), prove) if err != nil { return err } diff --git a/modules/ibc/commands/query.go b/modules/ibc/commands/query.go index e4fec6953f..fb1da65067 100644 --- a/modules/ibc/commands/query.go +++ b/modules/ibc/commands/query.go @@ -87,7 +87,7 @@ func ibcQueryCmd(cmd *cobra.Command, args []string) error { var res ibc.HandlerInfo key := stack.PrefixedKey(ibc.NameIBC, ibc.HandlerKey()) prove := !viper.GetBool(commands.FlagTrustNode) - h, err := query.GetParsed(key, &res, prove) + h, err := query.GetParsed(key, &res, query.GetHeight(), prove) if err != nil { return err } @@ -98,7 +98,7 @@ func chainsQueryCmd(cmd *cobra.Command, args []string) error { list := [][]byte{} key := stack.PrefixedKey(ibc.NameIBC, ibc.ChainsKey()) prove := !viper.GetBool(commands.FlagTrustNode) - h, err := query.GetParsed(key, &list, prove) + h, err := query.GetParsed(key, &list, query.GetHeight(), prove) if err != nil { return err } @@ -121,7 +121,7 @@ func chainQueryCmd(cmd *cobra.Command, args []string) error { var res ibc.ChainInfo key := stack.PrefixedKey(ibc.NameIBC, ibc.ChainKey(arg)) prove := !viper.GetBool(commands.FlagTrustNode) - h, err := query.GetParsed(key, &res, prove) + h, err := query.GetParsed(key, &res, query.GetHeight(), prove) if err != nil { return err } @@ -158,7 +158,7 @@ func packetsQueryCmd(cmd *cobra.Command, args []string) error { var res uint64 prove := !viper.GetBool(commands.FlagTrustNode) - h, err := query.GetParsed(key, &res, prove) + h, err := query.GetParsed(key, &res, query.GetHeight(), prove) if err != nil { return err } @@ -190,7 +190,7 @@ func packetQueryCmd(cmd *cobra.Command, args []string) error { // Input queue just display the results var packet ibc.Packet if from != "" { - h, err := query.GetParsed(key, &packet, prove) + h, err := query.GetParsed(key, &packet, query.GetHeight(), prove) if err != nil { return err } @@ -198,7 +198,7 @@ func packetQueryCmd(cmd *cobra.Command, args []string) error { } // output queue, create a post packet - bs, height, proof, err := query.GetWithProof(key) + bs, height, proof, err := query.GetWithProof(key, query.GetHeight()) if err != nil { return err } diff --git a/modules/nonce/commands/query.go b/modules/nonce/commands/query.go index e4652638ea..860f7b3aac 100644 --- a/modules/nonce/commands/query.go +++ b/modules/nonce/commands/query.go @@ -45,7 +45,7 @@ func nonceQueryCmd(cmd *cobra.Command, args []string) error { func doNonceQuery(signers []sdk.Actor) (sequence uint32, height uint64, err error) { key := stack.PrefixedKey(nonce.NameNonce, nonce.GetSeqKey(signers)) prove := !viper.GetBool(commands.FlagTrustNode) - height, err = query.GetParsed(key, &sequence, prove) + height, err = query.GetParsed(key, &sequence, query.GetHeight(), prove) if lc.IsNoDataErr(err) { // no data, return sequence 0 return 0, 0, nil diff --git a/modules/nonce/rest/handlers.go b/modules/nonce/rest/handlers.go index b27e7512fd..3a3077616e 100644 --- a/modules/nonce/rest/handlers.go +++ b/modules/nonce/rest/handlers.go @@ -3,6 +3,7 @@ package rest import ( "fmt" "net/http" + "strconv" "github.com/gorilla/mux" "github.com/spf13/viper" @@ -28,6 +29,17 @@ func doQueryNonce(w http.ResponseWriter, r *http.Request) { common.WriteError(w, err) return } + + var h int + qHeight := args["height"] + if qHeight != "" { + h, err = strconv.Atoi(qHeight) + if err != nil { + common.WriteError(w, err) + return + } + } + actor = coin.ChainAddr(actor) key := nonce.GetSeqKey([]sdk.Actor{actor}) key = stack.PrefixedKey(nonce.NameNonce, key) @@ -35,7 +47,7 @@ func doQueryNonce(w http.ResponseWriter, r *http.Request) { prove := !viper.GetBool(commands.FlagTrustNode) // query sequence number - data, height, err := query.Get(key, prove) + data, height, err := query.Get(key, h, prove) if lightclient.IsNoDataErr(err) { err = fmt.Errorf("nonce empty for address: %q", signature) common.WriteError(w, err) diff --git a/modules/roles/commands/query.go b/modules/roles/commands/query.go index fb2b077cf8..5fbc22405d 100644 --- a/modules/roles/commands/query.go +++ b/modules/roles/commands/query.go @@ -30,7 +30,7 @@ func roleQueryCmd(cmd *cobra.Command, args []string) error { var res roles.Role key := stack.PrefixedKey(roles.NameRole, role) prove := !viper.GetBool(commands.FlagTrustNode) - height, err := query.GetParsed(key, &res, prove) + height, err := query.GetParsed(key, &res, query.GetHeight(), prove) if err != nil { return err } From 5714b101b58c9b8bdc04a479460cbef20bf420c0 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Oct 2017 18:32:07 +0200 Subject: [PATCH 04/15] Handle explicit heights to query tx in basictx.sh --- examples/basecoin/tests/cli/basictx.sh | 22 +++++++++++----------- tests/cli/common.sh | 8 ++++++-- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/examples/basecoin/tests/cli/basictx.sh b/examples/basecoin/tests/cli/basictx.sh index 2ae46fce17..853aab4b48 100755 --- a/examples/basecoin/tests/cli/basictx.sh +++ b/examples/basecoin/tests/cli/basictx.sh @@ -40,10 +40,10 @@ test01SendTx() { HASH=$(echo $TX | jq .hash | tr -d \") TX_HEIGHT=$(echo $TX | jq .height) - checkAccount $SENDER "9007199254740000" + checkAccount $SENDER "9007199254740000" "$TX_HEIGHT" # make sure 0x prefix also works - checkAccount "0x$SENDER" "9007199254740000" - checkAccount $RECV "992" + checkAccount "0x$SENDER" "9007199254740000" "$TX_HEIGHT" + checkAccount $RECV "992" "$TX_HEIGHT" # Make sure tx is indexed checkSendTx $HASH $TX_HEIGHT $SENDER "992" @@ -60,8 +60,8 @@ test02SendTxWithFee() { TX_HEIGHT=$(echo $TX | jq .height) # deduct 100 from sender, add 90 to receiver... fees "vanish" - checkAccount $SENDER "9007199254739900" - checkAccount $RECV "1082" + checkAccount $SENDER "9007199254739900" "$TX_HEIGHT" + checkAccount $RECV "1082" "$TX_HEIGHT" # Make sure tx is indexed checkSendFeeTx $HASH $TX_HEIGHT $SENDER "90" "10" @@ -71,8 +71,8 @@ test02SendTxWithFee() { assertFalse "line=${LINENO}, replay: $TX" $? # checking normally - checkAccount $SENDER "9007199254739900" - checkAccount $RECV "1082" + checkAccount $SENDER "9007199254739900" "$TX_HEIGHT" + checkAccount $RECV "1082" "$TX_HEIGHT" # make sure we can query the proper nonce NONCE=$(${CLIENT_EXE} query nonce $SENDER) @@ -89,8 +89,8 @@ test02SendTxWithFee() { export BC_TRUST_NODE=1 export BC_NODE=localhost:46657 checkSendFeeTx $HASH $TX_HEIGHT $SENDER "90" "10" - checkAccount $SENDER "9007199254739900" - checkAccount $RECV "1082" + checkAccount $SENDER "9007199254739900" "$TX_HEIGHT" + checkAccount $RECV "1082" "$TX_HEIGHT" unset BC_TRUST_NODE unset BC_NODE export BC_HOME=$OLD_BC_HOME @@ -109,8 +109,8 @@ test03CreditTx() { TX_HEIGHT=$(echo $TX | jq .height) # receiver got cash, sender didn't lose any (1000 more than last check) - checkAccount $RECV "2082" - checkAccount $SENDER "9007199254739900" + checkAccount $RECV "2082" "$TX_HEIGHT" + checkAccount $SENDER "9007199254739900" "$TX_HEIGHT" } diff --git a/tests/cli/common.sh b/tests/cli/common.sh index b7a4ea9834..2b6b3679e3 100644 --- a/tests/cli/common.sh +++ b/tests/cli/common.sh @@ -124,11 +124,15 @@ getAddr() { echo $RAW | cut -d' ' -f2 } -# XXX Ex Usage: checkAccount $ADDR $AMOUNT +# XXX Ex Usage: checkAccount $ADDR $AMOUNT [$HEIGHT] # Desc: Assumes just one coin, checks the balance of first coin in any case +# pass optional height to query which block to query checkAccount() { + # default height of 0, but accept an argument + HEIGHT=${3:-0} + # make sure sender goes down - ACCT=$(${CLIENT_EXE} query account $1) + ACCT=$(${CLIENT_EXE} query account $1 --height=$HEIGHT) if ! assertTrue "line=${LINENO}, account must exist" $?; then return 1 fi From ff0a50a1b3fa56d089f9d751cb9a956a2b80c78b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Oct 2017 18:51:03 +0200 Subject: [PATCH 05/15] Fix cli tests to explicitly pass height when querying results of tx --- examples/basecoin/tests/cli/ibc.sh | 6 +++--- examples/basecoin/tests/cli/rest.sh | 8 ++++---- examples/basecoin/tests/cli/restart.sh | 4 ++-- examples/basecoin/tests/cli/roles.sh | 11 +++++----- examples/counter/tests/cli/counter.sh | 28 ++++++++++++++++---------- examples/eyes/tests/cli/eyes.sh | 2 +- tests/cli/common.sh | 7 +++++-- 7 files changed, 38 insertions(+), 28 deletions(-) diff --git a/examples/basecoin/tests/cli/ibc.sh b/examples/basecoin/tests/cli/ibc.sh index 45ab13b273..b43d5793c1 100755 --- a/examples/basecoin/tests/cli/ibc.sh +++ b/examples/basecoin/tests/cli/ibc.sh @@ -184,7 +184,7 @@ test04SendIBCPacket() { TX_HEIGHT=$(echo $TX | jq .height) # Make sure balance went down and tx is indexed - checkAccount $SENDER "9007199254720990" + checkAccount $SENDER "9007199254720990" "$TX_HEIGHT" checkSendTx $HASH $TX_HEIGHT $SENDER "20002" # look, we wrote a packet @@ -211,7 +211,7 @@ test05ReceiveIBCPacket() { # make some credit, so we can accept the packet TX=$(echo qwertyuiop | ${CLIENT_EXE} tx credit --amount=60006mycoin --to=$CHAIN_ID_1:: --name=$RICH) txSucceeded $? "$TX" "${CHAIN_ID_1}::" - checkAccount $CHAIN_ID_1:: "60006" + checkAccount $CHAIN_ID_1:: "60006" "$TX_HEIGHT" # now, we try to post it.... (this is PACKET from last test) @@ -279,7 +279,7 @@ assertNewHeight() { # TX_HEIGHT=$(echo $TX | jq .height) # # Make sure balance went down and tx is indexed -# checkAccount $SENDER "1" "9007199254720990" +# checkAccount $SENDER "1" "9007199254720990" "$TX_HEIGHT" # checkSendTx $HASH $TX_HEIGHT $SENDER "20002" # # Make sure nothing arrived - yet diff --git a/examples/basecoin/tests/cli/rest.sh b/examples/basecoin/tests/cli/rest.sh index 2d2c86de6a..e840cbb91c 100755 --- a/examples/basecoin/tests/cli/rest.sh +++ b/examples/basecoin/tests/cli/rest.sh @@ -126,8 +126,8 @@ test04CreateRoleInvalid() { # TX_HEIGHT=$(echo $TX | jq .height) # # deduct 100 from sender, add 90 to receiver... fees "vanish" -# checkAccount $SENDER "9007199254739900" -# checkAccount $RECV "1082" +# checkAccount $SENDER "9007199254739900" "$TX_HEIGHT" +# checkAccount $RECV "1082" "$TX_HEIGHT" # # Make sure tx is indexed # checkSendFeeTx $HASH $TX_HEIGHT $SENDER "90" "10" @@ -135,8 +135,8 @@ test04CreateRoleInvalid() { # # assert replay protection # TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=90mycoin --fee=10mycoin --sequence=2 --to=$RECV --name=$RICH 2>/dev/null) # assertFalse "line=${LINENO}, replay: $TX" $? -# checkAccount $SENDER "9007199254739900" -# checkAccount $RECV "1082" +# checkAccount $SENDER "9007199254739900" "$TX_HEIGHT" +# checkAccount $RECV "1082" "$TX_HEIGHT" # # make sure we can query the proper nonce # NONCE=$(${CLIENT_EXE} query nonce $SENDER) diff --git a/examples/basecoin/tests/cli/restart.sh b/examples/basecoin/tests/cli/restart.sh index c091b32e7f..1d85f94ccc 100755 --- a/examples/basecoin/tests/cli/restart.sh +++ b/examples/basecoin/tests/cli/restart.sh @@ -26,8 +26,8 @@ test00PreRestart() { HASH=$(echo $TX | jq .hash | tr -d \") TX_HEIGHT=$(echo $TX | jq .height) - checkAccount $SENDER "9007199254740000" - checkAccount $RECV "992" + checkAccount $SENDER "9007199254740000" "$TX_HEIGHT" + checkAccount $RECV "992" "$TX_HEIGHT" # make sure tx is indexed checkSendTx $HASH $TX_HEIGHT $SENDER "992" diff --git a/examples/basecoin/tests/cli/roles.sh b/examples/basecoin/tests/cli/roles.sh index 1dece90ec9..77d5f169d1 100755 --- a/examples/basecoin/tests/cli/roles.sh +++ b/examples/basecoin/tests/cli/roles.sh @@ -35,7 +35,7 @@ test01SetupRole() { HASH=$(echo $TX | jq .hash | tr -d \") TX_HEIGHT=$(echo $TX | jq .height) - checkRole "${ROLE}" $SIGS 3 + checkRole "${ROLE}" $SIGS 3 "$TX_HEIGHT" # Make sure tx is indexed checkRoleTx $HASH $TX_HEIGHT "${ROLE}" 3 @@ -51,8 +51,8 @@ test02SendTxToRole() { TX_HEIGHT=$(echo $TX | jq .height) # reduce by 10090 - checkAccount $SENDER "9007199254730902" - checkAccount $RECV "10000" + checkAccount $SENDER "9007199254730902" "$TX_HEIGHT" + checkAccount $RECV "10000" "$TX_HEIGHT" checkSendFeeTx $HASH $TX_HEIGHT $SENDER "10000" "90" } @@ -82,9 +82,10 @@ test03SendMultiFromRole() { # and get some dude to sign it for the full access TX=$(echo qwertyuiop | ${CLIENT_EXE} tx --in=$TX_FILE --name=$DUDE) txSucceeded $? "$TX" "multi-bank" + TX_HEIGHT=$(echo $TX | jq .height) - checkAccount $TWO "6000" - checkAccount $BANK "4000" + checkAccount $TWO "6000" "$TX_HEIGHT" + checkAccount $BANK "4000" "$TX_HEIGHT" } diff --git a/examples/counter/tests/cli/counter.sh b/examples/counter/tests/cli/counter.sh index 53eebbe12f..f1c9a4c05d 100755 --- a/examples/counter/tests/cli/counter.sh +++ b/examples/counter/tests/cli/counter.sh @@ -41,8 +41,8 @@ test01SendTx() { HASH=$(echo $TX | jq .hash | tr -d \") TX_HEIGHT=$(echo $TX | jq .height) - checkAccount $SENDER "9007199254740000" - checkAccount $RECV "992" + checkAccount $SENDER "9007199254740000" "$TX_HEIGHT" + checkAccount $RECV "992" "$TX_HEIGHT" # make sure tx is indexed checkSendTx $HASH $TX_HEIGHT $SENDER "992" @@ -53,11 +53,15 @@ test02GetCounter() { assertFalse "Line=${LINENO}, no default count" $? } -# checkCounter $COUNT $BALANCE +# checkCounter $COUNT $BALANCE [$HEIGHT] # Assumes just one coin, checks the balance of first coin in any case +# pass optional height to query which block to query checkCounter() { + # default height of 0, but accept an argument + HEIGHT=${3:-0} + # make sure sender goes down - ACCT=$(${CLIENT_EXE} query counter) + ACCT=$(${CLIENT_EXE} query counter --height=$HEIGHT) if assertTrue "Line=${LINENO}, count is set" $?; then assertEquals "Line=${LINENO}, proper count" "$1" $(echo $ACCT | jq .data.counter) assertEquals "Line=${LINENO}, proper money" "$2" $(echo $ACCT | jq .data.total_fees[0].amount) @@ -74,10 +78,10 @@ test03AddCount() { TX_HEIGHT=$(echo $TX | jq .height) # make sure the counter was updated - checkCounter "1" "10" + checkCounter "1" "10" "$TX_HEIGHT" # make sure the account was debited - checkAccount $SENDER "9007199254739990" + checkAccount $SENDER "9007199254739990" "$TX_HEIGHT" # make sure tx is indexed TX=$(${CLIENT_EXE} query tx $HASH --trace) @@ -96,18 +100,20 @@ test03AddCount() { # test again with fees... TX=$(echo qwertyuiop | ${CLIENT_EXE} tx counter --countfee=7mycoin --fee=4mycoin --sequence=3 --name=${RICH} --valid) txSucceeded $? "$TX" "counter" + TX_HEIGHT=$(echo $TX | jq .height) # make sure the counter was updated, added 7 - checkCounter "2" "17" - + checkCounter "2" "17" "$TX_HEIGHT" # make sure the account was debited 11 - checkAccount $SENDER "9007199254739979" + checkAccount $SENDER "9007199254739979" "$TX_HEIGHT" # make sure we cannot replay the counter, no state change TX=$(echo qwertyuiop | ${CLIENT_EXE} tx counter --countfee=10mycoin --sequence=2 --name=${RICH} --valid 2>/dev/null) assertFalse "line=${LINENO}, replay: $TX" $? - checkCounter "2" "17" - checkAccount $SENDER "9007199254739979" + TX_HEIGHT=$(echo $TX | jq .height) + + checkCounter "2" "17" "$TX_HEIGHT" + checkAccount $SENDER "9007199254739979" "$TX_HEIGHT" } # Load common then run these tests with shunit2! diff --git a/examples/eyes/tests/cli/eyes.sh b/examples/eyes/tests/cli/eyes.sh index f1e52b0acd..bd3b0dc7fa 100755 --- a/examples/eyes/tests/cli/eyes.sh +++ b/examples/eyes/tests/cli/eyes.sh @@ -49,7 +49,7 @@ test00SetGetRemove() { TX_HEIGHT=$(echo $TXRES | jq .height) # make sure it is set - DATA=$(${CLIENT_EXE} query eyes ${KEY}) + DATA=$(${CLIENT_EXE} query eyes ${KEY} --height=$TX_HEIGHT) assertTrue "line=${LINENO} data not set" $? assertEquals "line=${LINENO}" "\"${VALUE}\"" $(echo $DATA | jq .data.value) diff --git a/tests/cli/common.sh b/tests/cli/common.sh index 2b6b3679e3..aaeaca500c 100644 --- a/tests/cli/common.sh +++ b/tests/cli/common.sh @@ -142,11 +142,14 @@ checkAccount() { return $? } -# XXX Ex Usage: checkRole $ROLE $SIGS $NUM_SIGNERS +# XXX Ex Usage: checkRole $ROLE $SIGS $NUM_SIGNERS [$HEIGHT] # Desc: Ensures this named role exists, and has the number of members and required signatures as above checkRole() { + # default height of 0, but accept an argument + HEIGHT=${4:-0} + # make sure sender goes down - QROLE=$(${CLIENT_EXE} query role $1) + QROLE=$(${CLIENT_EXE} query role $1 --height=$HEIGHT) if ! assertTrue "line=${LINENO}, role must exist" $?; then return 1 fi From 609600d322025ff656fe73bd60c570cb2b958ad0 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Oct 2017 19:53:45 +0200 Subject: [PATCH 06/15] Fixed height handling in rest queries --- examples/basecoin/tests/cli/rest.sh | 16 ++++++++++------ modules/coin/rest/handlers.go | 2 +- modules/nonce/rest/handlers.go | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/examples/basecoin/tests/cli/rest.sh b/examples/basecoin/tests/cli/rest.sh index e840cbb91c..076e08e3e4 100755 --- a/examples/basecoin/tests/cli/rest.sh +++ b/examples/basecoin/tests/cli/rest.sh @@ -15,9 +15,9 @@ oneTimeSetUp() { exit 1; fi baseserver serve --port $BPORT >/dev/null & + sleep 0.1 # for startup PID_PROXY=$! disown - sleep 0.1 # for startup } oneTimeTearDown() { @@ -35,12 +35,16 @@ restAddr() { echo $ADDR } -# XXX Ex Usage: restAccount $ADDR $AMOUNT +# XXX Ex Usage: restAccount $ADDR $AMOUNT [$HEIGHT] # Desc: Assumes just one coin, checks the balance of first coin in any case restAccount() { assertNotNull "line=${LINENO}, address required" "$1" - ACCT=$(curl ${URL}/query/account/sigs:$1 2>/dev/null) - if [ -n "$DEBUG" ]; then echo $ACCT; echo; fi + QUERY=${URL}/query/account/sigs:$1 + if [ -n "$3" ]; then + QUERY="${QUERY}?height=${3}" + fi + ACCT=$(curl ${QUERY} 2>/dev/null) + if [ -n "$DEBUG" ]; then echo $QUERY; echo $ACCT; echo; fi assertEquals "line=${LINENO}, proper money" "$2" $(echo $ACCT | jq .data.coins[0].amount) return $? } @@ -76,8 +80,8 @@ test01SendTx() { HASH=$(echo $TX | jq .hash | tr -d \") TX_HEIGHT=$(echo $TX | jq .height) - restAccount $SENDER "9007199254740000" - restAccount $RECV "992" + restAccount $SENDER "9007199254740000" "$TX_HEIGHT" + restAccount $RECV "992" "$TX_HEIGHT" # Make sure tx is indexed checkSendTx $HASH $TX_HEIGHT $SENDER "992" diff --git a/modules/coin/rest/handlers.go b/modules/coin/rest/handlers.go index 443cc94080..6deaf44941 100644 --- a/modules/coin/rest/handlers.go +++ b/modules/coin/rest/handlers.go @@ -48,7 +48,7 @@ func doQueryAccount(w http.ResponseWriter, r *http.Request) { } var h int - qHeight := args["height"] + qHeight := r.URL.Query().Get("height") if qHeight != "" { h, err = strconv.Atoi(qHeight) if err != nil { diff --git a/modules/nonce/rest/handlers.go b/modules/nonce/rest/handlers.go index 3a3077616e..f22601951a 100644 --- a/modules/nonce/rest/handlers.go +++ b/modules/nonce/rest/handlers.go @@ -31,7 +31,7 @@ func doQueryNonce(w http.ResponseWriter, r *http.Request) { } var h int - qHeight := args["height"] + qHeight := r.URL.Query().Get("height") if qHeight != "" { h, err = strconv.Atoi(qHeight) if err != nil { From 9a3080ffccc9b2c15fcd6328ac19bef76817382c Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Oct 2017 20:58:43 +0200 Subject: [PATCH 07/15] Fix up some ibc queries, debug height mismatch --- examples/basecoin/tests/cli/ibc.sh | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/examples/basecoin/tests/cli/ibc.sh b/examples/basecoin/tests/cli/ibc.sh index b43d5793c1..f5fdf29a57 100755 --- a/examples/basecoin/tests/cli/ibc.sh +++ b/examples/basecoin/tests/cli/ibc.sh @@ -188,16 +188,17 @@ test04SendIBCPacket() { checkSendTx $HASH $TX_HEIGHT $SENDER "20002" # look, we wrote a packet - PACKETS=$(${CLIENT_EXE} query ibc packets --to=$CHAIN_ID_2) + PACKETS=$(${CLIENT_EXE} query ibc packets --to=$CHAIN_ID_2 --height=$TX_HEIGHT) assertTrue "line=${LINENO}, packets query" $? assertEquals "line=${LINENO}, packet count" 1 $(echo $PACKETS | jq .data) # and look at the packet itself - PACKET=$(${CLIENT_EXE} query ibc packet --to=$CHAIN_ID_2 --sequence=0) + PACKET=$(${CLIENT_EXE} query ibc packet --to=$CHAIN_ID_2 --sequence=0 --height=$TX_HEIGHT) assertTrue "line=${LINENO}, packet query" $? assertEquals "line=${LINENO}, proper src" "\"$CHAIN_ID_1\"" $(echo $PACKET | jq .src_chain) assertEquals "line=${LINENO}, proper dest" "\"$CHAIN_ID_2\"" $(echo $PACKET | jq .packet.dest_chain) assertEquals "line=${LINENO}, proper sequence" "0" $(echo $PACKET | jq .packet.sequence) + echo $PACKET # nothing arrived ARRIVED=$(${CLIENT_EXE} query ibc packets --from=$CHAIN_ID_1 --home=$CLIENT_2 2>/dev/null) @@ -211,12 +212,15 @@ test05ReceiveIBCPacket() { # make some credit, so we can accept the packet TX=$(echo qwertyuiop | ${CLIENT_EXE} tx credit --amount=60006mycoin --to=$CHAIN_ID_1:: --name=$RICH) txSucceeded $? "$TX" "${CHAIN_ID_1}::" - checkAccount $CHAIN_ID_1:: "60006" "$TX_HEIGHT" + TX_HEIGHT=$(echo $TX | jq .height) + checkAccount $CHAIN_ID_1:: "60006" "$TX_HEIGHT" # now, we try to post it.... (this is PACKET from last test) # get the seed and post it SRC_HEIGHT=$(echo $PACKET | jq .src_height) + SRC_HEIGHT=$(expr $SRC_HEIGHT + 1) + echo "src_height:" $SRC_HEIGHT # FIXME: this should auto-update on proofs... ${CLIENT_EXE} seeds update --height=$SRC_HEIGHT --home=${CLIENT_1} > /dev/null assertTrue "line=${LINENO}, update seed failed" $? @@ -224,14 +228,16 @@ test05ReceiveIBCPacket() { PACKET_SEED="$BASE_DIR_1/packet_seed.json" ${CLIENT_EXE} seeds export $PACKET_SEED --home=${CLIENT_1} #--height=$SRC_HEIGHT assertTrue "line=${LINENO}, export seed failed" $? - # echo "**** SEED ****" - # cat $PACKET_SEED | jq . + echo "**** SEED ****" + cat $PACKET_SEED | jq .checkpoint.header + # cat $PACKET_SEED | jq .checkpoint.header.app_hash TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \ - --seed=${PACKET_SEED} --name=$POOR) + --seed=${PACKET_SEED} --name=$POOR --sequence=3) txSucceeded $? "$TX" "prepare packet chain1 on chain 2" # an example to quit early if there is no point in more tests if [ $? != 0 ]; then echo "aborting!"; return 1; fi + TX_HEIGHT=$(echo $TX | jq .height) # write the packet to the file POST_PACKET="$BASE_DIR_1/post_packet.json" @@ -241,13 +247,14 @@ test05ReceiveIBCPacket() { # post it as a tx (cross-fingers) TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-post \ - --packet=${POST_PACKET} --name=$POOR) + --packet=${POST_PACKET} --name=$POOR --sequence=4) txSucceeded $? "$TX" "post packet from chain1 on chain 2" + TX_HEIGHT=$(echo $TX | jq .height) # TODO: more queries on stuff... # look, we wrote a packet - PACKETS=$(${CLIENT_EXE} query ibc packets --from=$CHAIN_ID_1) + PACKETS=$(${CLIENT_EXE} query ibc packets --height=$TX_HEIGHT --from=$CHAIN_ID_1) assertTrue "line=${LINENO}, packets query" $? assertEquals "line=${LINENO}, packet count" 1 $(echo $PACKETS | jq .data) } From 0d9c8de958e715adeb09ef679275d072965dbc8c Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 19 Oct 2017 15:44:11 +0200 Subject: [PATCH 08/15] Fix IBC off-by-one with proofs --- examples/basecoin/tests/cli/ibc.sh | 13 ++++++------- modules/ibc/middleware.go | 5 ++++- modules/ibc/tx.go | 1 + 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/examples/basecoin/tests/cli/ibc.sh b/examples/basecoin/tests/cli/ibc.sh index f5fdf29a57..ef9c8f6fdc 100755 --- a/examples/basecoin/tests/cli/ibc.sh +++ b/examples/basecoin/tests/cli/ibc.sh @@ -198,7 +198,7 @@ test04SendIBCPacket() { assertEquals "line=${LINENO}, proper src" "\"$CHAIN_ID_1\"" $(echo $PACKET | jq .src_chain) assertEquals "line=${LINENO}, proper dest" "\"$CHAIN_ID_2\"" $(echo $PACKET | jq .packet.dest_chain) assertEquals "line=${LINENO}, proper sequence" "0" $(echo $PACKET | jq .packet.sequence) - echo $PACKET + if [ -n "$DEBUG" ]; then echo $PACKET; echo; fi # nothing arrived ARRIVED=$(${CLIENT_EXE} query ibc packets --from=$CHAIN_ID_1 --home=$CLIENT_2 2>/dev/null) @@ -220,7 +220,6 @@ test05ReceiveIBCPacket() { # get the seed and post it SRC_HEIGHT=$(echo $PACKET | jq .src_height) SRC_HEIGHT=$(expr $SRC_HEIGHT + 1) - echo "src_height:" $SRC_HEIGHT # FIXME: this should auto-update on proofs... ${CLIENT_EXE} seeds update --height=$SRC_HEIGHT --home=${CLIENT_1} > /dev/null assertTrue "line=${LINENO}, update seed failed" $? @@ -228,9 +227,11 @@ test05ReceiveIBCPacket() { PACKET_SEED="$BASE_DIR_1/packet_seed.json" ${CLIENT_EXE} seeds export $PACKET_SEED --home=${CLIENT_1} #--height=$SRC_HEIGHT assertTrue "line=${LINENO}, export seed failed" $? - echo "**** SEED ****" - cat $PACKET_SEED | jq .checkpoint.header - # cat $PACKET_SEED | jq .checkpoint.header.app_hash + if [ -n "$DEBUG" ]; then + echo "**** SEED ****" + cat $PACKET_SEED | jq .checkpoint.header + echo + fi TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \ --seed=${PACKET_SEED} --name=$POOR --sequence=3) @@ -242,8 +243,6 @@ test05ReceiveIBCPacket() { # write the packet to the file POST_PACKET="$BASE_DIR_1/post_packet.json" echo $PACKET > $POST_PACKET - # echo "**** POST ****" - # cat $POST_PACKET | jq . # post it as a tx (cross-fingers) TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-post \ diff --git a/modules/ibc/middleware.go b/modules/ibc/middleware.go index fcf169aebc..09ffabb142 100644 --- a/modules/ibc/middleware.go +++ b/modules/ibc/middleware.go @@ -94,7 +94,10 @@ func (m Middleware) verifyPost(ctx sdk.Context, store state.SimpleDB, // look up the referenced header space := stack.PrefixedStore(from, store) provider := newDBProvider(space) - seed, err := provider.GetExactHeight(int(tx.FromChainHeight)) + + // if the query was on height H, the proof is in header H+1 + proofHeight := int(tx.FromChainHeight + 1) + seed, err := provider.GetExactHeight(proofHeight) if err != nil { return ictx, itx, err } diff --git a/modules/ibc/tx.go b/modules/ibc/tx.go index 89a86d0672..c2dc9ec835 100644 --- a/modules/ibc/tx.go +++ b/modules/ibc/tx.go @@ -113,6 +113,7 @@ type PostPacketTx struct { // The immediate source of the packet, not always Packet.SrcChainID FromChainID string `json:"src_chain"` // The block height in which Packet was committed, to check Proof + // AppHash for the proof in header for FromChainHeight+1 FromChainHeight uint64 `json:"src_height"` // this proof must match the header and the packet.Bytes() Proof *iavl.KeyExistsProof `json:"proof"` From 2e6b45437d701039c005d11a25620e02c8a5a1d5 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 19 Oct 2017 15:56:39 +0200 Subject: [PATCH 09/15] Better tests on ibc packet receipt, clean up shell test --- examples/basecoin/tests/cli/ibc.sh | 109 ++++------------------------- 1 file changed, 14 insertions(+), 95 deletions(-) diff --git a/examples/basecoin/tests/cli/ibc.sh b/examples/basecoin/tests/cli/ibc.sh index ef9c8f6fdc..275f4aeae4 100755 --- a/examples/basecoin/tests/cli/ibc.sh +++ b/examples/basecoin/tests/cli/ibc.sh @@ -208,24 +208,31 @@ test04SendIBCPacket() { test05ReceiveIBCPacket() { export BC_HOME=${CLIENT_2} + RECV=$(getAddr $POOR) # make some credit, so we can accept the packet TX=$(echo qwertyuiop | ${CLIENT_EXE} tx credit --amount=60006mycoin --to=$CHAIN_ID_1:: --name=$RICH) txSucceeded $? "$TX" "${CHAIN_ID_1}::" TX_HEIGHT=$(echo $TX | jq .height) + + # make sure there is enough credit checkAccount $CHAIN_ID_1:: "60006" "$TX_HEIGHT" + # and the poor guy doesn't have a penny to his name + ACCT2=$(${CLIENT_EXE} query account $RECV 2>/dev/null) + assertFalse "line=${LINENO}, has no genesis account" $? + # now, we try to post it.... (this is PACKET from last test) - # get the seed and post it + # get the seed with the proof and post it SRC_HEIGHT=$(echo $PACKET | jq .src_height) - SRC_HEIGHT=$(expr $SRC_HEIGHT + 1) + PROOF_HEIGHT=$(expr $SRC_HEIGHT + 1) # FIXME: this should auto-update on proofs... - ${CLIENT_EXE} seeds update --height=$SRC_HEIGHT --home=${CLIENT_1} > /dev/null + ${CLIENT_EXE} seeds update --height=$PROOF_HEIGHT --home=${CLIENT_1} > /dev/null assertTrue "line=${LINENO}, update seed failed" $? PACKET_SEED="$BASE_DIR_1/packet_seed.json" - ${CLIENT_EXE} seeds export $PACKET_SEED --home=${CLIENT_1} #--height=$SRC_HEIGHT + ${CLIENT_EXE} seeds export $PACKET_SEED --home=${CLIENT_1} --height=$PROOF_HEIGHT assertTrue "line=${LINENO}, export seed failed" $? if [ -n "$DEBUG" ]; then echo "**** SEED ****" @@ -250,7 +257,9 @@ test05ReceiveIBCPacket() { txSucceeded $? "$TX" "post packet from chain1 on chain 2" TX_HEIGHT=$(echo $TX | jq .height) - # TODO: more queries on stuff... + # ensure $POOR balance was incremented, and credit for CHAIN_1 decremented + checkAccount $CHAIN_ID_1:: "40004" "$TX_HEIGHT" + checkAccount $RECV "20002" "$TX_HEIGHT" # look, we wrote a packet PACKETS=$(${CLIENT_EXE} query ibc packets --height=$TX_HEIGHT --from=$CHAIN_ID_1) @@ -258,7 +267,6 @@ test05ReceiveIBCPacket() { assertEquals "line=${LINENO}, packet count" 1 $(echo $PACKETS | jq .data) } - # XXX Ex Usage: assertNewHeight $MSG $SEED_1 $SEED_2 # Desc: Asserts that seed2 has a higher block height than seed 1 assertNewHeight() { @@ -268,95 +276,6 @@ assertNewHeight() { return $? } -# test01SendIBCTx() { -# # Trigger a cross-chain sendTx... from RICH on chain1 to POOR on chain2 -# # we make sure the money was reduced, but nothing arrived -# SENDER=$(BC_HOME=${CLIENT_1} getAddr $RICH) -# RECV=$(BC_HOME=${CLIENT_2} getAddr $POOR) - -# export BC_HOME=${CLIENT_1} -# TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=20002mycoin \ -# --sequence=1 --to=${CHAIN_ID_2}/${RECV} --name=$RICH) -# txSucceeded $? "$TX" "${CHAIN_ID_2}/${RECV}" -# # an example to quit early if there is no point in more tests -# if [ $? != 0 ]; then echo "aborting!"; return 1; fi - -# HASH=$(echo $TX | jq .hash | tr -d \") -# TX_HEIGHT=$(echo $TX | jq .height) - -# # Make sure balance went down and tx is indexed -# checkAccount $SENDER "1" "9007199254720990" "$TX_HEIGHT" -# checkSendTx $HASH $TX_HEIGHT $SENDER "20002" - -# # Make sure nothing arrived - yet -# waitForBlock ${PORT_1} -# assertFalse "line=${LINENO}, no relay running" "BC_HOME=${CLIENT_2} ${CLIENT_EXE} query account $RECV" - -# # Start the relay and wait a few blocks... -# # (already sent a tx on chain1, so use higher sequence) -# startRelay 2 1 -# if [ $? != 0 ]; then echo "can't start relay"; cat ${BASE_DIR_1}/../relay.log; return 1; fi - -# # Give it a little time, then make sure the money arrived -# echo "waiting for relay..." -# sleep 1 -# waitForBlock ${PORT_1} -# waitForBlock ${PORT_2} - -# # Check the new account -# echo "checking ibc recipient..." -# BC_HOME=${CLIENT_2} checkAccount $RECV "0" "20002" - -# # Stop relay -# printf "stoping relay\n" -# kill -9 $PID_RELAY -# } - -# # StartRelay $seq1 $seq2 -# # startRelay hooks up a relay between chain1 and chain2 -# # it needs the proper sequence number for $RICH on chain1 and chain2 as args -# startRelay() { -# # Send some cash to the default key, so it can send messages -# RELAY_KEY=${BASE_DIR_1}/server/key.json -# RELAY_ADDR=$(cat $RELAY_KEY | jq .address | tr -d \") -# echo starting relay $PID_RELAY ... - -# # Get paid on chain1 -# export BC_HOME=${CLIENT_1} -# SENDER=$(getAddr $RICH) -# RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=100000mycoin \ -# --sequence=$1 --to=$RELAY_ADDR --name=$RICH) -# txSucceeded $? "$RES" "$RELAY_ADDR" -# if [ $? != 0 ]; then echo "can't pay chain1!"; return 1; fi - -# # Get paid on chain2 -# export BC_HOME=${CLIENT_2} -# SENDER=$(getAddr $RICH) -# RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=100000mycoin \ -# --sequence=$2 --to=$RELAY_ADDR --name=$RICH) -# txSucceeded $? "$RES" "$RELAY_ADDR" -# if [ $? != 0 ]; then echo "can't pay chain2!"; return 1; fi - -# # Initialize the relay (register both chains) -# ${SERVER_EXE} relay init --chain1-id=$CHAIN_ID_1 --chain2-id=$CHAIN_ID_2 \ -# --chain1-addr=tcp://localhost:${PORT_1} --chain2-addr=tcp://localhost:${PORT_2} \ -# --genesis1=${BASE_DIR_1}/server/genesis.json --genesis2=${BASE_DIR_2}/server/genesis.json \ -# --from=$RELAY_KEY > ${BASE_DIR_1}/../relay.log -# if [ $? != 0 ]; then echo "can't initialize relays"; cat ${BASE_DIR_1}/../relay.log; return 1; fi - -# # Now start the relay (constantly send packets) -# ${SERVER_EXE} relay start --chain1-id=$CHAIN_ID_1 --chain2-id=$CHAIN_ID_2 \ -# --chain1-addr=tcp://localhost:${PORT_1} --chain2-addr=tcp://localhost:${PORT_2} \ -# --from=$RELAY_KEY >> ${BASE_DIR_1}/../relay.log & -# sleep 2 -# PID_RELAY=$! -# disown - -# # Return an error if it dies in the first two seconds to make sure it is running -# ps $PID_RELAY >/dev/null -# return $? -# } - # Load common then run these tests with shunit2! DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory CLI_DIR=$GOPATH/src/github.com/cosmos/cosmos-sdk/tests/cli From f40807ce5ff8f4d8e75d5055dd4bfdf7c11604b1 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 19 Oct 2017 16:11:01 +0200 Subject: [PATCH 10/15] Update ibc unit tests for height+1 --- modules/ibc/test_helpers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ibc/test_helpers.go b/modules/ibc/test_helpers.go index 7219ecc544..6f0a9bda06 100644 --- a/modules/ibc/test_helpers.go +++ b/modules/ibc/test_helpers.go @@ -42,7 +42,7 @@ func (m MockChain) MakePostPacket(packet Packet, h int) ( PostPacketTx, UpdateChainTx) { post := makePostPacket(m.tree, packet, m.chainID, h) - seed := genEmptySeed(m.keys, m.chainID, h, m.tree.Hash(), len(m.keys)) + seed := genEmptySeed(m.keys, m.chainID, h+1, m.tree.Hash(), len(m.keys)) update := UpdateChainTx{seed} return post, update From ae6c9ef9b1a6f2157050be78894b15c53cd78480 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 19 Oct 2017 16:03:04 +0200 Subject: [PATCH 11/15] update abci, iavl, tendermint versions again --- glide.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/glide.lock b/glide.lock index 54c597f601..cdd2ba1eb7 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: fa04e2d0e8764d44c0f8e3400d7d12118b0f05aac6c12e5ff0d3dd1940c03100 -updated: 2017-10-18T13:44:50.561421607+02:00 +updated: 2017-10-19T16:01:35.775869665+02:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -107,7 +107,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: 3c16b313dd2342bb576844ade3acca3010928908 + version: 5162ed1b2b4e7c0cea98be442210b43a0b6b94b9 subpackages: - client - example/dummy @@ -133,7 +133,7 @@ imports: - data - data/base58 - name: github.com/tendermint/iavl - version: ff4ffa531df48509d51f0c16c2432f986eed9fcc + version: 4f9a4a2433e3b3022ae2ceec50a1f57689d54145 - name: github.com/tendermint/light-client version: 79125bb4dfe173fe8a7208327ac4ec4c73d1a8a7 subpackages: @@ -142,7 +142,7 @@ imports: - certifiers/files - proofs - name: github.com/tendermint/tendermint - version: b234f7aba2e6c39f0023be8712be23f7a78e1b11 + version: fa56e8c0ce463f77c87ab17a3d7cf5431d9f2c0b subpackages: - blockchain - cmd/tendermint/commands From 822b6a3fef10dd6cd2f6b17e6585bdd7f2833658 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 19 Oct 2017 17:44:22 +0200 Subject: [PATCH 12/15] Cleanup loop per Alexis --- genesis/parse.go | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/genesis/parse.go b/genesis/parse.go index 67bc32ef1d..a3a937efd3 100644 --- a/genesis/parse.go +++ b/genesis/parse.go @@ -54,22 +54,18 @@ func GetOptions(path string) ([]Option, error) { opts := genDoc.AppOptions cnt := 1 + len(opts.Accounts) + len(opts.pluginOptions) - res := make([]Option, cnt) - - res[0] = Option{sdk.ModuleNameBase, sdk.ChainKey, genDoc.ChainID} - i := 1 + res := make([]Option, 0, cnt) + res = append(res, Option{sdk.ModuleNameBase, sdk.ChainKey, genDoc.ChainID}) // set accounts for _, acct := range opts.Accounts { - res[i] = Option{"coin", "account", string(acct)} - i++ + res = append(res, Option{"coin", "account", string(acct)}) } // set plugin options for _, kv := range opts.pluginOptions { module, key := splitKey(kv.Key) - res[i] = Option{module, key, kv.Value} - i++ + res = append(res, Option{module, key, kv.Value}) } return res, nil From ba27d23ad172f68f7999ed90b8830e1040410ed2 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 20 Oct 2017 13:45:54 +0200 Subject: [PATCH 13/15] Clean up genesis parse per Anton --- genesis/parse.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/genesis/parse.go b/genesis/parse.go index a3a937efd3..e447ac0bc4 100644 --- a/genesis/parse.go +++ b/genesis/parse.go @@ -10,6 +10,10 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) +// KeyDelimiter is used to separate module and key in +// the options +const KeyDelimiter = "/" + // Option just holds module/key/value triples from // parsing the genesis file type Option struct { @@ -141,8 +145,8 @@ func parseList(kvzIn []json.RawMessage) (kvz []keyValue, err error) { // Splits the string at the first '/'. // if there are none, assign default module ("base"). func splitKey(key string) (string, string) { - if strings.Contains(key, "/") { - keyParts := strings.SplitN(key, "/", 2) + if strings.Contains(key, KeyDelimiter) { + keyParts := strings.SplitN(key, KeyDelimiter, 2) return keyParts[0], keyParts[1] } return sdk.ModuleNameBase, key From 630c5ca9ffb4722e6fc3235979772f7c772ed1bf Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 20 Oct 2017 19:41:01 +0200 Subject: [PATCH 14/15] Update iavl tree and address pr cleanup comments --- app/app_test.go | 6 +++--- app/store.go | 10 ++-------- glide.lock | 8 ++++---- state/merkle.go | 22 ++++++++++++++++++++-- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/app/app_test.go b/app/app_test.go index c5e4880229..39f205f0f7 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -218,13 +218,13 @@ func TestInitState(t *testing.T) { assert.Equal(unsortCoins, coins) err = app.InitState("base", "dslfkgjdas", "") - require.NotNil(err) + require.Error(err) err = app.InitState("", "dslfkgjdas", "") - require.NotNil(err) + require.Error(err) err = app.InitState("dslfkgjdas", "szfdjzs", "") - require.NotNil(err) + require.Error(err) } // Test CheckTx and DeliverTx with insufficient and sufficient balance diff --git a/app/store.go b/app/store.go index 24b465ee9d..faa0d77ce8 100644 --- a/app/store.go +++ b/app/store.go @@ -258,17 +258,11 @@ func loadState(dbName string, cacheSize int, historySize uint64) (*sm.State, err dir := path.Dir(dbPath) name := path.Base(dbPath) - // Make sure the path exists - empty, _ := cmn.IsDirEmpty(dbPath + ".db") - // Open database called "dir/name.db", if it doesn't exist it will be created db := dbm.NewDB(name, dbm.LevelDBBackendStr, dir) tree := iavl.NewVersionedTree(cacheSize, db) - - if !empty { - if err = tree.Load(); err != nil { - return nil, errors.ErrInternal("Loading tree: " + err.Error()) - } + if err = tree.Load(); err != nil { + return nil, errors.ErrInternal("Loading tree: " + err.Error()) } return sm.NewState(tree, historySize), nil diff --git a/glide.lock b/glide.lock index cdd2ba1eb7..9702ff2b44 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: fa04e2d0e8764d44c0f8e3400d7d12118b0f05aac6c12e5ff0d3dd1940c03100 -updated: 2017-10-19T16:01:35.775869665+02:00 +updated: 2017-10-20T19:33:25.496934736+02:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -133,9 +133,9 @@ imports: - data - data/base58 - name: github.com/tendermint/iavl - version: 4f9a4a2433e3b3022ae2ceec50a1f57689d54145 + version: 721710e7aa59f61dbfbf558943a207ba3fe6b926 - name: github.com/tendermint/light-client - version: 79125bb4dfe173fe8a7208327ac4ec4c73d1a8a7 + version: f817693e93241ee10d8ad49935f7c05b4776d829 subpackages: - certifiers - certifiers/client @@ -237,7 +237,7 @@ imports: - tap - transport - name: gopkg.in/go-playground/validator.v9 - version: d529ee1b0f30352444f507cc6cdac96bfd12decc + version: 6d8c18553ea1ac493d049edd6f102f52e618f085 - name: gopkg.in/yaml.v2 version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b testImports: diff --git a/state/merkle.go b/state/merkle.go index b301438305..7bfabc4375 100644 --- a/state/merkle.go +++ b/state/merkle.go @@ -11,6 +11,8 @@ type State struct { historySize uint64 } +// NewState wraps a versioned tree and maintains all needed +// states for the abci app func NewState(tree *iavl.VersionedTree, historySize uint64) *State { base := NewBonsai(tree) return &State{ @@ -21,31 +23,47 @@ func NewState(tree *iavl.VersionedTree, historySize uint64) *State { } } +// Size is the number of nodes in the last commit func (s State) Size() int { return s.committed.Tree.Size() } +// IsEmpty is true is no data was ever in the tree +// (and signals it is unsafe to save) +func (s State) IsEmpty() bool { + return s.committed.Tree.IsEmpty() +} + +// Committed gives us read-only access to the committed +// state(s), including historical queries func (s State) Committed() *Bonsai { return s.committed } +// Append gives us read-write access to the current working +// state (to be committed at EndBlock) func (s State) Append() SimpleDB { return s.deliverTx } +// Append gives us read-write access to the current scratch +// state (to be reset at EndBlock) func (s State) Check() SimpleDB { return s.checkTx } +// LatestHeight is the last block height we have committed func (s State) LatestHeight() uint64 { return s.committed.Tree.LatestVersion() } +// LatestHash is the root hash of the last state we have +// committed func (s State) LatestHash() []byte { return s.committed.Tree.Hash() } -// Commit save persistent nodes to the database and re-copies the trees +// Commit saves persistent nodes to the database and re-copies the trees func (s *State) Commit(version uint64) ([]byte, error) { // commit (if we didn't do hash earlier) err := s.committed.Commit(s.deliverTx) @@ -55,7 +73,7 @@ func (s *State) Commit(version uint64) ([]byte, error) { // store a new version var hash []byte - if s.committed.Tree.Size() > 0 || s.committed.Tree.LatestVersion() > 0 { + if !s.IsEmpty() { hash, err = s.committed.Tree.SaveVersion(version) if err != nil { return nil, err From ae09c8fafff7c95e726c09a00f42d7b33a447a4c Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 14:56:32 +0200 Subject: [PATCH 15/15] Dpes use develop, now that abci and light client prs are merged --- glide.lock | 10 +++++----- glide.yaml | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/glide.lock b/glide.lock index 9702ff2b44..2bd6a73941 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: fa04e2d0e8764d44c0f8e3400d7d12118b0f05aac6c12e5ff0d3dd1940c03100 -updated: 2017-10-20T19:33:25.496934736+02:00 +hash: fbfdd03c0367bb0785ceb81ed34059df219e55d5a9c71c12597e505fbce14165 +updated: 2017-10-23T14:49:22.891642342+02:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -107,7 +107,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: 5162ed1b2b4e7c0cea98be442210b43a0b6b94b9 + version: bb9bb4aa465a31fd6a272765be381888e6898c74 subpackages: - client - example/dummy @@ -128,14 +128,14 @@ imports: - keys/storage/memstorage - keys/wordlist - name: github.com/tendermint/go-wire - version: 26ee079df7fca1958da8995c727b59759b197534 + version: 55ae61f1fc83cfaa57ab7d54250d7a1a2be0b83c subpackages: - data - data/base58 - name: github.com/tendermint/iavl version: 721710e7aa59f61dbfbf558943a207ba3fe6b926 - name: github.com/tendermint/light-client - version: f817693e93241ee10d8ad49935f7c05b4776d829 + version: 569e1583da8a52e499764533f3a05d05be6d56d6 subpackages: - certifiers - certifiers/client diff --git a/glide.yaml b/glide.yaml index 03ad9bf18f..258c028e44 100644 --- a/glide.yaml +++ b/glide.yaml @@ -7,7 +7,7 @@ import: - package: github.com/spf13/pflag - package: github.com/spf13/viper - package: github.com/tendermint/abci - version: feature/merkleeyes-to-iavl + version: develop subpackages: - server - types @@ -20,7 +20,7 @@ import: subpackages: - data - package: github.com/tendermint/light-client - version: feature/merkleeyes-to-iavl + version: develop subpackages: - proofs - certifiers