From 82714e7ccc36a81b892e77d96190a471168c779a Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 19 Oct 2017 15:57:57 +0200 Subject: [PATCH 001/117] Note that go 1.8+ is required --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a5bc0e3f0971..3e759ebc337f 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ master | [![CircleCI](https://circleci.com/gh/cosmos/cosmos-sdk/tree/master.s !!!!!!!!!!!!!!!!!!!!! +**Note: Requires Go 1.8+** + The Cosmos SDK is the middleware platform that the [Cosmos Hub](https://cosmos.network) is constructed from. The Hub is a blockchain (or, internet of blockchains) in which the Atom supply resides. The Atoms supply is defined at genesis and can change based on the rules of the Hub. Under the hood, the Cosmos SDK is an [ABCI application](https://github.com/tendermint/abci) designed to be used with the [Tendermint consensus engine](https://tendermint.com/) to form a Proof-of-Stake cryptocurrency. It also provides a general purpose framework From 6c667b8398b22c6711af128e244cd3221926b705 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 20 Oct 2017 13:05:59 +0200 Subject: [PATCH 002/117] Use tendermint version format for basecoin version --- client/commands/version.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/commands/version.go b/client/commands/version.go index 551b2506f363..172185fdfbe9 100644 --- a/client/commands/version.go +++ b/client/commands/version.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/cosmos/cosmos-sdk/version" ) @@ -15,6 +16,6 @@ var VersionCmd = &cobra.Command{ Use: "version", Short: "Show version info", Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("v%s %s\n", version.Version, CommitHash) + fmt.Printf("%s-%s\n", version.Version, CommitHash) }, } From e863e1be70a47fae1be48f7450d5a1c6b006567f Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 16 Oct 2017 15:51:37 +0200 Subject: [PATCH 003/117] Started separating BaseApp from Basecoin --- app/app.go | 151 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 87 insertions(+), 64 deletions(-) diff --git a/app/app.go b/app/app.go index e20f97f2c787..b89042d8e8e5 100644 --- a/app/app.go +++ b/app/app.go @@ -24,15 +24,9 @@ const ( // Basecoin - The ABCI application type Basecoin struct { - info *sm.ChainState - state *Store - + *BaseApp handler sdk.Handler tick Ticker - - pending []*abci.Validator - height uint64 - logger log.Logger } // Ticker - tick function @@ -43,48 +37,20 @@ var _ abci.Application = &Basecoin{} // NewBasecoin - create a new instance of the basecoin application func NewBasecoin(handler sdk.Handler, store *Store, logger log.Logger) *Basecoin { return &Basecoin{ + BaseApp: NewBaseApp(store, logger), handler: handler, - info: sm.NewChainState(), - state: store, - logger: logger, } } // NewBasecoinTick - create a new instance of the basecoin application with tick functionality func NewBasecoinTick(handler sdk.Handler, store *Store, logger log.Logger, tick Ticker) *Basecoin { return &Basecoin{ + BaseApp: NewBaseApp(store, logger), handler: handler, - info: sm.NewChainState(), - state: store, - logger: logger, tick: tick, } } -// GetChainID returns the currently stored chain -func (app *Basecoin) GetChainID() string { - return app.info.GetChainID(app.state.Committed()) -} - -// GetState is back... please kill me -func (app *Basecoin) GetState() sm.SimpleDB { - return app.state.Append() -} - -// Info - ABCI -func (app *Basecoin) Info(req abci.RequestInfo) abci.ResponseInfo { - resp := app.state.Info() - app.logger.Debug("Info", - "height", resp.LastBlockHeight, - "hash", fmt.Sprintf("%X", resp.LastBlockAppHash)) - app.height = resp.LastBlockHeight - return abci.ResponseInfo{ - Data: fmt.Sprintf("Basecoin v%v", version.Version), - LastBlockHeight: resp.LastBlockHeight, - LastBlockAppHash: resp.LastBlockAppHash, - } -} - // InitState - used to setup state (was SetOption) // to be used by InitChain later func (app *Basecoin) InitState(key string, value string) string { @@ -99,18 +65,13 @@ func (app *Basecoin) InitState(key string, value string) string { return fmt.Sprintf("Error: unknown base option: %s", key) } - log, err := app.handler.InitState(app.logger, state, module, key, value) + log, err := app.handler.InitState(app.Logger(), state, module, key, value) if err == nil { return log } return "Error: " + err.Error() } -// SetOption - ABCI -func (app *Basecoin) SetOption(key string, value string) string { - return "Not Implemented" -} - // DeliverTx - ABCI func (app *Basecoin) DeliverTx(txBytes []byte) abci.Result { tx, err := sdk.LoadTx(txBytes) @@ -121,14 +82,14 @@ func (app *Basecoin) DeliverTx(txBytes []byte) abci.Result { ctx := stack.NewContext( app.GetChainID(), app.height, - app.logger.With("call", "delivertx"), + app.Logger().With("call", "delivertx"), ) res, err := app.handler.DeliverTx(ctx, app.state.Append(), tx) if err != nil { return errors.Result(err) } - app.addValChange(res.Diff) + app.AddValChange(res.Diff) return sdk.ToABCI(res) } @@ -142,7 +103,7 @@ func (app *Basecoin) CheckTx(txBytes []byte) abci.Result { ctx := stack.NewContext( app.GetChainID(), app.height, - app.logger.With("call", "checktx"), + app.Logger().With("call", "checktx"), ) res, err := app.handler.CheckTx(ctx, app.state.Check(), tx) @@ -152,8 +113,82 @@ func (app *Basecoin) CheckTx(txBytes []byte) abci.Result { return sdk.ToABCI(res) } +// BeginBlock - ABCI +func (app *Basecoin) BeginBlock(req abci.RequestBeginBlock) { + // call the embeded Begin + app.BaseApp.BeginBlock(req) + + // now execute tick + if app.tick != nil { + diff, err := app.tick(app.state.Append()) + if err != nil { + panic(err) + } + app.AddValChange(diff) + } +} + +/////////////////////////// Move to SDK /////// + +// BaseApp contains a data store and all info needed +// to perform queries and handshakes. +// +// It should be embeded in another struct for CheckTx, +// DeliverTx and initializing state from the genesis. +type BaseApp struct { + info *sm.ChainState + state *Store + + pending []*abci.Validator + height uint64 + logger log.Logger +} + +// NewBaseApp creates a data store to handle queries +func NewBaseApp(store *Store, logger log.Logger) *BaseApp { + return &BaseApp{ + info: sm.NewChainState(), + state: store, + logger: logger, + } +} + +// GetChainID returns the currently stored chain +func (app *BaseApp) GetChainID() string { + return app.info.GetChainID(app.state.Committed()) +} + +// GetState returns the delivertx state, should be removed +func (app *BaseApp) GetState() sm.SimpleDB { + return app.state.Append() +} + +// Logger returns the application base logger +func (app *BaseApp) Logger() log.Logger { + return app.logger +} + +// Info - ABCI +func (app *BaseApp) Info(req abci.RequestInfo) abci.ResponseInfo { + resp := app.state.Info() + app.logger.Debug("Info", + "height", resp.LastBlockHeight, + "hash", fmt.Sprintf("%X", resp.LastBlockAppHash)) + app.height = resp.LastBlockHeight + return abci.ResponseInfo{ + Data: fmt.Sprintf("Basecoin v%v", version.Version), + LastBlockHeight: resp.LastBlockHeight, + LastBlockAppHash: resp.LastBlockAppHash, + } +} + +// SetOption - ABCI +func (app *BaseApp) SetOption(key string, value string) string { + return "Not Implemented" +} + // Query - ABCI -func (app *Basecoin) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) { +func (app *BaseApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) { if len(reqQuery.Data) == 0 { resQuery.Log = "Query cannot be zero length" resQuery.Code = abci.CodeType_EncodingError @@ -164,7 +199,7 @@ func (app *Basecoin) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQu } // Commit - ABCI -func (app *Basecoin) Commit() (res abci.Result) { +func (app *BaseApp) Commit() (res abci.Result) { // Commit state res = app.state.Commit() if res.IsErr() { @@ -174,39 +209,27 @@ func (app *Basecoin) Commit() (res abci.Result) { } // InitChain - ABCI -func (app *Basecoin) InitChain(req abci.RequestInitChain) { +func (app *BaseApp) InitChain(req abci.RequestInitChain) { // for _, plugin := range app.plugins.GetList() { // plugin.InitChain(app.state, validators) // } } // BeginBlock - ABCI -func (app *Basecoin) BeginBlock(req abci.RequestBeginBlock) { +func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) { app.height++ - - // for _, plugin := range app.plugins.GetList() { - // plugin.BeginBlock(app.state, hash, header) - // } - - if app.tick != nil { - diff, err := app.tick(app.state.Append()) - if err != nil { - panic(err) - } - app.addValChange(diff) - } } // EndBlock - ABCI // Returns a list of all validator changes made in this block -func (app *Basecoin) EndBlock(height uint64) (res abci.ResponseEndBlock) { +func (app *BaseApp) EndBlock(height uint64) (res abci.ResponseEndBlock) { // TODO: cleanup in case a validator exists multiple times in the list res.Diffs = app.pending app.pending = nil return } -func (app *Basecoin) addValChange(diffs []*abci.Validator) { +func (app *BaseApp) AddValChange(diffs []*abci.Validator) { for _, d := range diffs { idx := pubKeyIndex(d, app.pending) if idx >= 0 { From 987c0469da2b9e7d61e48c74b4bb6c02afb19083 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 16 Oct 2017 15:56:23 +0200 Subject: [PATCH 004/117] Pull out basecoin stuff --- app/app.go | 109 ------------------------------------------------ app/bc.go | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 109 deletions(-) create mode 100644 app/bc.go diff --git a/app/app.go b/app/app.go index b89042d8e8e5..df0e2d20794b 100644 --- a/app/app.go +++ b/app/app.go @@ -9,9 +9,6 @@ import ( cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/errors" - "github.com/cosmos/cosmos-sdk/stack" sm "github.com/cosmos/cosmos-sdk/state" "github.com/cosmos/cosmos-sdk/version" ) @@ -22,112 +19,6 @@ const ( ChainKey = "chain_id" ) -// Basecoin - The ABCI application -type Basecoin struct { - *BaseApp - handler sdk.Handler - tick Ticker -} - -// Ticker - tick function -type Ticker func(sm.SimpleDB) ([]*abci.Validator, error) - -var _ abci.Application = &Basecoin{} - -// NewBasecoin - create a new instance of the basecoin application -func NewBasecoin(handler sdk.Handler, store *Store, logger log.Logger) *Basecoin { - return &Basecoin{ - BaseApp: NewBaseApp(store, logger), - handler: handler, - } -} - -// NewBasecoinTick - create a new instance of the basecoin application with tick functionality -func NewBasecoinTick(handler sdk.Handler, store *Store, logger log.Logger, tick Ticker) *Basecoin { - return &Basecoin{ - BaseApp: NewBaseApp(store, logger), - handler: handler, - tick: tick, - } -} - -// InitState - used to setup state (was SetOption) -// to be used by InitChain later -func (app *Basecoin) InitState(key string, value string) string { - module, key := splitKey(key) - state := app.state.Append() - - if module == ModuleNameBase { - if key == ChainKey { - app.info.SetChainID(state, value) - return "Success" - } - return fmt.Sprintf("Error: unknown base option: %s", key) - } - - log, err := app.handler.InitState(app.Logger(), state, module, key, value) - if err == nil { - return log - } - return "Error: " + err.Error() -} - -// DeliverTx - ABCI -func (app *Basecoin) DeliverTx(txBytes []byte) abci.Result { - tx, err := sdk.LoadTx(txBytes) - if err != nil { - return errors.Result(err) - } - - ctx := stack.NewContext( - app.GetChainID(), - app.height, - app.Logger().With("call", "delivertx"), - ) - res, err := app.handler.DeliverTx(ctx, app.state.Append(), tx) - - if err != nil { - return errors.Result(err) - } - app.AddValChange(res.Diff) - return sdk.ToABCI(res) -} - -// CheckTx - ABCI -func (app *Basecoin) CheckTx(txBytes []byte) abci.Result { - tx, err := sdk.LoadTx(txBytes) - if err != nil { - return errors.Result(err) - } - - ctx := stack.NewContext( - app.GetChainID(), - app.height, - app.Logger().With("call", "checktx"), - ) - res, err := app.handler.CheckTx(ctx, app.state.Check(), tx) - - if err != nil { - return errors.Result(err) - } - return sdk.ToABCI(res) -} - -// BeginBlock - ABCI -func (app *Basecoin) BeginBlock(req abci.RequestBeginBlock) { - // call the embeded Begin - app.BaseApp.BeginBlock(req) - - // now execute tick - if app.tick != nil { - diff, err := app.tick(app.state.Append()) - if err != nil { - panic(err) - } - app.AddValChange(diff) - } -} - /////////////////////////// Move to SDK /////// // BaseApp contains a data store and all info needed diff --git a/app/bc.go b/app/bc.go new file mode 100644 index 000000000000..a7dbf80fa464 --- /dev/null +++ b/app/bc.go @@ -0,0 +1,119 @@ +package app + +import ( + "fmt" + + abci "github.com/tendermint/abci/types" + "github.com/tendermint/tmlibs/log" + + sdk "github.com/cosmos/cosmos-sdk" + "github.com/cosmos/cosmos-sdk/errors" + "github.com/cosmos/cosmos-sdk/stack" + sm "github.com/cosmos/cosmos-sdk/state" +) + +// Basecoin - The ABCI application +type Basecoin struct { + *BaseApp + handler sdk.Handler + tick Ticker +} + +// Ticker - tick function +type Ticker func(sm.SimpleDB) ([]*abci.Validator, error) + +var _ abci.Application = &Basecoin{} + +// NewBasecoin - create a new instance of the basecoin application +func NewBasecoin(handler sdk.Handler, store *Store, logger log.Logger) *Basecoin { + return &Basecoin{ + BaseApp: NewBaseApp(store, logger), + handler: handler, + } +} + +// NewBasecoinTick - create a new instance of the basecoin application with tick functionality +func NewBasecoinTick(handler sdk.Handler, store *Store, logger log.Logger, tick Ticker) *Basecoin { + return &Basecoin{ + BaseApp: NewBaseApp(store, logger), + handler: handler, + tick: tick, + } +} + +// InitState - used to setup state (was SetOption) +// to be used by InitChain later +func (app *Basecoin) InitState(key string, value string) string { + module, key := splitKey(key) + state := app.state.Append() + + if module == ModuleNameBase { + if key == ChainKey { + app.info.SetChainID(state, value) + return "Success" + } + return fmt.Sprintf("Error: unknown base option: %s", key) + } + + log, err := app.handler.InitState(app.Logger(), state, module, key, value) + if err == nil { + return log + } + return "Error: " + err.Error() +} + +// DeliverTx - ABCI +func (app *Basecoin) DeliverTx(txBytes []byte) abci.Result { + tx, err := sdk.LoadTx(txBytes) + if err != nil { + return errors.Result(err) + } + + ctx := stack.NewContext( + app.GetChainID(), + app.height, + app.Logger().With("call", "delivertx"), + ) + res, err := app.handler.DeliverTx(ctx, app.state.Append(), tx) + + if err != nil { + return errors.Result(err) + } + app.AddValChange(res.Diff) + return sdk.ToABCI(res) +} + +// CheckTx - ABCI +func (app *Basecoin) CheckTx(txBytes []byte) abci.Result { + tx, err := sdk.LoadTx(txBytes) + if err != nil { + return errors.Result(err) + } + + ctx := stack.NewContext( + app.GetChainID(), + app.height, + app.Logger().With("call", "checktx"), + ) + res, err := app.handler.CheckTx(ctx, app.state.Check(), tx) + + if err != nil { + return errors.Result(err) + } + return sdk.ToABCI(res) +} + +// BeginBlock - ABCI +func (app *Basecoin) BeginBlock(req abci.RequestBeginBlock) { + // call the embeded Begin + app.BaseApp.BeginBlock(req) + + // now execute tick + if app.tick != nil { + diff, err := app.tick(app.state.Append()) + if err != nil { + panic(err) + } + app.AddValChange(diff) + } +} From 9d1205f8c7caa1f87c017039bcbf86ef13067f12 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 16 Oct 2017 16:26:21 +0200 Subject: [PATCH 005/117] Merged app.Store into app.BaseApp --- app/app.go | 154 +++++++++++++++++++++++++++++++------- app/app_test.go | 30 ++++---- app/app_val_test.go | 4 +- app/bc.go | 24 +++--- app/genesis_test.go | 23 ++++-- app/store.go | 175 +++----------------------------------------- state/merkle.go | 4 +- 7 files changed, 183 insertions(+), 231 deletions(-) diff --git a/app/app.go b/app/app.go index df0e2d20794b..aa06cce8eae9 100644 --- a/app/app.go +++ b/app/app.go @@ -3,12 +3,17 @@ package app import ( "bytes" "fmt" + "path" + "path/filepath" "strings" abci "github.com/tendermint/abci/types" + "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" + dbm "github.com/tendermint/tmlibs/db" "github.com/tendermint/tmlibs/log" + "github.com/cosmos/cosmos-sdk/errors" sm "github.com/cosmos/cosmos-sdk/state" "github.com/cosmos/cosmos-sdk/version" ) @@ -19,16 +24,14 @@ const ( ChainKey = "chain_id" ) -/////////////////////////// Move to SDK /////// - // BaseApp contains a data store and all info needed // to perform queries and handshakes. // // It should be embeded in another struct for CheckTx, // DeliverTx and initializing state from the genesis. type BaseApp struct { - info *sm.ChainState - state *Store + info *sm.ChainState + *sm.State pending []*abci.Validator height uint64 @@ -36,22 +39,22 @@ type BaseApp struct { } // NewBaseApp creates a data store to handle queries -func NewBaseApp(store *Store, logger log.Logger) *BaseApp { - return &BaseApp{ +func NewBaseApp(dbName string, cacheSize int, logger log.Logger) (*BaseApp, error) { + state, err := loadState(dbName, cacheSize) + if err != nil { + return nil, err + } + app := &BaseApp{ info: sm.NewChainState(), - state: store, + State: state, logger: logger, } + return app, nil } // GetChainID returns the currently stored chain func (app *BaseApp) GetChainID() string { - return app.info.GetChainID(app.state.Committed()) -} - -// GetState returns the delivertx state, should be removed -func (app *BaseApp) GetState() sm.SimpleDB { - return app.state.Append() + return app.info.GetChainID(app.Committed()) } // Logger returns the application base logger @@ -59,17 +62,27 @@ func (app *BaseApp) Logger() log.Logger { return app.logger } -// Info - ABCI +// Hash gets the last hash stored in the database +func (app *BaseApp) Hash() []byte { + return app.State.LatestHash() +} + +// Info implements abci.Application. It returns the height and hash, +// as well as the abci name and version. +// +// The height is the block that holds the transactions, not the apphash itself. func (app *BaseApp) Info(req abci.RequestInfo) abci.ResponseInfo { - resp := app.state.Info() - app.logger.Debug("Info", - "height", resp.LastBlockHeight, - "hash", fmt.Sprintf("%X", resp.LastBlockAppHash)) - app.height = resp.LastBlockHeight + hash := app.Hash() + + app.logger.Info("Info synced", + "height", app.height, + "hash", fmt.Sprintf("%X", hash)) + return abci.ResponseInfo{ + // TODO Data: fmt.Sprintf("Basecoin v%v", version.Version), - LastBlockHeight: resp.LastBlockHeight, - LastBlockAppHash: resp.LastBlockAppHash, + LastBlockHeight: app.height, + LastBlockAppHash: hash, } } @@ -86,17 +99,66 @@ func (app *BaseApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQue return } - return app.state.Query(reqQuery) + // set the query response height to current + tree := app.State.Committed() + + height := reqQuery.Height + if height == 0 { + // TODO: once the rpc actually passes in non-zero + // heights we can use to query right after a tx + // 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.height + // } + } + resQuery.Height = height + + switch reqQuery.Path { + case "/store", "/key": // Get by key + key := reqQuery.Data // Data holds the key bytes + resQuery.Key = key + if reqQuery.Prove { + value, proof, err := tree.GetVersionedWithProof(key, height) + if err != nil { + resQuery.Log = err.Error() + break + } + resQuery.Value = value + resQuery.Proof = proof.Bytes() + } else { + value := tree.Get(key) + resQuery.Value = value + } + + default: + resQuery.Code = abci.CodeType_UnknownRequest + resQuery.Log = cmn.Fmt("Unexpected Query path: %v", reqQuery.Path) + } + return } -// Commit - ABCI +// Commit implements abci.Application func (app *BaseApp) Commit() (res abci.Result) { - // Commit state - res = app.state.Commit() - if res.IsErr() { - cmn.PanicSanity("Error getting hash: " + res.Error()) + app.height++ + + hash, err := app.State.Commit(app.height) + if err != nil { + // die if we can't commit, not to recover + panic(err) + } + app.logger.Debug("Commit synced", + "height", app.height, + "hash", fmt.Sprintf("%X", hash), + ) + + if app.State.Size() == 0 { + return abci.NewResultOK(nil, "Empty hash for empty tree") } - return res + return abci.NewResultOK(hash, "") } // InitChain - ABCI @@ -152,3 +214,39 @@ func splitKey(key string) (string, string) { } return ModuleNameBase, key } + +func loadState(dbName string, cacheSize int) (*sm.State, error) { + // memory backed case, just for testing + if dbName == "" { + tree := iavl.NewVersionedTree(0, dbm.NewMemDB()) + return sm.NewState(tree), nil + } + + // Expand the path fully + dbPath, err := filepath.Abs(dbName) + if err != nil { + return nil, errors.ErrInternal("Invalid Database Name") + } + + // Some external calls accidently add a ".db", which is now removed + dbPath = strings.TrimSuffix(dbPath, path.Ext(dbPath)) + + // Split the database name into it's components (dir, name) + 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()) + } + } + + return sm.NewState(tree), nil +} diff --git a/app/app_test.go b/app/app_test.go index 1cf983459510..bcf32dfbeb92 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -112,14 +112,15 @@ func (at *appTest) reset() { // Note: switch logger if you want to get more info logger := log.TestingLogger() // logger := log.NewTracingLogger(log.NewTMLogger(os.Stdout)) - store, err := NewStore("", 0, logger.With("module", "store")) - require.Nil(at.t, err, "%+v", err) - at.app = NewBasecoin( + var err error + at.app, err = NewBasecoin( DefaultHandler("mycoin"), - store, + "", + 0, logger.With("module", "app"), ) + require.Nil(at.t, err, "%+v", err) res := at.app.InitState("base/chain_id", at.chainID) require.EqualValues(at.t, res, "Success") @@ -146,9 +147,9 @@ func getAddr(addr []byte, state state.SimpleDB) (coin.Coins, error) { func (at *appTest) exec(t *testing.T, tx sdk.Tx, checkTx bool) (res abci.Result, diffIn, diffOut coin.Coins) { require := require.New(t) - initBalIn, err := getBalance(at.acctIn.Actor(), at.app.GetState()) + initBalIn, err := getBalance(at.acctIn.Actor(), at.app.Append()) require.Nil(err, "%+v", err) - initBalOut, err := getBalance(at.acctOut.Actor(), at.app.GetState()) + initBalOut, err := getBalance(at.acctOut.Actor(), at.app.Append()) require.Nil(err, "%+v", err) txBytes := wire.BinaryBytes(tx) @@ -158,9 +159,9 @@ func (at *appTest) exec(t *testing.T, tx sdk.Tx, checkTx bool) (res abci.Result, res = at.app.DeliverTx(txBytes) } - endBalIn, err := getBalance(at.acctIn.Actor(), at.app.GetState()) + endBalIn, err := getBalance(at.acctIn.Actor(), at.app.Append()) require.Nil(err, "%+v", err) - endBalOut, err := getBalance(at.acctOut.Actor(), at.app.GetState()) + endBalOut, err := getBalance(at.acctOut.Actor(), at.app.Append()) require.Nil(err, "%+v", err) return res, endBalIn.Minus(initBalIn), endBalOut.Minus(initBalOut) } @@ -172,14 +173,13 @@ func TestInitState(t *testing.T) { require := require.New(t) logger := log.TestingLogger() - store, err := NewStore("", 0, logger.With("module", "store")) - require.Nil(err, "%+v", err) - - app := NewBasecoin( + app, err := NewBasecoin( DefaultHandler("atom"), - store, + "", + 0, logger.With("module", "app"), ) + require.Nil(err, "%+v", err) //testing ChainID chainID := "testChain" @@ -194,7 +194,7 @@ func TestInitState(t *testing.T) { require.EqualValues(res, "Success") // make sure it is set correctly, with some balance - coins, err := getBalance(acct.Actor(), app.GetState()) + coins, err := getBalance(acct.Actor(), app.Append()) require.Nil(err) assert.Equal(bal, coins) @@ -221,7 +221,7 @@ func TestInitState(t *testing.T) { res = app.InitState("coin/account", unsortAcc) require.EqualValues(res, "Success") - coins, err = getAddr(unsortAddr, app.GetState()) + coins, err = getAddr(unsortAddr, app.Append()) require.Nil(err) assert.True(coins.IsValid()) assert.Equal(unsortCoins, coins) diff --git a/app/app_val_test.go b/app/app_val_test.go index 95ea77674ab4..e85868b8abfd 100644 --- a/app/app_val_test.go +++ b/app/app_val_test.go @@ -39,9 +39,9 @@ func TestEndBlock(t *testing.T) { assert, require := assert.New(t), require.New(t) logger := log.NewNopLogger() - store := MockStore() handler := base.ValSetHandler{} - app := NewBasecoin(handler, store, logger) + app, err := NewBasecoin(handler, "", 0, logger) + require.Nil(err, "%+v", err) val1 := makeVal() val2 := makeVal() diff --git a/app/bc.go b/app/bc.go index a7dbf80fa464..f681a7c52be7 100644 --- a/app/bc.go +++ b/app/bc.go @@ -25,27 +25,31 @@ type Ticker func(sm.SimpleDB) ([]*abci.Validator, error) var _ abci.Application = &Basecoin{} // NewBasecoin - create a new instance of the basecoin application -func NewBasecoin(handler sdk.Handler, store *Store, logger log.Logger) *Basecoin { - return &Basecoin{ - BaseApp: NewBaseApp(store, logger), +func NewBasecoin(handler sdk.Handler, dbName string, cacheSize int, logger log.Logger) (*Basecoin, error) { + base, err := NewBaseApp(dbName, cacheSize, logger) + app := &Basecoin{ + BaseApp: base, handler: handler, } + return app, err } // NewBasecoinTick - create a new instance of the basecoin application with tick functionality -func NewBasecoinTick(handler sdk.Handler, store *Store, logger log.Logger, tick Ticker) *Basecoin { - return &Basecoin{ - BaseApp: NewBaseApp(store, logger), +func NewBasecoinTick(handler sdk.Handler, tick Ticker, dbName string, cacheSize int, logger log.Logger) (*Basecoin, error) { + base, err := NewBaseApp(dbName, cacheSize, logger) + app := &Basecoin{ + BaseApp: base, handler: handler, tick: tick, } + return app, err } // InitState - used to setup state (was SetOption) // to be used by InitChain later func (app *Basecoin) InitState(key string, value string) string { module, key := splitKey(key) - state := app.state.Append() + state := app.Append() if module == ModuleNameBase { if key == ChainKey { @@ -74,7 +78,7 @@ func (app *Basecoin) DeliverTx(txBytes []byte) abci.Result { app.height, app.Logger().With("call", "delivertx"), ) - res, err := app.handler.DeliverTx(ctx, app.state.Append(), tx) + res, err := app.handler.DeliverTx(ctx, app.Append(), tx) if err != nil { return errors.Result(err) @@ -95,7 +99,7 @@ func (app *Basecoin) CheckTx(txBytes []byte) abci.Result { app.height, app.Logger().With("call", "checktx"), ) - res, err := app.handler.CheckTx(ctx, app.state.Check(), tx) + res, err := app.handler.CheckTx(ctx, app.Check(), tx) if err != nil { return errors.Result(err) @@ -110,7 +114,7 @@ func (app *Basecoin) BeginBlock(req abci.RequestBeginBlock) { // now execute tick if app.tick != nil { - diff, err := app.tick(app.state.Append()) + diff, err := app.tick(app.Append()) if err != nil { panic(err) } diff --git a/app/genesis_test.go b/app/genesis_test.go index 2b76cd7f9514..ccb1229dcc97 100644 --- a/app/genesis_test.go +++ b/app/genesis_test.go @@ -19,9 +19,12 @@ const genesisAcctFilepath = "./testdata/genesis2.json" func TestLoadGenesisDoNotFailIfAppOptionsAreMissing(t *testing.T) { logger := log.TestingLogger() - store, err := NewStore("", 0, logger) + app, err := NewBasecoin(DefaultHandler("mycoin"), + "", + 0, + logger) require.Nil(t, err, "%+v", err) - app := NewBasecoin(DefaultHandler("mycoin"), store, logger) + err = app.LoadGenesis("./testdata/genesis3.json") require.Nil(t, err, "%+v", err) } @@ -30,10 +33,12 @@ func TestLoadGenesis(t *testing.T) { assert, require := assert.New(t), require.New(t) logger := log.TestingLogger() - store, err := NewStore("", 0, logger) + app, err := NewBasecoin(DefaultHandler("mycoin"), + "", + 0, + logger) require.Nil(err, "%+v", err) - app := NewBasecoin(DefaultHandler("mycoin"), store, logger) err = app.LoadGenesis(genesisFilepath) require.Nil(err, "%+v", err) @@ -43,7 +48,7 @@ func TestLoadGenesis(t *testing.T) { // and check the account info - previously calculated values addr, _ := hex.DecodeString("eb98e0688217cfdeb70eddf4b33cdcc37fc53197") - coins, err := getAddr(addr, app.GetState()) + coins, err := getAddr(addr, app.Append()) require.Nil(err) assert.True(coins.IsPositive()) @@ -62,10 +67,12 @@ func TestLoadGenesisAccountAddress(t *testing.T) { assert, require := assert.New(t), require.New(t) logger := log.TestingLogger() - store, err := NewStore("", 0, logger) + app, err := NewBasecoin(DefaultHandler("mycoin"), + "", + 0, + logger) require.Nil(err, "%+v", err) - app := NewBasecoin(DefaultHandler("mycoin"), store, logger) err = app.LoadGenesis(genesisAcctFilepath) require.Nil(err, "%+v", err) @@ -93,7 +100,7 @@ func TestLoadGenesisAccountAddress(t *testing.T) { for i, tc := range cases { addr, err := hex.DecodeString(tc.addr) require.Nil(err, tc.addr) - coins, err := getAddr(addr, app.GetState()) + coins, err := getAddr(addr, app.Append()) require.Nil(err, "%+v", err) if !tc.exists { assert.True(coins.IsZero(), "%d", i) diff --git a/app/store.go b/app/store.go index 05843f64ff9c..ff33d7dbcbdd 100644 --- a/app/store.go +++ b/app/store.go @@ -1,168 +1,11 @@ package app -import ( - "fmt" - "path" - "path/filepath" - "strings" - - "github.com/pkg/errors" - abci "github.com/tendermint/abci/types" - "github.com/tendermint/iavl" - cmn "github.com/tendermint/tmlibs/common" - dbm "github.com/tendermint/tmlibs/db" - "github.com/tendermint/tmlibs/log" - - "github.com/cosmos/cosmos-sdk/state" -) - -// Store contains the merkle tree, and all info to handle abci requests -type Store struct { - state.State - height uint64 - logger log.Logger -} - -// MockStore returns an in-memory store only intended for testing -func MockStore() *Store { - res, err := NewStore("", 0, log.NewNopLogger()) - if err != nil { - // should never happen, abort test if it does - panic(err) - } - return res -} - -// NewStore initializes an in-memory iavl.VersionedTree, or attempts to load a -// persistant tree from disk -func NewStore(dbName string, cacheSize int, logger log.Logger) (*Store, error) { - // memory backed case, just for testing - if dbName == "" { - tree := iavl.NewVersionedTree( - 0, - dbm.NewMemDB(), - ) - store := &Store{ - State: state.NewState(tree), - logger: logger, - } - return store, nil - } - - // Expand the path fully - dbPath, err := filepath.Abs(dbName) - if err != nil { - return nil, errors.Wrap(err, "Invalid Database Name") - } - - // Some external calls accidently add a ".db", which is now removed - dbPath = strings.TrimSuffix(dbPath, path.Ext(dbPath)) - - // Split the database name into it's components (dir, name) - 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 { - logger.Info("no existing db, creating new db") - } else { - logger.Info("loading existing db") - if err = tree.Load(); err != nil { - return nil, errors.Wrap(err, "Loading tree") - } - } - - res := &Store{ - State: state.NewState(tree), - logger: logger, - } - res.height = res.State.LatestHeight() - return res, nil -} - -// Hash gets the last hash stored in the database -func (s *Store) Hash() []byte { - return s.State.LatestHash() -} - -// Info implements abci.Application. It returns the height, hash and size (in the data). -// The height is the block that holds the transactions, not the apphash itself. -func (s *Store) Info() abci.ResponseInfo { - s.logger.Info("Info synced", - "height", s.height, - "hash", fmt.Sprintf("%X", s.Hash())) - return abci.ResponseInfo{ - Data: cmn.Fmt("size:%v", s.State.Size()), - LastBlockHeight: s.height, - LastBlockAppHash: s.Hash(), - } -} - -// Commit implements abci.Application -func (s *Store) Commit() abci.Result { - s.height++ - - hash, err := s.State.Commit(s.height) - if err != nil { - return abci.NewError(abci.CodeType_InternalError, err.Error()) - } - s.logger.Debug("Commit synced", - "height", s.height, - "hash", fmt.Sprintf("%X", hash), - ) - - if s.State.Size() == 0 { - return abci.NewResultOK(nil, "Empty hash for empty tree") - } - return abci.NewResultOK(hash, "") -} - -// Query implements abci.Application -func (s *Store) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) { - // set the query response height to current - tree := s.State.Committed() - - height := reqQuery.Height - if height == 0 { - // TODO: once the rpc actually passes in non-zero - // heights we can use to query right after a tx - // we must retrun most recent, even if apphash - // is not yet in the blockchain - - // if tree.Tree.VersionExists(s.height - 1) { - // height = s.height - 1 - // } else { - height = s.height - // } - } - resQuery.Height = height - - switch reqQuery.Path { - case "/store", "/key": // Get by key - key := reqQuery.Data // Data holds the key bytes - resQuery.Key = key - if reqQuery.Prove { - value, proof, err := tree.GetVersionedWithProof(key, height) - if err != nil { - resQuery.Log = err.Error() - break - } - resQuery.Value = value - resQuery.Proof = proof.Bytes() - } else { - value := tree.Get(key) - resQuery.Value = value - } - - default: - resQuery.Code = abci.CodeType_UnknownRequest - resQuery.Log = cmn.Fmt("Unexpected Query path: %v", reqQuery.Path) - } - return -} +// // MockStore returns an in-memory store only intended for testing +// func MockStore() *Store { +// res, err := NewStore("", 0, log.NewNopLogger()) +// if err != nil { +// // should never happen, abort test if it does +// panic(err) +// } +// return res +// } diff --git a/state/merkle.go b/state/merkle.go index 14ad5300248f..ec81c6d002ff 100644 --- a/state/merkle.go +++ b/state/merkle.go @@ -11,9 +11,9 @@ type State struct { persistent bool } -func NewState(tree *iavl.VersionedTree) State { +func NewState(tree *iavl.VersionedTree) *State { base := NewBonsai(tree) - return State{ + return &State{ committed: base, deliverTx: base.Checkpoint(), checkTx: base.Checkpoint(), From c1d36eeb217276352d68afad158d6b34e273f7b9 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 16 Oct 2017 16:56:20 +0200 Subject: [PATCH 006/117] Fixed all tests --- app/app.go | 20 +++++++------- app/bc.go | 4 +-- benchmarks/app_test.go | 23 +++++++--------- client/query_test.go | 4 +-- .../counter/plugins/counter/counter_test.go | 9 +++---- server/commands/start.go | 26 +++++++++---------- 6 files changed, 41 insertions(+), 45 deletions(-) diff --git a/app/app.go b/app/app.go index aa06cce8eae9..47fb34f311fe 100644 --- a/app/app.go +++ b/app/app.go @@ -33,9 +33,13 @@ type BaseApp struct { info *sm.ChainState *sm.State + // cached validator changes from DeliverTx pending []*abci.Validator - height uint64 - logger log.Logger + + // height is last committed block, DeliverTx is the next one + height uint64 + + logger log.Logger } // NewBaseApp creates a data store to handle queries @@ -45,8 +49,9 @@ func NewBaseApp(dbName string, cacheSize int, logger log.Logger) (*BaseApp, erro return nil, err } app := &BaseApp{ - info: sm.NewChainState(), State: state, + height: state.LatestHeight(), + info: sm.NewChainState(), logger: logger, } return app, nil @@ -163,14 +168,10 @@ func (app *BaseApp) Commit() (res abci.Result) { // InitChain - ABCI func (app *BaseApp) InitChain(req abci.RequestInitChain) { - // for _, plugin := range app.plugins.GetList() { - // plugin.InitChain(app.state, validators) - // } } // BeginBlock - ABCI func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) { - app.height++ } // EndBlock - ABCI @@ -182,6 +183,9 @@ func (app *BaseApp) EndBlock(height uint64) (res abci.ResponseEndBlock) { return } +// AddValChange is meant to be called by apps on DeliverTx +// results, this is added to the cache for the endblock +// changeset func (app *BaseApp) AddValChange(diffs []*abci.Validator) { for _, d := range diffs { idx := pubKeyIndex(d, app.pending) @@ -203,8 +207,6 @@ func pubKeyIndex(val *abci.Validator, list []*abci.Validator) int { return -1 } -//TODO move split key to tmlibs? - // Splits the string at the first '/'. // if there are none, assign default module ("base"). func splitKey(key string) (string, string) { diff --git a/app/bc.go b/app/bc.go index f681a7c52be7..183e48bf4310 100644 --- a/app/bc.go +++ b/app/bc.go @@ -75,7 +75,7 @@ func (app *Basecoin) DeliverTx(txBytes []byte) abci.Result { ctx := stack.NewContext( app.GetChainID(), - app.height, + app.height+1, app.Logger().With("call", "delivertx"), ) res, err := app.handler.DeliverTx(ctx, app.Append(), tx) @@ -96,7 +96,7 @@ func (app *Basecoin) CheckTx(txBytes []byte) abci.Result { ctx := stack.NewContext( app.GetChainID(), - app.height, + app.height+1, app.Logger().With("call", "checktx"), ) res, err := app.handler.CheckTx(ctx, app.Check(), tx) diff --git a/benchmarks/app_test.go b/benchmarks/app_test.go index acbf182f789a..a849120156e1 100644 --- a/benchmarks/app_test.go +++ b/benchmarks/app_test.go @@ -53,25 +53,22 @@ func NewBenchApp(h sdk.Handler, chainID string, n int, // logger := log.NewFilter(log.NewTMLogger(os.Stdout), log.AllowError()) // logger = log.NewTracingLogger(logger) - // TODO: disk writing - var store *app.Store - var err error - + dbDir, cache := "", 0 if persist { - tmpDir, _ := ioutil.TempDir("", "bc-app-benchmark") - store, err = app.NewStore(tmpDir, 500, logger) - } else { - store, err = app.NewStore("", 0, logger) - } - if err != nil { - panic(err) + dbDir, _ = ioutil.TempDir("", "bc-app-benchmark") + cache = 500 } - app := app.NewBasecoin( + app, err := app.NewBasecoin( h, - store, + dbDir, + cache, logger.With("module", "app"), ) + if err != nil { + panic(err) + } + res := app.InitState("base/chain_id", chainID) if res != "Success" { panic("cannot set chain") diff --git a/client/query_test.go b/client/query_test.go index 5d6a5bf5c453..fe8ee41801cf 100644 --- a/client/query_test.go +++ b/client/query_test.go @@ -26,11 +26,11 @@ var node *nm.Node func TestMain(m *testing.M) { logger := log.TestingLogger() - store, err := app.NewStore("", 0, logger) + app, err := app.NewBasecoin(eyes.NewHandler(), "", 0, logger) if err != nil { panic(err) } - app := app.NewBasecoin(eyes.NewHandler(), store, logger) + node = rpctest.StartTendermint(app) code := m.Run() diff --git a/examples/counter/plugins/counter/counter_test.go b/examples/counter/plugins/counter/counter_test.go index 50af3b3d9b9f..b9630706efce 100644 --- a/examples/counter/plugins/counter/counter_test.go +++ b/examples/counter/plugins/counter/counter_test.go @@ -27,15 +27,14 @@ func TestCounterPlugin(t *testing.T) { logger := log.TestingLogger() // logger := log.NewTracingLogger(log.NewTMLogger(os.Stdout)) - store, err := app.NewStore("", 0, logger.With("module", "store")) - require.Nil(err, "%+v", err) - h := NewHandler("gold") - bcApp := app.NewBasecoin( + bcApp, err := app.NewBasecoin( h, - store, + "", + 0, logger.With("module", "app"), ) + require.Nil(err, "%+v", err) bcApp.InitState("base/chain_id", chainID) // Account initialization diff --git a/server/commands/start.go b/server/commands/start.go index 494660300a98..825e9bfd35f3 100644 --- a/server/commands/start.go +++ b/server/commands/start.go @@ -74,38 +74,36 @@ func tickStartCmd(tick app.Ticker) func(cmd *cobra.Command, args []string) error return func(cmd *cobra.Command, args []string) error { rootDir := viper.GetString(cli.HomeFlag) - store, err := app.NewStore( + // Create Basecoin app + basecoinApp, err := app.NewBasecoinTick( + Handler, + tick, path.Join(rootDir, "data", "merkleeyes.db"), EyesCacheSize, - logger.With("module", "store"), - ) + logger.With("module", "app")) if err != nil { return err } - - // Create Basecoin app - basecoinApp := app.NewBasecoinTick(Handler, store, logger.With("module", "app"), tick) - return start(rootDir, store, basecoinApp) + return start(rootDir, basecoinApp) } } func startCmd(cmd *cobra.Command, args []string) error { rootDir := viper.GetString(cli.HomeFlag) - store, err := app.NewStore( + // Create Basecoin app + basecoinApp, err := app.NewBasecoin( + Handler, path.Join(rootDir, "data", "merkleeyes.db"), EyesCacheSize, - logger.With("module", "store"), - ) + logger.With("module", "app")) if err != nil { return err } - // Create Basecoin app - basecoinApp := app.NewBasecoin(Handler, store, logger.With("module", "app")) - return start(rootDir, store, basecoinApp) + return start(rootDir, basecoinApp) } -func start(rootDir string, store *app.Store, basecoinApp *app.Basecoin) error { +func start(rootDir string, basecoinApp *app.Basecoin) error { // if chain_id has not been set yet, load the genesis. // else, assume it's been loaded From df0f3a22da2c865cd7aeefbfa237081490934a13 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 16 Oct 2017 17:34:29 +0200 Subject: [PATCH 007/117] Separate genesis parsing from basecoin --- app/app.go | 13 +---- app/app_test.go | 33 ++++++------ app/bc.go | 35 +++++++++---- app/genesis.go | 52 +++++++++++++++---- benchmarks/app_test.go | 8 +-- .../counter/plugins/counter/counter_test.go | 7 +-- 6 files changed, 93 insertions(+), 55 deletions(-) diff --git a/app/app.go b/app/app.go index 47fb34f311fe..fcac9cb9fe9b 100644 --- a/app/app.go +++ b/app/app.go @@ -20,8 +20,7 @@ import ( //nolint const ( - ModuleNameBase = "base" - ChainKey = "chain_id" + ChainKey = "chain_id" ) // BaseApp contains a data store and all info needed @@ -207,16 +206,6 @@ func pubKeyIndex(val *abci.Validator, list []*abci.Validator) int { return -1 } -// 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) - return keyParts[0], keyParts[1] - } - return ModuleNameBase, key -} - func loadState(dbName string, cacheSize int) (*sm.State, error) { // memory backed case, just for testing if dbName == "" { diff --git a/app/app_test.go b/app/app_test.go index bcf32dfbeb92..5be1320daf95 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -100,8 +100,8 @@ func (at *appTest) feeTx(coins coin.Coins, toll coin.Coin, sequence uint32) sdk. // set the account on the app through InitState func (at *appTest) initAccount(acct *coin.AccountWithKey) { - res := at.app.InitState("coin/account", acct.MakeOption()) - require.EqualValues(at.t, res, "Success") + _, err := at.app.InitState("coin", "account", acct.MakeOption()) + require.Nil(at.t, err, "%+v", err) } // reset the in and out accs to be one account each with 7mycoin @@ -122,8 +122,8 @@ func (at *appTest) reset() { ) require.Nil(at.t, err, "%+v", err) - res := at.app.InitState("base/chain_id", at.chainID) - require.EqualValues(at.t, res, "Success") + _, err = at.app.InitState("base", "chain_id", at.chainID) + require.Nil(at.t, err, "%+v", err) at.initAccount(at.acctIn) at.initAccount(at.acctOut) @@ -183,15 +183,15 @@ func TestInitState(t *testing.T) { //testing ChainID chainID := "testChain" - res := app.InitState("base/chain_id", chainID) + _, err = app.InitState("base", "chain_id", chainID) + require.Nil(err, "%+v", err) assert.EqualValues(app.GetChainID(), chainID) - assert.EqualValues(res, "Success") // make a nice account... bal := coin.Coins{{"atom", 77}, {"eth", 12}} acct := coin.NewAccountWithKey(bal) - res = app.InitState("coin/account", acct.MakeOption()) - require.EqualValues(res, "Success") + _, err = app.InitState("coin", "account", acct.MakeOption()) + require.Nil(err, "%+v", err) // make sure it is set correctly, with some balance coins, err := getBalance(acct.Actor(), app.Append()) @@ -218,23 +218,22 @@ func TestInitState(t *testing.T) { } ] }` - res = app.InitState("coin/account", unsortAcc) - require.EqualValues(res, "Success") + _, err = app.InitState("coin", "account", unsortAcc) + require.Nil(err, "%+v", err) coins, err = getAddr(unsortAddr, app.Append()) require.Nil(err) assert.True(coins.IsValid()) assert.Equal(unsortCoins, coins) - res = app.InitState("base/dslfkgjdas", "") - assert.NotEqual(res, "Success") - - res = app.InitState("dslfkgjdas", "") - assert.NotEqual(res, "Success") + _, err = app.InitState("base", "dslfkgjdas", "") + require.NotNil(err) - res = app.InitState("dslfkgjdas/szfdjzs", "") - assert.NotEqual(res, "Success") + _, err = app.InitState("", "dslfkgjdas", "") + require.NotNil(err) + _, err = app.InitState("dslfkgjdas", "szfdjzs", "") + require.NotNil(err) } // Test CheckTx and DeliverTx with insufficient and sufficient balance diff --git a/app/bc.go b/app/bc.go index 183e48bf4310..b876156d895e 100644 --- a/app/bc.go +++ b/app/bc.go @@ -47,23 +47,18 @@ func NewBasecoinTick(handler sdk.Handler, tick Ticker, dbName string, cacheSize // InitState - used to setup state (was SetOption) // to be used by InitChain later -func (app *Basecoin) InitState(key string, value string) string { - module, key := splitKey(key) +func (app *Basecoin) InitState(module, key, value string) (string, error) { state := app.Append() if module == ModuleNameBase { if key == ChainKey { app.info.SetChainID(state, value) - return "Success" + return "Success", nil } - return fmt.Sprintf("Error: unknown base option: %s", key) + return "", fmt.Errorf("unknown base option: %s", key) } - log, err := app.handler.InitState(app.Logger(), state, module, key, value) - if err == nil { - return log - } - return "Error: " + err.Error() + return app.handler.InitState(app.Logger(), state, module, key, value) } // DeliverTx - ABCI @@ -121,3 +116,25 @@ func (app *Basecoin) BeginBlock(req abci.RequestBeginBlock) { app.AddValChange(diff) } } + +// LoadGenesis parses the genesis file and sets the initial +// state based on that +func (app *Basecoin) LoadGenesis(filePath string) error { + init, err := GetInitialState(filePath) + if err != nil { + return err + } + + // execute all the genesis init options + // abort on any error + fmt.Printf("%#v\n", init) + for _, mkv := range init { + log, _ := app.InitState(mkv.Module, mkv.Key, mkv.Value) + // TODO: error out on bad options?? + // if err != nil { + // return err + // } + app.Logger().Info(log) + } + return nil +} diff --git a/app/genesis.go b/app/genesis.go index 81d99fead9dd..ceb0e1156ef6 100644 --- a/app/genesis.go +++ b/app/genesis.go @@ -2,33 +2,55 @@ package app import ( "encoding/json" + "strings" "github.com/pkg/errors" cmn "github.com/tendermint/tmlibs/common" ) -// LoadGenesis - Load the genesis file into memory -func (app *Basecoin) LoadGenesis(path string) error { +//nolint +const ( + ModuleNameBase = "base" +) + +// InitState just holds module/key/value triples from +// parsing the genesis file +type InitState struct { + Module string + Key string + Value string +} + +// GetInitialState parses the genesis file in a format +// that can easily be handed into InitState modules +func GetInitialState(path string) ([]InitState, error) { genDoc, err := loadGenesis(path) if err != nil { - return err + return nil, err } - // set chain_id - app.InitState("base/chain_id", genDoc.ChainID) + opts := genDoc.AppOptions + cnt := 1 + len(opts.Accounts) + len(opts.pluginOptions) + res := make([]InitState, cnt) + + res[0] = InitState{ModuleNameBase, ChainKey, genDoc.ChainID} + i := 1 // set accounts - for _, acct := range genDoc.AppOptions.Accounts { - _ = app.InitState("coin/account", string(acct)) + for _, acct := range opts.Accounts { + res[i] = InitState{"coin", "account", string(acct)} + i++ } // set plugin options - for _, kv := range genDoc.AppOptions.pluginOptions { - _ = app.InitState(kv.Key, kv.Value) + for _, kv := range opts.pluginOptions { + module, key := splitKey(kv.Key) + res[i] = InitState{module, key, kv.Value} + i++ } - return nil + return res, nil } type keyValue struct { @@ -97,3 +119,13 @@ func parseGenesisList(kvzIn []json.RawMessage) (kvz []keyValue, err error) { } return kvz, nil } + +// 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) + return keyParts[0], keyParts[1] + } + return ModuleNameBase, key +} diff --git a/benchmarks/app_test.go b/benchmarks/app_test.go index a849120156e1..690727e74a62 100644 --- a/benchmarks/app_test.go +++ b/benchmarks/app_test.go @@ -69,8 +69,8 @@ func NewBenchApp(h sdk.Handler, chainID string, n int, panic(err) } - res := app.InitState("base/chain_id", chainID) - if res != "Success" { + _, err = app.InitState("base", "chain_id", chainID) + if err != nil { panic("cannot set chain") } @@ -79,8 +79,8 @@ func NewBenchApp(h sdk.Handler, chainID string, n int, accts := make([]*coin.AccountWithKey, n) for i := 0; i < n; i++ { accts[i] = coin.NewAccountWithKey(money) - res := app.InitState("coin/account", accts[i].MakeOption()) - if res != "Success" { + _, err = app.InitState("coin", "account", accts[i].MakeOption()) + if err != nil { panic("can't set account") } } diff --git a/examples/counter/plugins/counter/counter_test.go b/examples/counter/plugins/counter/counter_test.go index b9630706efce..a10e0afbbb24 100644 --- a/examples/counter/plugins/counter/counter_test.go +++ b/examples/counter/plugins/counter/counter_test.go @@ -35,13 +35,14 @@ func TestCounterPlugin(t *testing.T) { logger.With("module", "app"), ) require.Nil(err, "%+v", err) - bcApp.InitState("base/chain_id", chainID) + _, err = bcApp.InitState("base", "chain_id", chainID) + require.Nil(err, "%+v", err) // Account initialization bal := coin.Coins{{"", 1000}, {"gold", 1000}} acct := coin.NewAccountWithKey(bal) - log := bcApp.InitState("coin/account", acct.MakeOption()) - require.Equal("Success", log) + _, err = bcApp.InitState("coin", "account", acct.MakeOption()) + require.Nil(err, "%+v", err) // Deliver a CounterTx DeliverCounterTx := func(valid bool, counterFee coin.Coins, sequence uint32) abci.Result { From adab86c94747d3d65c341789616c45aa4e56db39 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 16 Oct 2017 18:14:55 +0200 Subject: [PATCH 008/117] Cleanup --- app/app.go | 10 +++++++--- app/bc.go | 7 +++++-- app/store.go | 11 ----------- 3 files changed, 12 insertions(+), 16 deletions(-) delete mode 100644 app/store.go diff --git a/app/app.go b/app/app.go index fcac9cb9fe9b..c8a03c6fe2fa 100644 --- a/app/app.go +++ b/app/app.go @@ -15,7 +15,6 @@ import ( "github.com/cosmos/cosmos-sdk/errors" sm "github.com/cosmos/cosmos-sdk/state" - "github.com/cosmos/cosmos-sdk/version" ) //nolint @@ -29,6 +28,10 @@ const ( // It should be embeded in another struct for CheckTx, // DeliverTx and initializing state from the genesis. type BaseApp struct { + // Name is what is returned from info + Name string + + // this is the database state info *sm.ChainState *sm.State @@ -42,12 +45,13 @@ type BaseApp struct { } // NewBaseApp creates a data store to handle queries -func NewBaseApp(dbName string, cacheSize int, logger log.Logger) (*BaseApp, error) { +func NewBaseApp(appName, dbName string, cacheSize int, logger log.Logger) (*BaseApp, error) { state, err := loadState(dbName, cacheSize) if err != nil { return nil, err } app := &BaseApp{ + Name: appName, State: state, height: state.LatestHeight(), info: sm.NewChainState(), @@ -84,7 +88,7 @@ func (app *BaseApp) Info(req abci.RequestInfo) abci.ResponseInfo { return abci.ResponseInfo{ // TODO - Data: fmt.Sprintf("Basecoin v%v", version.Version), + Data: app.Name, LastBlockHeight: app.height, LastBlockAppHash: hash, } diff --git a/app/bc.go b/app/bc.go index b876156d895e..81e559f4a1ea 100644 --- a/app/bc.go +++ b/app/bc.go @@ -4,6 +4,7 @@ import ( "fmt" abci "github.com/tendermint/abci/types" + "github.com/tendermint/abci/version" "github.com/tendermint/tmlibs/log" sdk "github.com/cosmos/cosmos-sdk" @@ -26,7 +27,8 @@ var _ abci.Application = &Basecoin{} // NewBasecoin - create a new instance of the basecoin application func NewBasecoin(handler sdk.Handler, dbName string, cacheSize int, logger log.Logger) (*Basecoin, error) { - base, err := NewBaseApp(dbName, cacheSize, logger) + appName := fmt.Sprintf("Basecoin v%v", version.Version) + base, err := NewBaseApp(appName, dbName, cacheSize, logger) app := &Basecoin{ BaseApp: base, handler: handler, @@ -36,7 +38,8 @@ func NewBasecoin(handler sdk.Handler, dbName string, cacheSize int, logger log.L // NewBasecoinTick - create a new instance of the basecoin application with tick functionality func NewBasecoinTick(handler sdk.Handler, tick Ticker, dbName string, cacheSize int, logger log.Logger) (*Basecoin, error) { - base, err := NewBaseApp(dbName, cacheSize, logger) + appName := fmt.Sprintf("Basecoin v%v", version.Version) + base, err := NewBaseApp(appName, dbName, cacheSize, logger) app := &Basecoin{ BaseApp: base, handler: handler, diff --git a/app/store.go b/app/store.go deleted file mode 100644 index ff33d7dbcbdd..000000000000 --- a/app/store.go +++ /dev/null @@ -1,11 +0,0 @@ -package app - -// // MockStore returns an in-memory store only intended for testing -// func MockStore() *Store { -// res, err := NewStore("", 0, log.NewNopLogger()) -// if err != nil { -// // should never happen, abort test if it does -// panic(err) -// } -// return res -// } From 3a16fa9482dfc358287b54c5aada71ae8ba31211 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 16 Oct 2017 18:31:07 +0200 Subject: [PATCH 009/117] Clean up genesis handling --- app/bc.go | 32 ++++++++--------------------- app/genesis.go | 44 ++++++++++++++++++++++++++++++++-------- app/genesis_test.go | 6 +++--- server/commands/start.go | 2 +- 4 files changed, 47 insertions(+), 37 deletions(-) diff --git a/app/bc.go b/app/bc.go index 81e559f4a1ea..46d1a1ca0f2e 100644 --- a/app/bc.go +++ b/app/bc.go @@ -4,13 +4,13 @@ import ( "fmt" abci "github.com/tendermint/abci/types" - "github.com/tendermint/abci/version" "github.com/tendermint/tmlibs/log" sdk "github.com/cosmos/cosmos-sdk" "github.com/cosmos/cosmos-sdk/errors" "github.com/cosmos/cosmos-sdk/stack" sm "github.com/cosmos/cosmos-sdk/state" + "github.com/cosmos/cosmos-sdk/version" ) // Basecoin - The ABCI application @@ -61,7 +61,13 @@ func (app *Basecoin) InitState(module, key, value string) (string, error) { return "", fmt.Errorf("unknown base option: %s", key) } - return app.handler.InitState(app.Logger(), state, module, key, value) + log, err := app.handler.InitState(app.Logger(), state, module, key, value) + if err != nil { + app.Logger().Error("Genesis App Options", "err", err) + } else { + app.Logger().Info(log) + } + return log, err } // DeliverTx - ABCI @@ -119,25 +125,3 @@ func (app *Basecoin) BeginBlock(req abci.RequestBeginBlock) { app.AddValChange(diff) } } - -// LoadGenesis parses the genesis file and sets the initial -// state based on that -func (app *Basecoin) LoadGenesis(filePath string) error { - init, err := GetInitialState(filePath) - if err != nil { - return err - } - - // execute all the genesis init options - // abort on any error - fmt.Printf("%#v\n", init) - for _, mkv := range init { - log, _ := app.InitState(mkv.Module, mkv.Key, mkv.Value) - // TODO: error out on bad options?? - // if err != nil { - // return err - // } - app.Logger().Info(log) - } - return nil -} diff --git a/app/genesis.go b/app/genesis.go index ceb0e1156ef6..29031d269a6d 100644 --- a/app/genesis.go +++ b/app/genesis.go @@ -14,17 +14,43 @@ const ( ModuleNameBase = "base" ) -// InitState just holds module/key/value triples from +// Option just holds module/key/value triples from // parsing the genesis file -type InitState struct { +type Option struct { Module string Key string Value string } -// GetInitialState parses the genesis file in a format -// that can easily be handed into InitState modules -func GetInitialState(path string) ([]InitState, error) { +// InitStater is anything that can handle app options +// from genesis file. +type InitStater interface { + InitState(module, key, value string) (string, error) +} + +// LoadGenesis parses the genesis file and sets the initial +// state based on that +func LoadGenesis(app InitStater, filePath string) error { + opts, err := GetGenesisOptions(filePath) + if err != nil { + return err + } + + // execute all the genesis init options + // abort on any error + for _, opt := range opts { + _, _ = app.InitState(opt.Module, opt.Key, opt.Value) + // TODO: error out on bad options?? + // if err != nil { + // return err + // } + } + return nil +} + +// GetGenesisOptions parses the genesis file in a format +// that can easily be handed into InitStaters +func GetGenesisOptions(path string) ([]Option, error) { genDoc, err := loadGenesis(path) if err != nil { return nil, err @@ -32,21 +58,21 @@ func GetInitialState(path string) ([]InitState, error) { opts := genDoc.AppOptions cnt := 1 + len(opts.Accounts) + len(opts.pluginOptions) - res := make([]InitState, cnt) + res := make([]Option, cnt) - res[0] = InitState{ModuleNameBase, ChainKey, genDoc.ChainID} + res[0] = Option{ModuleNameBase, ChainKey, genDoc.ChainID} i := 1 // set accounts for _, acct := range opts.Accounts { - res[i] = InitState{"coin", "account", string(acct)} + res[i] = Option{"coin", "account", string(acct)} i++ } // set plugin options for _, kv := range opts.pluginOptions { module, key := splitKey(kv.Key) - res[i] = InitState{module, key, kv.Value} + res[i] = Option{module, key, kv.Value} i++ } diff --git a/app/genesis_test.go b/app/genesis_test.go index ccb1229dcc97..ee73ceb0f430 100644 --- a/app/genesis_test.go +++ b/app/genesis_test.go @@ -25,7 +25,7 @@ func TestLoadGenesisDoNotFailIfAppOptionsAreMissing(t *testing.T) { logger) require.Nil(t, err, "%+v", err) - err = app.LoadGenesis("./testdata/genesis3.json") + err = LoadGenesis(app, "./testdata/genesis3.json") require.Nil(t, err, "%+v", err) } @@ -39,7 +39,7 @@ func TestLoadGenesis(t *testing.T) { logger) require.Nil(err, "%+v", err) - err = app.LoadGenesis(genesisFilepath) + err = LoadGenesis(app, genesisFilepath) require.Nil(err, "%+v", err) // check the chain id @@ -73,7 +73,7 @@ func TestLoadGenesisAccountAddress(t *testing.T) { logger) require.Nil(err, "%+v", err) - err = app.LoadGenesis(genesisAcctFilepath) + err = LoadGenesis(app, genesisAcctFilepath) require.Nil(err, "%+v", err) // check the chain id diff --git a/server/commands/start.go b/server/commands/start.go index 825e9bfd35f3..117ec6b2bf3c 100644 --- a/server/commands/start.go +++ b/server/commands/start.go @@ -111,7 +111,7 @@ func start(rootDir string, basecoinApp *app.Basecoin) error { // If genesis file exists, set key-value options genesisFile := path.Join(rootDir, "genesis.json") if _, err := os.Stat(genesisFile); err == nil { - err := basecoinApp.LoadGenesis(genesisFile) + err = app.LoadGenesis(basecoinApp, genesisFile) if err != nil { return errors.Errorf("Error in LoadGenesis: %v\n", err) } From f65215ad922f55862e6baf33ef2dfe714655962c Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 16 Oct 2017 19:21:43 +0200 Subject: [PATCH 010/117] Big cleanup of app dir StoreApp just the queries, BaseApp with handler/ticker Ticker now defined top level, as an interface, with context Name for info taken as parameter, start cmd uses commandline name Cleaner compisition of apps. --- app/app_test.go | 19 +-- app/base.go | 113 ++++++++++++++++ app/bc.go | 127 ------------------ app/genesis_test.go | 18 +-- app/{app.go => store.go} | 59 ++++---- app/{app_val_test.go => val_test.go} | 3 +- benchmarks/app_test.go | 12 +- client/query_test.go | 5 +- examples/basecoin/tests/cli/rpc.sh | 2 +- .../counter/plugins/counter/counter_test.go | 8 +- handler.go | 12 ++ server/commands/start.go | 28 ++-- 12 files changed, 202 insertions(+), 204 deletions(-) create mode 100644 app/base.go delete mode 100644 app/bc.go rename app/{app.go => store.go} (77%) rename app/{app_val_test.go => val_test.go} (96%) diff --git a/app/app_test.go b/app/app_test.go index 5be1320daf95..0e90f654136a 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -55,7 +55,7 @@ func DefaultHandler(feeDenom string) sdk.Handler { type appTest struct { t *testing.T chainID string - app *Basecoin + app *BaseApp acctIn *coin.AccountWithKey acctOut *coin.AccountWithKey } @@ -113,14 +113,9 @@ func (at *appTest) reset() { logger := log.TestingLogger() // logger := log.NewTracingLogger(log.NewTMLogger(os.Stdout)) - var err error - at.app, err = NewBasecoin( - DefaultHandler("mycoin"), - "", - 0, - logger.With("module", "app"), - ) + store, err := NewStoreApp("app-test", "", 0, logger) require.Nil(at.t, err, "%+v", err) + at.app = NewBaseApp(store, DefaultHandler("mycoin"), nil) _, err = at.app.InitState("base", "chain_id", at.chainID) require.Nil(at.t, err, "%+v", err) @@ -173,13 +168,9 @@ func TestInitState(t *testing.T) { require := require.New(t) logger := log.TestingLogger() - app, err := NewBasecoin( - DefaultHandler("atom"), - "", - 0, - logger.With("module", "app"), - ) + store, err := NewStoreApp("app-test", "", 0, logger) require.Nil(err, "%+v", err) + app := NewBaseApp(store, DefaultHandler("atom"), nil) //testing ChainID chainID := "testChain" diff --git a/app/base.go b/app/base.go new file mode 100644 index 000000000000..a0ddbb7e21b3 --- /dev/null +++ b/app/base.go @@ -0,0 +1,113 @@ +package app + +import ( + "fmt" + + abci "github.com/tendermint/abci/types" + + sdk "github.com/cosmos/cosmos-sdk" + "github.com/cosmos/cosmos-sdk/errors" + "github.com/cosmos/cosmos-sdk/stack" +) + +// BaseApp - The ABCI application +type BaseApp struct { + *StoreApp + handler sdk.Handler + clock sdk.Ticker +} + +var _ abci.Application = &BaseApp{} + +// NewBaseApp extends a StoreApp with a handler and a ticker, +// which it binds to the proper abci calls +func NewBaseApp(store *StoreApp, handler sdk.Handler, clock sdk.Ticker) *BaseApp { + return &BaseApp{ + StoreApp: store, + handler: handler, + clock: clock, + } +} + +// DeliverTx - ABCI - dispatches to the handler +func (app *BaseApp) DeliverTx(txBytes []byte) abci.Result { + tx, err := sdk.LoadTx(txBytes) + if err != nil { + return errors.Result(err) + } + + ctx := stack.NewContext( + app.GetChainID(), + app.WorkingHeight(), + app.Logger().With("call", "delivertx"), + ) + res, err := app.handler.DeliverTx(ctx, app.Append(), tx) + + if err != nil { + return errors.Result(err) + } + app.AddValChange(res.Diff) + return sdk.ToABCI(res) +} + +// CheckTx - ABCI - dispatches to the handler +func (app *BaseApp) CheckTx(txBytes []byte) abci.Result { + tx, err := sdk.LoadTx(txBytes) + if err != nil { + return errors.Result(err) + } + + ctx := stack.NewContext( + app.GetChainID(), + app.WorkingHeight(), + app.Logger().With("call", "checktx"), + ) + res, err := app.handler.CheckTx(ctx, app.Check(), tx) + + if err != nil { + return errors.Result(err) + } + return sdk.ToABCI(res) +} + +// BeginBlock - ABCI - triggers Tick actions +func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) { + // execute tick if present + if app.clock != nil { + ctx := stack.NewContext( + app.GetChainID(), + app.WorkingHeight(), + app.Logger().With("call", "tick"), + ) + + diff, err := app.clock.Tick(ctx, app.Append()) + if err != nil { + panic(err) + } + app.AddValChange(diff) + } +} + +// InitState - used to setup state (was SetOption) +// to be used by InitChain later +// +// TODO: rethink this a bit more.... +func (app *BaseApp) InitState(module, key, value string) (string, error) { + state := app.Append() + + if module == ModuleNameBase { + if key == ChainKey { + app.info.SetChainID(state, value) + return "Success", nil + } + return "", fmt.Errorf("unknown base option: %s", key) + } + + log, err := app.handler.InitState(app.Logger(), state, module, key, value) + if err != nil { + app.Logger().Error("Genesis App Options", "err", err) + } else { + app.Logger().Info(log) + } + return log, err +} diff --git a/app/bc.go b/app/bc.go deleted file mode 100644 index 46d1a1ca0f2e..000000000000 --- a/app/bc.go +++ /dev/null @@ -1,127 +0,0 @@ -package app - -import ( - "fmt" - - abci "github.com/tendermint/abci/types" - "github.com/tendermint/tmlibs/log" - - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/errors" - "github.com/cosmos/cosmos-sdk/stack" - sm "github.com/cosmos/cosmos-sdk/state" - "github.com/cosmos/cosmos-sdk/version" -) - -// Basecoin - The ABCI application -type Basecoin struct { - *BaseApp - handler sdk.Handler - tick Ticker -} - -// Ticker - tick function -type Ticker func(sm.SimpleDB) ([]*abci.Validator, error) - -var _ abci.Application = &Basecoin{} - -// NewBasecoin - create a new instance of the basecoin application -func NewBasecoin(handler sdk.Handler, dbName string, cacheSize int, logger log.Logger) (*Basecoin, error) { - appName := fmt.Sprintf("Basecoin v%v", version.Version) - base, err := NewBaseApp(appName, dbName, cacheSize, logger) - app := &Basecoin{ - BaseApp: base, - handler: handler, - } - return app, err -} - -// NewBasecoinTick - create a new instance of the basecoin application with tick functionality -func NewBasecoinTick(handler sdk.Handler, tick Ticker, dbName string, cacheSize int, logger log.Logger) (*Basecoin, error) { - appName := fmt.Sprintf("Basecoin v%v", version.Version) - base, err := NewBaseApp(appName, dbName, cacheSize, logger) - app := &Basecoin{ - BaseApp: base, - handler: handler, - tick: tick, - } - return app, err -} - -// InitState - used to setup state (was SetOption) -// to be used by InitChain later -func (app *Basecoin) InitState(module, key, value string) (string, error) { - state := app.Append() - - if module == ModuleNameBase { - if key == ChainKey { - app.info.SetChainID(state, value) - return "Success", nil - } - return "", fmt.Errorf("unknown base option: %s", key) - } - - log, err := app.handler.InitState(app.Logger(), state, module, key, value) - if err != nil { - app.Logger().Error("Genesis App Options", "err", err) - } else { - app.Logger().Info(log) - } - return log, err -} - -// DeliverTx - ABCI -func (app *Basecoin) DeliverTx(txBytes []byte) abci.Result { - tx, err := sdk.LoadTx(txBytes) - if err != nil { - return errors.Result(err) - } - - ctx := stack.NewContext( - app.GetChainID(), - app.height+1, - app.Logger().With("call", "delivertx"), - ) - res, err := app.handler.DeliverTx(ctx, app.Append(), tx) - - if err != nil { - return errors.Result(err) - } - app.AddValChange(res.Diff) - return sdk.ToABCI(res) -} - -// CheckTx - ABCI -func (app *Basecoin) CheckTx(txBytes []byte) abci.Result { - tx, err := sdk.LoadTx(txBytes) - if err != nil { - return errors.Result(err) - } - - ctx := stack.NewContext( - app.GetChainID(), - app.height+1, - app.Logger().With("call", "checktx"), - ) - res, err := app.handler.CheckTx(ctx, app.Check(), tx) - - if err != nil { - return errors.Result(err) - } - return sdk.ToABCI(res) -} - -// BeginBlock - ABCI -func (app *Basecoin) BeginBlock(req abci.RequestBeginBlock) { - // call the embeded Begin - app.BaseApp.BeginBlock(req) - - // now execute tick - if app.tick != nil { - diff, err := app.tick(app.Append()) - if err != nil { - panic(err) - } - app.AddValChange(diff) - } -} diff --git a/app/genesis_test.go b/app/genesis_test.go index ee73ceb0f430..14b841480b72 100644 --- a/app/genesis_test.go +++ b/app/genesis_test.go @@ -19,11 +19,9 @@ const genesisAcctFilepath = "./testdata/genesis2.json" func TestLoadGenesisDoNotFailIfAppOptionsAreMissing(t *testing.T) { logger := log.TestingLogger() - app, err := NewBasecoin(DefaultHandler("mycoin"), - "", - 0, - logger) + store, err := MockStoreApp("genesis", logger) require.Nil(t, err, "%+v", err) + app := NewBaseApp(store, DefaultHandler("mycoin"), nil) err = LoadGenesis(app, "./testdata/genesis3.json") require.Nil(t, err, "%+v", err) @@ -33,11 +31,9 @@ func TestLoadGenesis(t *testing.T) { assert, require := assert.New(t), require.New(t) logger := log.TestingLogger() - app, err := NewBasecoin(DefaultHandler("mycoin"), - "", - 0, - logger) + store, err := MockStoreApp("genesis", logger) require.Nil(err, "%+v", err) + app := NewBaseApp(store, DefaultHandler("mycoin"), nil) err = LoadGenesis(app, genesisFilepath) require.Nil(err, "%+v", err) @@ -67,11 +63,9 @@ func TestLoadGenesisAccountAddress(t *testing.T) { assert, require := assert.New(t), require.New(t) logger := log.TestingLogger() - app, err := NewBasecoin(DefaultHandler("mycoin"), - "", - 0, - logger) + store, err := MockStoreApp("genesis", logger) require.Nil(err, "%+v", err) + app := NewBaseApp(store, DefaultHandler("mycoin"), nil) err = LoadGenesis(app, genesisAcctFilepath) require.Nil(err, "%+v", err) diff --git a/app/app.go b/app/store.go similarity index 77% rename from app/app.go rename to app/store.go index c8a03c6fe2fa..8385515916de 100644 --- a/app/app.go +++ b/app/store.go @@ -22,12 +22,12 @@ const ( ChainKey = "chain_id" ) -// BaseApp contains a data store and all info needed +// StoreApp contains a data store and all info needed // to perform queries and handshakes. // // It should be embeded in another struct for CheckTx, // DeliverTx and initializing state from the genesis. -type BaseApp struct { +type StoreApp struct { // Name is what is returned from info Name string @@ -44,63 +44,78 @@ type BaseApp struct { logger log.Logger } -// NewBaseApp creates a data store to handle queries -func NewBaseApp(appName, dbName string, cacheSize int, logger log.Logger) (*BaseApp, error) { +// 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) if err != nil { return nil, err } - app := &BaseApp{ + app := &StoreApp{ Name: appName, State: state, height: state.LatestHeight(), info: sm.NewChainState(), - logger: logger, + logger: logger.With("module", "app"), } return app, nil } +// MockStoreApp returns a Store app with no persistence +func MockStoreApp(appName string, logger log.Logger) (*StoreApp, error) { + return NewStoreApp(appName, "", 0, logger) +} + // GetChainID returns the currently stored chain -func (app *BaseApp) GetChainID() string { +func (app *StoreApp) GetChainID() string { return app.info.GetChainID(app.Committed()) } // Logger returns the application base logger -func (app *BaseApp) Logger() log.Logger { +func (app *StoreApp) Logger() log.Logger { return app.logger } // Hash gets the last hash stored in the database -func (app *BaseApp) Hash() []byte { +func (app *StoreApp) Hash() []byte { return app.State.LatestHash() } +// CommittedHeight gets the last block height committed +// to the db +func (app *StoreApp) CommittedHeight() uint64 { + return app.height +} + +// WorkingHeight gets the current block we are writing +func (app *StoreApp) WorkingHeight() uint64 { + return app.height + 1 +} + // Info implements abci.Application. It returns the height and hash, // as well as the abci name and version. // // The height is the block that holds the transactions, not the apphash itself. -func (app *BaseApp) Info(req abci.RequestInfo) abci.ResponseInfo { +func (app *StoreApp) Info(req abci.RequestInfo) abci.ResponseInfo { hash := app.Hash() app.logger.Info("Info synced", - "height", app.height, + "height", app.CommittedHeight(), "hash", fmt.Sprintf("%X", hash)) return abci.ResponseInfo{ - // TODO Data: app.Name, - LastBlockHeight: app.height, + LastBlockHeight: app.CommittedHeight(), LastBlockAppHash: hash, } } // SetOption - ABCI -func (app *BaseApp) SetOption(key string, value string) string { +func (app *StoreApp) SetOption(key string, value string) string { return "Not Implemented" } // Query - ABCI -func (app *BaseApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) { +func (app *StoreApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) { if len(reqQuery.Data) == 0 { resQuery.Log = "Query cannot be zero length" resQuery.Code = abci.CodeType_EncodingError @@ -120,7 +135,7 @@ func (app *BaseApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQue // if tree.Tree.VersionExists(app.height - 1) { // height = app.height - 1 // } else { - height = app.height + height = app.CommittedHeight() // } } resQuery.Height = height @@ -150,7 +165,7 @@ func (app *BaseApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQue } // Commit implements abci.Application -func (app *BaseApp) Commit() (res abci.Result) { +func (app *StoreApp) Commit() (res abci.Result) { app.height++ hash, err := app.State.Commit(app.height) @@ -170,16 +185,14 @@ func (app *BaseApp) Commit() (res abci.Result) { } // InitChain - ABCI -func (app *BaseApp) InitChain(req abci.RequestInitChain) { -} +func (app *StoreApp) InitChain(req abci.RequestInitChain) {} // BeginBlock - ABCI -func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) { -} +func (app *StoreApp) BeginBlock(req abci.RequestBeginBlock) {} // EndBlock - ABCI // Returns a list of all validator changes made in this block -func (app *BaseApp) EndBlock(height uint64) (res abci.ResponseEndBlock) { +func (app *StoreApp) EndBlock(height uint64) (res abci.ResponseEndBlock) { // TODO: cleanup in case a validator exists multiple times in the list res.Diffs = app.pending app.pending = nil @@ -189,7 +202,7 @@ func (app *BaseApp) EndBlock(height uint64) (res abci.ResponseEndBlock) { // AddValChange is meant to be called by apps on DeliverTx // results, this is added to the cache for the endblock // changeset -func (app *BaseApp) AddValChange(diffs []*abci.Validator) { +func (app *StoreApp) AddValChange(diffs []*abci.Validator) { for _, d := range diffs { idx := pubKeyIndex(d, app.pending) if idx >= 0 { diff --git a/app/app_val_test.go b/app/val_test.go similarity index 96% rename from app/app_val_test.go rename to app/val_test.go index e85868b8abfd..c333273f2559 100644 --- a/app/app_val_test.go +++ b/app/val_test.go @@ -40,8 +40,9 @@ func TestEndBlock(t *testing.T) { logger := log.NewNopLogger() handler := base.ValSetHandler{} - app, err := NewBasecoin(handler, "", 0, logger) + store, err := MockStoreApp("vals", logger) require.Nil(err, "%+v", err) + app := NewBaseApp(store, handler, nil) val1 := makeVal() val2 := makeVal() diff --git a/benchmarks/app_test.go b/benchmarks/app_test.go index 690727e74a62..5d72736aa3ee 100644 --- a/benchmarks/app_test.go +++ b/benchmarks/app_test.go @@ -10,7 +10,7 @@ import ( "github.com/tendermint/tmlibs/log" sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/app" + sdkapp "github.com/cosmos/cosmos-sdk/app" "github.com/cosmos/cosmos-sdk/modules/auth" "github.com/cosmos/cosmos-sdk/modules/base" "github.com/cosmos/cosmos-sdk/modules/coin" @@ -21,7 +21,7 @@ import ( ) type BenchApp struct { - App *app.Basecoin + App *sdkapp.BaseApp Accounts []*coin.AccountWithKey ChainID string } @@ -59,15 +59,11 @@ func NewBenchApp(h sdk.Handler, chainID string, n int, cache = 500 } - app, err := app.NewBasecoin( - h, - dbDir, - cache, - logger.With("module", "app"), - ) + store, err := sdkapp.NewStoreApp("bench", dbDir, cache, logger) if err != nil { panic(err) } + app := sdkapp.NewBaseApp(store, h, nil) _, err = app.InitState("base", "chain_id", chainID) if err != nil { diff --git a/client/query_test.go b/client/query_test.go index fe8ee41801cf..f8031ee8384f 100644 --- a/client/query_test.go +++ b/client/query_test.go @@ -18,7 +18,7 @@ import ( "github.com/tendermint/tendermint/types" "github.com/tendermint/tmlibs/log" - "github.com/cosmos/cosmos-sdk/app" + sdkapp "github.com/cosmos/cosmos-sdk/app" "github.com/cosmos/cosmos-sdk/modules/eyes" ) @@ -26,10 +26,11 @@ var node *nm.Node func TestMain(m *testing.M) { logger := log.TestingLogger() - app, err := app.NewBasecoin(eyes.NewHandler(), "", 0, logger) + store, err := sdkapp.MockStoreApp("query", logger) if err != nil { panic(err) } + app := sdkapp.NewBaseApp(store, eyes.NewHandler(), nil) node = rpctest.StartTendermint(app) diff --git a/examples/basecoin/tests/cli/rpc.sh b/examples/basecoin/tests/cli/rpc.sh index 3f5a55713499..5ab6022d9b2b 100755 --- a/examples/basecoin/tests/cli/rpc.sh +++ b/examples/basecoin/tests/cli/rpc.sh @@ -66,7 +66,7 @@ test01GetInsecure() { INFO=$(${CLIENT_EXE} rpc info) assertTrue "line=${LINENO}, get info" "$?" DATA=$(echo $INFO | jq .response.data) - assertEquals "line=${LINENO}, basecoin info" '"Basecoin v0.7.1"' "$DATA" + assertEquals "line=${LINENO}, basecoin info" '"basecoin v0.7.1"' "$DATA" } test02GetSecure() { diff --git a/examples/counter/plugins/counter/counter_test.go b/examples/counter/plugins/counter/counter_test.go index a10e0afbbb24..07861dc29bac 100644 --- a/examples/counter/plugins/counter/counter_test.go +++ b/examples/counter/plugins/counter/counter_test.go @@ -28,13 +28,9 @@ func TestCounterPlugin(t *testing.T) { // logger := log.NewTracingLogger(log.NewTMLogger(os.Stdout)) h := NewHandler("gold") - bcApp, err := app.NewBasecoin( - h, - "", - 0, - logger.With("module", "app"), - ) + store, err := app.MockStoreApp("counter", logger) require.Nil(err, "%+v", err) + bcApp := app.NewBaseApp(store, h, nil) _, err = bcApp.InitState("base", "chain_id", chainID) require.Nil(err, "%+v", err) diff --git a/handler.go b/handler.go index 8047fc40af09..51d8e4a12788 100644 --- a/handler.go +++ b/handler.go @@ -25,6 +25,18 @@ type Handler interface { // BeginBlock(store state.SimpleDB, hash []byte, header *abci.Header) } +// Ticker can be executed every block +type Ticker interface { + Tick(Context, state.SimpleDB) ([]*abci.Validator, error) +} + +// TickerFunc allows a function to implement the interface +type TickerFunc func(Context, state.SimpleDB) ([]*abci.Validator, error) + +func (t TickerFunc) Tick(ctx Context, store state.SimpleDB) ([]*abci.Validator, error) { + return t(ctx, store) +} + // Named ensures there is a name for the item type Named interface { Name() string diff --git a/server/commands/start.go b/server/commands/start.go index 117ec6b2bf3c..22e79ec1c7f7 100644 --- a/server/commands/start.go +++ b/server/commands/start.go @@ -21,6 +21,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk" "github.com/cosmos/cosmos-sdk/app" + "github.com/cosmos/cosmos-sdk/version" ) // StartCmd - command to start running the abci app (and tendermint)! @@ -31,7 +32,7 @@ var StartCmd = &cobra.Command{ } // GetTickStartCmd - initialize a command as the start command with tick -func GetTickStartCmd(tick app.Ticker) *cobra.Command { +func GetTickStartCmd(tick sdk.Ticker) *cobra.Command { startCmd := &cobra.Command{ Use: "start", Short: "Start this full node", @@ -70,20 +71,23 @@ func addStartFlag(startCmd *cobra.Command) { } //returns the start command which uses the tick -func tickStartCmd(tick app.Ticker) func(cmd *cobra.Command, args []string) error { +func tickStartCmd(clock sdk.Ticker) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { rootDir := viper.GetString(cli.HomeFlag) - // Create Basecoin app - basecoinApp, err := app.NewBasecoinTick( - Handler, - tick, + cmdName := cmd.Root().Name() + appName := fmt.Sprintf("%s v%v", cmdName, version.Version) + storeApp, err := app.NewStoreApp( + appName, path.Join(rootDir, "data", "merkleeyes.db"), EyesCacheSize, logger.With("module", "app")) if err != nil { return err } + + // Create Basecoin app + basecoinApp := app.NewBaseApp(storeApp, Handler, clock) return start(rootDir, basecoinApp) } } @@ -91,19 +95,23 @@ func tickStartCmd(tick app.Ticker) func(cmd *cobra.Command, args []string) error func startCmd(cmd *cobra.Command, args []string) error { rootDir := viper.GetString(cli.HomeFlag) - // Create Basecoin app - basecoinApp, err := app.NewBasecoin( - Handler, + cmdName := cmd.Root().Name() + appName := fmt.Sprintf("%s v%v", cmdName, version.Version) + storeApp, err := app.NewStoreApp( + appName, path.Join(rootDir, "data", "merkleeyes.db"), EyesCacheSize, logger.With("module", "app")) if err != nil { return err } + + // Create Basecoin app + basecoinApp := app.NewBaseApp(storeApp, Handler, nil) return start(rootDir, basecoinApp) } -func start(rootDir string, basecoinApp *app.Basecoin) error { +func start(rootDir string, basecoinApp *app.BaseApp) error { // if chain_id has not been set yet, load the genesis. // else, assume it's been loaded From 3316bfcfb8928867e7f068a4948443d273345bca Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 16 Oct 2017 19:36:03 +0200 Subject: [PATCH 011/117] Abort on error with genesis app_options --- app/genesis.go | 9 ++--- app/genesis_test.go | 74 ++++++++++++++++++++++++------------- app/testdata/genesis2.json | 13 ------- app/testdata/genesis2b.json | 52 ++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 44 deletions(-) create mode 100644 app/testdata/genesis2b.json diff --git a/app/genesis.go b/app/genesis.go index 29031d269a6d..17d9bdebea64 100644 --- a/app/genesis.go +++ b/app/genesis.go @@ -39,11 +39,10 @@ func LoadGenesis(app InitStater, filePath string) error { // execute all the genesis init options // abort on any error for _, opt := range opts { - _, _ = app.InitState(opt.Module, opt.Key, opt.Value) - // TODO: error out on bad options?? - // if err != nil { - // return err - // } + _, err = app.InitState(opt.Module, opt.Key, opt.Value) + if err != nil { + return err + } } return nil } diff --git a/app/genesis_test.go b/app/genesis_test.go index 14b841480b72..f62164f696d3 100644 --- a/app/genesis_test.go +++ b/app/genesis_test.go @@ -17,6 +17,10 @@ import ( const genesisFilepath = "./testdata/genesis.json" const genesisAcctFilepath = "./testdata/genesis2.json" +// 2b is just like 2, but add carl who has inconsistent +// pubkey and address +const genesisBadAcctFilepath = "./testdata/genesis2b.json" + func TestLoadGenesisDoNotFailIfAppOptionsAreMissing(t *testing.T) { logger := log.TestingLogger() store, err := MockStoreApp("genesis", logger) @@ -27,35 +31,16 @@ func TestLoadGenesisDoNotFailIfAppOptionsAreMissing(t *testing.T) { require.Nil(t, err, "%+v", err) } -func TestLoadGenesis(t *testing.T) { - assert, require := assert.New(t), require.New(t) +func TestLoadGenesisFailsWithUnknownOptions(t *testing.T) { + require := require.New(t) logger := log.TestingLogger() store, err := MockStoreApp("genesis", logger) require.Nil(err, "%+v", err) - app := NewBaseApp(store, DefaultHandler("mycoin"), nil) + app := NewBaseApp(store, DefaultHandler("mycoin"), nil) err = LoadGenesis(app, genesisFilepath) - require.Nil(err, "%+v", err) - - // check the chain id - assert.Equal("foo_bar_chain", app.GetChainID()) - - // and check the account info - previously calculated values - addr, _ := hex.DecodeString("eb98e0688217cfdeb70eddf4b33cdcc37fc53197") - - coins, err := getAddr(addr, app.Append()) - require.Nil(err) - assert.True(coins.IsPositive()) - - // make sure balance is proper - assert.Equal(2, len(coins)) - assert.True(coins.IsValid()) - // note, that we now sort them to be valid - assert.EqualValues(654321, coins[0].Amount) - assert.EqualValues("ETH", coins[0].Denom) - assert.EqualValues(12345, coins[1].Amount) - assert.EqualValues("blank", coins[1].Denom) + require.NotNil(err, "%+v", err) } // Fix for issue #89, change the parse format for accounts in genesis.json @@ -84,9 +69,6 @@ func TestLoadGenesisAccountAddress(t *testing.T) { {"62035D628DE7543332544AA60D90D3693B6AD51B", true, true, coin.Coins{{"one", 111}}}, // this comes from an address, should be stored proper (bob) {"C471FB670E44D219EE6DF2FC284BE38793ACBCE1", true, false, coin.Coins{{"two", 222}}}, - // this one had a mismatched address and pubkey, should not store under either (carl) - {"1234ABCDD18E8EFE3FFC4B0506BF9BF8E5B0D9E9", false, false, nil}, // this is given addr - {"700BEC5ED18E8EFE3FFC4B0506BF9BF8E5B0D9E9", false, false, nil}, // this is addr of the given pubkey // this comes from a secp256k1 public key, should be stored proper (sam) {"979F080B1DD046C452C2A8A250D18646C6B669D4", true, true, coin.Coins{{"four", 444}}}, } @@ -106,6 +88,19 @@ func TestLoadGenesisAccountAddress(t *testing.T) { } } +// When you define an account in genesis with address +// and pubkey that don't match +func TestLoadGenesisAccountInconsistentAddress(t *testing.T) { + require := require.New(t) + + logger := log.TestingLogger() + store, err := MockStoreApp("genesis", logger) + require.Nil(err, "%+v", err) + app := NewBaseApp(store, DefaultHandler("mycoin"), nil) + err = LoadGenesis(app, genesisBadAcctFilepath) + require.NotNil(err) +} + func TestParseGenesisList(t *testing.T) { assert, require := assert.New(t), require.New(t) @@ -126,3 +121,30 @@ func TestParseGenesisList(t *testing.T) { assert.Equal(genDoc.AppOptions.pluginOptions[0].Value, "value1") assert.Equal(genDoc.AppOptions.pluginOptions[1].Value, "value2") } + +func TestGetGenesisOptions(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + opts, err := GetGenesisOptions(genesisFilepath) + require.Nil(err, "loading genesis file %+v", err) + + require.Equal(4, len(opts)) + chain := opts[0] + assert.Equal(ModuleNameBase, chain.Module) + assert.Equal(ChainKey, chain.Key) + assert.Equal("foo_bar_chain", chain.Value) + + acct := opts[1] + assert.Equal("coin", acct.Module) + assert.Equal("account", acct.Key) + + p1 := opts[2] + assert.Equal("plugin1", p1.Module) + assert.Equal("key1", p1.Key) + assert.Equal("value1", p1.Value) + + p2 := opts[3] + assert.Equal("plugin1", p2.Module) + assert.Equal("key2", p2.Key) + assert.Equal("value2", p2.Value) +} diff --git a/app/testdata/genesis2.json b/app/testdata/genesis2.json index a880b3c64c02..18ec87164fd3 100644 --- a/app/testdata/genesis2.json +++ b/app/testdata/genesis2.json @@ -22,19 +22,6 @@ "amount": 222 } ] - }, { - "name": "carl", - "address": "1234ABCDD18E8EFE3FFC4B0506BF9BF8E5B0D9E9", - "pub_key": { - "type": "ed25519", - "data": "177C0AC45E86257F0708DC085D592AB22AAEECD1D26381B757F7C96135921858" - }, - "coins": [ - { - "denom": "three", - "amount": 333 - } - ] }, { "name": "sam", "pub_key": { diff --git a/app/testdata/genesis2b.json b/app/testdata/genesis2b.json new file mode 100644 index 000000000000..a880b3c64c02 --- /dev/null +++ b/app/testdata/genesis2b.json @@ -0,0 +1,52 @@ +{ + "chain_id": "addr_accounts_chain", + "app_options": { + "accounts": [{ + "name": "alice", + "pub_key": { + "type": "ed25519", + "data": "DBD9A46C45868F0A37C92B53113C09B048FBD87B5FBC2F8B199052973B8FAA36" + }, + "coins": [ + { + "denom": "one", + "amount": 111 + } + ] + }, { + "name": "bob", + "address": "C471FB670E44D219EE6DF2FC284BE38793ACBCE1", + "coins": [ + { + "denom": "two", + "amount": 222 + } + ] + }, { + "name": "carl", + "address": "1234ABCDD18E8EFE3FFC4B0506BF9BF8E5B0D9E9", + "pub_key": { + "type": "ed25519", + "data": "177C0AC45E86257F0708DC085D592AB22AAEECD1D26381B757F7C96135921858" + }, + "coins": [ + { + "denom": "three", + "amount": 333 + } + ] + }, { + "name": "sam", + "pub_key": { + "type": "secp256k1", + "data": "02AA8342F63CCCCE6DDB128525BA048CE0B2993DA3B4308746E1F216361A87651E" + }, + "coins": [ + { + "denom": "four", + "amount": 444 + } + ] + }] + } +} From 9b206153e279feca2aebb8045af37a430c4656f7 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 16 Oct 2017 19:58:12 +0200 Subject: [PATCH 012/117] Eyes takes init state, fix cli test about genesis --- examples/basecoin/cmd/basecoin/main.go | 3 +++ examples/basecoin/tests/cli/init-server.sh | 6 +++--- modules/eyes/handler.go | 15 +++++++++++++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/examples/basecoin/cmd/basecoin/main.go b/examples/basecoin/cmd/basecoin/main.go index 2a96f76bd154..af31e2fe8025 100644 --- a/examples/basecoin/cmd/basecoin/main.go +++ b/examples/basecoin/cmd/basecoin/main.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/modules/auth" "github.com/cosmos/cosmos-sdk/modules/base" "github.com/cosmos/cosmos-sdk/modules/coin" + "github.com/cosmos/cosmos-sdk/modules/eyes" "github.com/cosmos/cosmos-sdk/modules/fee" "github.com/cosmos/cosmos-sdk/modules/ibc" "github.com/cosmos/cosmos-sdk/modules/nonce" @@ -45,6 +46,8 @@ func BuildApp(feeDenom string) sdk.Handler { coin.NewHandler(), stack.WrapHandler(roles.NewHandler()), stack.WrapHandler(ibc.NewHandler()), + // and just for run, add eyes as well + stack.WrapHandler(eyes.NewHandler()), ) } diff --git a/examples/basecoin/tests/cli/init-server.sh b/examples/basecoin/tests/cli/init-server.sh index dfd503df7d04..992354081986 100755 --- a/examples/basecoin/tests/cli/init-server.sh +++ b/examples/basecoin/tests/cli/init-server.sh @@ -12,7 +12,7 @@ test01initOption() { GENESIS_FILE=${SERVE_DIR}/genesis.json HEX="deadbeef1234deadbeef1234deadbeef1234aaaa" - ${SERVER_EXE} init ${HEX} --home="$SERVE_DIR" -p=app1/key1/val1 -p='"app2/key2/{""name"": ""joe"", ""age"": ""100""}"' >/dev/null + ${SERVER_EXE} init ${HEX} --home="$SERVE_DIR" -p=eyes/key1/val1 -p='"eyes/key2/{""name"": ""joe"", ""age"": ""100""}"' >/dev/null if ! assertTrue "line=${LINENO}" $?; then return 1; fi OPTION1KEY=$(cat ${GENESIS_FILE} | jq '.app_options.plugin_options[2]') @@ -21,9 +21,9 @@ test01initOption() { OPTION2VAL=$(cat ${GENESIS_FILE} | jq '.app_options.plugin_options[5]') OPTION2VALEXPECTED=$(echo '{"name": "joe", "age": "100"}' | jq '.') - assertEquals "line=${LINENO}" '"app1/key1"' $OPTION1KEY + assertEquals "line=${LINENO}" '"eyes/key1"' $OPTION1KEY assertEquals "line=${LINENO}" '"val1"' $OPTION1VAL - assertEquals "line=${LINENO}" '"app2/key2"' $OPTION2KEY + assertEquals "line=${LINENO}" '"eyes/key2"' $OPTION2KEY assertEquals "line=${LINENO}" "$OPTION2VALEXPECTED" "$OPTION2VAL" } diff --git a/modules/eyes/handler.go b/modules/eyes/handler.go index 478019b33dc6..34a54877e4b9 100644 --- a/modules/eyes/handler.go +++ b/modules/eyes/handler.go @@ -1,10 +1,12 @@ package eyes import ( + wire "github.com/tendermint/go-wire" + "github.com/tendermint/tmlibs/log" + sdk "github.com/cosmos/cosmos-sdk" "github.com/cosmos/cosmos-sdk/errors" "github.com/cosmos/cosmos-sdk/state" - wire "github.com/tendermint/go-wire" ) const ( @@ -19,7 +21,6 @@ const ( // Handler allows us to set and remove data type Handler struct { - sdk.NopInitState sdk.NopInitValidate } @@ -35,6 +36,16 @@ func (Handler) Name() string { return Name } +// InitState - sets the genesis state +func (h Handler) InitState(l log.Logger, store state.SimpleDB, + module, key, value string) (log string, err error) { + if module != Name { + return "", errors.ErrUnknownModule(module) + } + store.Set([]byte(key), []byte(value)) + return key, nil +} + // CheckTx verifies if the transaction is properly formated func (h Handler) CheckTx(ctx sdk.Context, store state.SimpleDB, tx sdk.Tx) (res sdk.CheckResult, err error) { err = tx.ValidateBasic() From 4855b3c9d97e4a2b1e99af9f0aaaf7bf43fd41bf Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 17 Oct 2017 11:54:51 +0200 Subject: [PATCH 013/117] StoreApp explicitly exposes some State methods, not embedded, for better godoc --- app/store.go | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/app/store.go b/app/store.go index 8385515916de..8c31d9cb6f25 100644 --- a/app/store.go +++ b/app/store.go @@ -32,8 +32,8 @@ type StoreApp struct { Name string // this is the database state - info *sm.ChainState - *sm.State + info *sm.ChainState + state *sm.State // cached validator changes from DeliverTx pending []*abci.Validator @@ -52,7 +52,7 @@ func NewStoreApp(appName, dbName string, cacheSize int, logger log.Logger) (*Sto } app := &StoreApp{ Name: appName, - State: state, + state: state, height: state.LatestHeight(), info: sm.NewChainState(), logger: logger.With("module", "app"), @@ -67,7 +67,7 @@ func MockStoreApp(appName string, logger log.Logger) (*StoreApp, error) { // GetChainID returns the currently stored chain func (app *StoreApp) GetChainID() string { - return app.info.GetChainID(app.Committed()) + return app.info.GetChainID(app.state.Committed()) } // Logger returns the application base logger @@ -77,7 +77,23 @@ func (app *StoreApp) Logger() log.Logger { // Hash gets the last hash stored in the database func (app *StoreApp) Hash() []byte { - return app.State.LatestHash() + return app.state.LatestHash() +} + +// Committed returns the committed state, +// also exposing historical queries +// func (app *StoreApp) Committed() *Bonsai { +// return app.state.committed +// } + +// Append returns the working state for DeliverTx +func (app *StoreApp) Append() sm.SimpleDB { + return app.state.Append() +} + +// Check returns the working state for CheckTx +func (app *StoreApp) Check() sm.SimpleDB { + return app.state.Check() } // CommittedHeight gets the last block height committed @@ -123,7 +139,7 @@ func (app *StoreApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQu } // set the query response height to current - tree := app.State.Committed() + tree := app.state.Committed() height := reqQuery.Height if height == 0 { @@ -168,7 +184,7 @@ func (app *StoreApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQu func (app *StoreApp) Commit() (res abci.Result) { app.height++ - hash, err := app.State.Commit(app.height) + hash, err := app.state.Commit(app.height) if err != nil { // die if we can't commit, not to recover panic(err) @@ -178,7 +194,7 @@ func (app *StoreApp) Commit() (res abci.Result) { "hash", fmt.Sprintf("%X", hash), ) - if app.State.Size() == 0 { + if app.state.Size() == 0 { return abci.NewResultOK(nil, "Empty hash for empty tree") } return abci.NewResultOK(hash, "") From fbe88ee27571dfd582dbe494e5709e5795fb9205 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 17 Oct 2017 12:13:37 +0200 Subject: [PATCH 014/117] Clean up state.State as we only support persistence --- state/merkle.go | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/state/merkle.go b/state/merkle.go index ec81c6d002ff..2373d27d3bb3 100644 --- a/state/merkle.go +++ b/state/merkle.go @@ -5,19 +5,17 @@ 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 - persistent bool + committed *Bonsai + deliverTx SimpleDB + checkTx SimpleDB } func NewState(tree *iavl.VersionedTree) *State { base := NewBonsai(tree) return &State{ - committed: base, - deliverTx: base.Checkpoint(), - checkTx: base.Checkpoint(), - persistent: true, + committed: base, + deliverTx: base.Checkpoint(), + checkTx: base.Checkpoint(), } } @@ -45,14 +43,6 @@ func (s State) LatestHash() []byte { return s.committed.Tree.Hash() } -// BatchSet is used for some weird magic in storing the new height -func (s *State) BatchSet(key, value []byte) { - if s.persistent { - // This is in the batch with the Save, but not in the tree - s.committed.Tree.BatchSet(key, value) - } -} - // Commit save 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) @@ -62,15 +52,11 @@ func (s *State) Commit(version uint64) ([]byte, error) { } var hash []byte - if s.persistent { - if s.committed.Tree.Size() > 0 || s.committed.Tree.LatestVersion() > 0 { - hash, err = s.committed.Tree.SaveVersion(version) - if err != nil { - return nil, err - } + if s.committed.Tree.Size() > 0 || s.committed.Tree.LatestVersion() > 0 { + hash, err = s.committed.Tree.SaveVersion(version) + if err != nil { + return nil, err } - } else { - hash = s.committed.Tree.Hash() } s.deliverTx = s.committed.Checkpoint() From 6305399baf2b82955e5525da79943bb2a23dbe14 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 17 Oct 2017 15:47:33 +0200 Subject: [PATCH 015/117] Pulled genesis file parsing into own package, for clarity --- app/app_test.go | 16 ------ app/base.go | 4 +- app/genesis_test.go | 59 ++-------------------- app/store.go | 5 -- app/genesis.go => genesis/parse.go | 12 ++--- genesis/parse_test.go | 78 ++++++++++++++++++++++++++++++ genesis/testdata/genesis.json | 22 +++++++++ handler.go | 7 +++ server/commands/start.go | 3 +- 9 files changed, 120 insertions(+), 86 deletions(-) rename app/genesis.go => genesis/parse.go (95%) create mode 100644 genesis/parse_test.go create mode 100644 genesis/testdata/genesis.json diff --git a/app/app_test.go b/app/app_test.go index 0e90f654136a..5d6f84a3c0a8 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -291,19 +291,3 @@ func TestQuery(t *testing.T) { }) assert.NotEqual(resQueryPreCommit, resQueryPostCommit, "Query should change before/after commit") } - -func TestSplitKey(t *testing.T) { - assert := assert.New(t) - prefix, suffix := splitKey("foo/bar") - assert.EqualValues("foo", prefix) - assert.EqualValues("bar", suffix) - - prefix, suffix = splitKey("foobar") - assert.EqualValues("base", prefix) - assert.EqualValues("foobar", suffix) - - prefix, suffix = splitKey("some/complex/issue") - assert.EqualValues("some", prefix) - assert.EqualValues("complex/issue", suffix) - -} diff --git a/app/base.go b/app/base.go index a0ddbb7e21b3..8d7e73a1ea0a 100644 --- a/app/base.go +++ b/app/base.go @@ -95,8 +95,8 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) { func (app *BaseApp) InitState(module, key, value string) (string, error) { state := app.Append() - if module == ModuleNameBase { - if key == ChainKey { + if module == sdk.ModuleNameBase { + if key == sdk.ChainKey { app.info.SetChainID(state, value) return "Success", nil } diff --git a/app/genesis_test.go b/app/genesis_test.go index f62164f696d3..4707d8c4ee58 100644 --- a/app/genesis_test.go +++ b/app/genesis_test.go @@ -2,15 +2,14 @@ package app import ( "encoding/hex" - "encoding/json" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" + "github.com/cosmos/cosmos-sdk/genesis" "github.com/cosmos/cosmos-sdk/modules/coin" ) @@ -27,7 +26,7 @@ func TestLoadGenesisDoNotFailIfAppOptionsAreMissing(t *testing.T) { require.Nil(t, err, "%+v", err) app := NewBaseApp(store, DefaultHandler("mycoin"), nil) - err = LoadGenesis(app, "./testdata/genesis3.json") + err = genesis.LoadGenesis(app, "./testdata/genesis3.json") require.Nil(t, err, "%+v", err) } @@ -39,7 +38,7 @@ func TestLoadGenesisFailsWithUnknownOptions(t *testing.T) { require.Nil(err, "%+v", err) app := NewBaseApp(store, DefaultHandler("mycoin"), nil) - err = LoadGenesis(app, genesisFilepath) + err = genesis.LoadGenesis(app, genesisFilepath) require.NotNil(err, "%+v", err) } @@ -52,7 +51,7 @@ func TestLoadGenesisAccountAddress(t *testing.T) { require.Nil(err, "%+v", err) app := NewBaseApp(store, DefaultHandler("mycoin"), nil) - err = LoadGenesis(app, genesisAcctFilepath) + err = genesis.LoadGenesis(app, genesisAcctFilepath) require.Nil(err, "%+v", err) // check the chain id @@ -97,54 +96,6 @@ func TestLoadGenesisAccountInconsistentAddress(t *testing.T) { store, err := MockStoreApp("genesis", logger) require.Nil(err, "%+v", err) app := NewBaseApp(store, DefaultHandler("mycoin"), nil) - err = LoadGenesis(app, genesisBadAcctFilepath) + err = genesis.LoadGenesis(app, genesisBadAcctFilepath) require.NotNil(err) } - -func TestParseGenesisList(t *testing.T) { - assert, require := assert.New(t), require.New(t) - - bytes, err := cmn.ReadFile(genesisFilepath) - require.Nil(err, "loading genesis file %+v", err) - - // the basecoin genesis go-wire/data :) - genDoc := new(FullGenesisDoc) - err = json.Unmarshal(bytes, genDoc) - require.Nil(err, "unmarshaling genesis file %+v", err) - - pluginOpts, err := parseGenesisList(genDoc.AppOptions.PluginOptions) - require.Nil(err, "%+v", err) - genDoc.AppOptions.pluginOptions = pluginOpts - - assert.Equal(genDoc.AppOptions.pluginOptions[0].Key, "plugin1/key1") - assert.Equal(genDoc.AppOptions.pluginOptions[1].Key, "plugin1/key2") - assert.Equal(genDoc.AppOptions.pluginOptions[0].Value, "value1") - assert.Equal(genDoc.AppOptions.pluginOptions[1].Value, "value2") -} - -func TestGetGenesisOptions(t *testing.T) { - assert, require := assert.New(t), require.New(t) - - opts, err := GetGenesisOptions(genesisFilepath) - require.Nil(err, "loading genesis file %+v", err) - - require.Equal(4, len(opts)) - chain := opts[0] - assert.Equal(ModuleNameBase, chain.Module) - assert.Equal(ChainKey, chain.Key) - assert.Equal("foo_bar_chain", chain.Value) - - acct := opts[1] - assert.Equal("coin", acct.Module) - assert.Equal("account", acct.Key) - - p1 := opts[2] - assert.Equal("plugin1", p1.Module) - assert.Equal("key1", p1.Key) - assert.Equal("value1", p1.Value) - - p2 := opts[3] - assert.Equal("plugin1", p2.Module) - assert.Equal("key2", p2.Key) - assert.Equal("value2", p2.Value) -} diff --git a/app/store.go b/app/store.go index 8c31d9cb6f25..2ad14915ab07 100644 --- a/app/store.go +++ b/app/store.go @@ -17,11 +17,6 @@ import ( sm "github.com/cosmos/cosmos-sdk/state" ) -//nolint -const ( - ChainKey = "chain_id" -) - // StoreApp contains a data store and all info needed // to perform queries and handshakes. // diff --git a/app/genesis.go b/genesis/parse.go similarity index 95% rename from app/genesis.go rename to genesis/parse.go index 17d9bdebea64..f0eefd213888 100644 --- a/app/genesis.go +++ b/genesis/parse.go @@ -1,19 +1,15 @@ -package app +package genesis import ( "encoding/json" "strings" + sdk "github.com/cosmos/cosmos-sdk" "github.com/pkg/errors" cmn "github.com/tendermint/tmlibs/common" ) -//nolint -const ( - ModuleNameBase = "base" -) - // Option just holds module/key/value triples from // parsing the genesis file type Option struct { @@ -59,7 +55,7 @@ func GetGenesisOptions(path string) ([]Option, error) { cnt := 1 + len(opts.Accounts) + len(opts.pluginOptions) res := make([]Option, cnt) - res[0] = Option{ModuleNameBase, ChainKey, genDoc.ChainID} + res[0] = Option{sdk.ModuleNameBase, sdk.ChainKey, genDoc.ChainID} i := 1 // set accounts @@ -152,5 +148,5 @@ func splitKey(key string) (string, string) { keyParts := strings.SplitN(key, "/", 2) return keyParts[0], keyParts[1] } - return ModuleNameBase, key + return sdk.ModuleNameBase, key } diff --git a/genesis/parse_test.go b/genesis/parse_test.go new file mode 100644 index 000000000000..5c81d794cccc --- /dev/null +++ b/genesis/parse_test.go @@ -0,0 +1,78 @@ +package genesis + +import ( + "encoding/json" + "testing" + + sdk "github.com/cosmos/cosmos-sdk" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + cmn "github.com/tendermint/tmlibs/common" +) + +const genesisFilepath = "./testdata/genesis.json" + +func TestParseGenesisList(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + bytes, err := cmn.ReadFile(genesisFilepath) + require.Nil(err, "loading genesis file %+v", err) + + // the basecoin genesis go-wire/data :) + genDoc := new(FullGenesisDoc) + err = json.Unmarshal(bytes, genDoc) + require.Nil(err, "unmarshaling genesis file %+v", err) + + pluginOpts, err := parseGenesisList(genDoc.AppOptions.PluginOptions) + require.Nil(err, "%+v", err) + genDoc.AppOptions.pluginOptions = pluginOpts + + assert.Equal(genDoc.AppOptions.pluginOptions[0].Key, "plugin1/key1") + assert.Equal(genDoc.AppOptions.pluginOptions[1].Key, "plugin1/key2") + assert.Equal(genDoc.AppOptions.pluginOptions[0].Value, "value1") + assert.Equal(genDoc.AppOptions.pluginOptions[1].Value, "value2") +} + +func TestGetGenesisOptions(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + opts, err := GetGenesisOptions(genesisFilepath) + require.Nil(err, "loading genesis file %+v", err) + + require.Equal(4, len(opts)) + chain := opts[0] + assert.Equal(sdk.ModuleNameBase, chain.Module) + assert.Equal(sdk.ChainKey, chain.Key) + assert.Equal("foo_bar_chain", chain.Value) + + acct := opts[1] + assert.Equal("coin", acct.Module) + assert.Equal("account", acct.Key) + + p1 := opts[2] + assert.Equal("plugin1", p1.Module) + assert.Equal("key1", p1.Key) + assert.Equal("value1", p1.Value) + + p2 := opts[3] + assert.Equal("plugin1", p2.Module) + assert.Equal("key2", p2.Key) + assert.Equal("value2", p2.Value) +} + +func TestSplitKey(t *testing.T) { + assert := assert.New(t) + prefix, suffix := splitKey("foo/bar") + assert.EqualValues("foo", prefix) + assert.EqualValues("bar", suffix) + + prefix, suffix = splitKey("foobar") + assert.EqualValues("base", prefix) + assert.EqualValues("foobar", suffix) + + prefix, suffix = splitKey("some/complex/issue") + assert.EqualValues("some", prefix) + assert.EqualValues("complex/issue", suffix) + +} diff --git a/genesis/testdata/genesis.json b/genesis/testdata/genesis.json new file mode 100644 index 000000000000..ee8879fd288f --- /dev/null +++ b/genesis/testdata/genesis.json @@ -0,0 +1,22 @@ +{ + "chain_id": "foo_bar_chain", + "app_options": { + "accounts": [{ + "pub_key": { + "type": "ed25519", + "data": "6880db93598e283a67c4d88fc67a8858aa2de70f713fe94a5109e29c137100c2" + }, + "coins": [ + { + "denom": "blank", + "amount": 12345 + }, + { + "denom": "ETH", + "amount": 654321 + } + ] + }], + "plugin_options": ["plugin1/key1", "value1", "plugin1/key2", "value2"] + } +} diff --git a/handler.go b/handler.go index 51d8e4a12788..f7d6638029d7 100644 --- a/handler.go +++ b/handler.go @@ -8,6 +8,13 @@ import ( "github.com/cosmos/cosmos-sdk/state" ) +const ( + // ModuleNameBase is the module name for internal functionality + ModuleNameBase = "base" + // ChainKey is the option key for setting the chain id + ChainKey = "chain_id" +) + // Handler is anything that processes a transaction type Handler interface { // Checker verifies there are valid fees and estimates work diff --git a/server/commands/start.go b/server/commands/start.go index 22e79ec1c7f7..a7f41a329b73 100644 --- a/server/commands/start.go +++ b/server/commands/start.go @@ -21,6 +21,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk" "github.com/cosmos/cosmos-sdk/app" + "github.com/cosmos/cosmos-sdk/genesis" "github.com/cosmos/cosmos-sdk/version" ) @@ -119,7 +120,7 @@ func start(rootDir string, basecoinApp *app.BaseApp) error { // If genesis file exists, set key-value options genesisFile := path.Join(rootDir, "genesis.json") if _, err := os.Stat(genesisFile); err == nil { - err = app.LoadGenesis(basecoinApp, genesisFile) + err = genesis.LoadGenesis(basecoinApp, genesisFile) if err != nil { return errors.Errorf("Error in LoadGenesis: %v\n", err) } From 763168015970de5edafb42fb3311e5b0d72a8d74 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 17 Oct 2017 15:51:13 +0200 Subject: [PATCH 016/117] Cleanup names in genesis package --- app/genesis_test.go | 8 ++++---- genesis/parse.go | 34 +++++++++++++++++----------------- genesis/parse_test.go | 10 +++++----- server/commands/start.go | 2 +- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/app/genesis_test.go b/app/genesis_test.go index 4707d8c4ee58..a519bc99823d 100644 --- a/app/genesis_test.go +++ b/app/genesis_test.go @@ -26,7 +26,7 @@ func TestLoadGenesisDoNotFailIfAppOptionsAreMissing(t *testing.T) { require.Nil(t, err, "%+v", err) app := NewBaseApp(store, DefaultHandler("mycoin"), nil) - err = genesis.LoadGenesis(app, "./testdata/genesis3.json") + err = genesis.Load(app, "./testdata/genesis3.json") require.Nil(t, err, "%+v", err) } @@ -38,7 +38,7 @@ func TestLoadGenesisFailsWithUnknownOptions(t *testing.T) { require.Nil(err, "%+v", err) app := NewBaseApp(store, DefaultHandler("mycoin"), nil) - err = genesis.LoadGenesis(app, genesisFilepath) + err = genesis.Load(app, genesisFilepath) require.NotNil(err, "%+v", err) } @@ -51,7 +51,7 @@ func TestLoadGenesisAccountAddress(t *testing.T) { require.Nil(err, "%+v", err) app := NewBaseApp(store, DefaultHandler("mycoin"), nil) - err = genesis.LoadGenesis(app, genesisAcctFilepath) + err = genesis.Load(app, genesisAcctFilepath) require.Nil(err, "%+v", err) // check the chain id @@ -96,6 +96,6 @@ func TestLoadGenesisAccountInconsistentAddress(t *testing.T) { store, err := MockStoreApp("genesis", logger) require.Nil(err, "%+v", err) app := NewBaseApp(store, DefaultHandler("mycoin"), nil) - err = genesis.LoadGenesis(app, genesisBadAcctFilepath) + err = genesis.Load(app, genesisBadAcctFilepath) require.NotNil(err) } diff --git a/genesis/parse.go b/genesis/parse.go index f0eefd213888..6a183464c5a3 100644 --- a/genesis/parse.go +++ b/genesis/parse.go @@ -24,10 +24,10 @@ type InitStater interface { InitState(module, key, value string) (string, error) } -// LoadGenesis parses the genesis file and sets the initial +// Load parses the genesis file and sets the initial // state based on that -func LoadGenesis(app InitStater, filePath string) error { - opts, err := GetGenesisOptions(filePath) +func Load(app InitStater, filePath string) error { + opts, err := GetOptions(filePath) if err != nil { return err } @@ -43,10 +43,10 @@ func LoadGenesis(app InitStater, filePath string) error { return nil } -// GetGenesisOptions parses the genesis file in a format +// GetOptions parses the genesis file in a format // that can easily be handed into InitStaters -func GetGenesisOptions(path string) ([]Option, error) { - genDoc, err := loadGenesis(path) +func GetOptions(path string) ([]Option, error) { + genDoc, err := load(path) if err != nil { return nil, err } @@ -79,38 +79,38 @@ type keyValue struct { Value string `json:"value"` } -// FullGenesisDoc - includes tendermint (in the json, we ignore here) -type FullGenesisDoc struct { - ChainID string `json:"chain_id"` - AppOptions *GenesisDoc `json:"app_options"` +// FullDoc - includes tendermint (in the json, we ignore here) +type FullDoc struct { + ChainID string `json:"chain_id"` + AppOptions *Doc `json:"app_options"` } -// GenesisDoc - All genesis values -type GenesisDoc struct { +// Doc - All genesis values +type Doc struct { Accounts []json.RawMessage `json:"accounts"` PluginOptions []json.RawMessage `json:"plugin_options"` pluginOptions []keyValue // unmarshaled rawmessages } -func loadGenesis(filePath string) (*FullGenesisDoc, error) { +func load(filePath string) (*FullDoc, error) { bytes, err := cmn.ReadFile(filePath) if err != nil { return nil, errors.Wrap(err, "loading genesis file") } // the basecoin genesis go-wire/data :) - genDoc := new(FullGenesisDoc) + genDoc := new(FullDoc) err = json.Unmarshal(bytes, genDoc) if err != nil { return nil, errors.Wrap(err, "unmarshaling genesis file") } if genDoc.AppOptions == nil { - genDoc.AppOptions = new(GenesisDoc) + genDoc.AppOptions = new(Doc) } - pluginOpts, err := parseGenesisList(genDoc.AppOptions.PluginOptions) + pluginOpts, err := parseList(genDoc.AppOptions.PluginOptions) if err != nil { return nil, err } @@ -118,7 +118,7 @@ func loadGenesis(filePath string) (*FullGenesisDoc, error) { return genDoc, nil } -func parseGenesisList(kvzIn []json.RawMessage) (kvz []keyValue, err error) { +func parseList(kvzIn []json.RawMessage) (kvz []keyValue, err error) { if len(kvzIn)%2 != 0 { return nil, errors.New("genesis cannot have an odd number of items. Format = [key1, value1, key2, value2, ...]") } diff --git a/genesis/parse_test.go b/genesis/parse_test.go index 5c81d794cccc..822e2630ac74 100644 --- a/genesis/parse_test.go +++ b/genesis/parse_test.go @@ -13,18 +13,18 @@ import ( const genesisFilepath = "./testdata/genesis.json" -func TestParseGenesisList(t *testing.T) { +func TestParseList(t *testing.T) { assert, require := assert.New(t), require.New(t) bytes, err := cmn.ReadFile(genesisFilepath) require.Nil(err, "loading genesis file %+v", err) // the basecoin genesis go-wire/data :) - genDoc := new(FullGenesisDoc) + genDoc := new(FullDoc) err = json.Unmarshal(bytes, genDoc) require.Nil(err, "unmarshaling genesis file %+v", err) - pluginOpts, err := parseGenesisList(genDoc.AppOptions.PluginOptions) + pluginOpts, err := parseList(genDoc.AppOptions.PluginOptions) require.Nil(err, "%+v", err) genDoc.AppOptions.pluginOptions = pluginOpts @@ -34,10 +34,10 @@ func TestParseGenesisList(t *testing.T) { assert.Equal(genDoc.AppOptions.pluginOptions[1].Value, "value2") } -func TestGetGenesisOptions(t *testing.T) { +func TestGetOptions(t *testing.T) { assert, require := assert.New(t), require.New(t) - opts, err := GetGenesisOptions(genesisFilepath) + opts, err := GetOptions(genesisFilepath) require.Nil(err, "loading genesis file %+v", err) require.Equal(4, len(opts)) diff --git a/server/commands/start.go b/server/commands/start.go index a7f41a329b73..5580ce303678 100644 --- a/server/commands/start.go +++ b/server/commands/start.go @@ -120,7 +120,7 @@ func start(rootDir string, basecoinApp *app.BaseApp) error { // If genesis file exists, set key-value options genesisFile := path.Join(rootDir, "genesis.json") if _, err := os.Stat(genesisFile); err == nil { - err = genesis.LoadGenesis(basecoinApp, genesisFile) + err = genesis.Load(basecoinApp, genesisFile) if err != nil { return errors.Errorf("Error in LoadGenesis: %v\n", err) } From acdc083821566e76e78ed2da9e9025d23c69bbc7 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Oct 2017 09:59:05 +0200 Subject: [PATCH 017/117] Clean up genesis, add godoc to genesis and app --- app/app_test.go | 16 ++--- app/base.go | 16 ++--- app/doc.go | 19 ++++++ benchmarks/app_test.go | 4 +- .../counter/plugins/counter/counter_test.go | 4 +- genesis/doc.go | 61 +++++++++++++++++++ genesis/parse.go | 7 ++- 7 files changed, 105 insertions(+), 22 deletions(-) create mode 100644 app/doc.go create mode 100644 genesis/doc.go diff --git a/app/app_test.go b/app/app_test.go index 5d6f84a3c0a8..c5e48802293d 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -100,7 +100,7 @@ func (at *appTest) feeTx(coins coin.Coins, toll coin.Coin, sequence uint32) sdk. // set the account on the app through InitState func (at *appTest) initAccount(acct *coin.AccountWithKey) { - _, err := at.app.InitState("coin", "account", acct.MakeOption()) + err := at.app.InitState("coin", "account", acct.MakeOption()) require.Nil(at.t, err, "%+v", err) } @@ -117,7 +117,7 @@ func (at *appTest) reset() { require.Nil(at.t, err, "%+v", err) at.app = NewBaseApp(store, DefaultHandler("mycoin"), nil) - _, err = at.app.InitState("base", "chain_id", at.chainID) + err = at.app.InitState("base", "chain_id", at.chainID) require.Nil(at.t, err, "%+v", err) at.initAccount(at.acctIn) @@ -174,14 +174,14 @@ func TestInitState(t *testing.T) { //testing ChainID chainID := "testChain" - _, err = app.InitState("base", "chain_id", chainID) + err = app.InitState("base", "chain_id", chainID) require.Nil(err, "%+v", err) assert.EqualValues(app.GetChainID(), chainID) // make a nice account... bal := coin.Coins{{"atom", 77}, {"eth", 12}} acct := coin.NewAccountWithKey(bal) - _, err = app.InitState("coin", "account", acct.MakeOption()) + err = app.InitState("coin", "account", acct.MakeOption()) require.Nil(err, "%+v", err) // make sure it is set correctly, with some balance @@ -209,7 +209,7 @@ func TestInitState(t *testing.T) { } ] }` - _, err = app.InitState("coin", "account", unsortAcc) + err = app.InitState("coin", "account", unsortAcc) require.Nil(err, "%+v", err) coins, err = getAddr(unsortAddr, app.Append()) @@ -217,13 +217,13 @@ func TestInitState(t *testing.T) { assert.True(coins.IsValid()) assert.Equal(unsortCoins, coins) - _, err = app.InitState("base", "dslfkgjdas", "") + err = app.InitState("base", "dslfkgjdas", "") require.NotNil(err) - _, err = app.InitState("", "dslfkgjdas", "") + err = app.InitState("", "dslfkgjdas", "") require.NotNil(err) - _, err = app.InitState("dslfkgjdas", "szfdjzs", "") + err = app.InitState("dslfkgjdas", "szfdjzs", "") require.NotNil(err) } diff --git a/app/base.go b/app/base.go index 8d7e73a1ea0a..2ba14fd6469d 100644 --- a/app/base.go +++ b/app/base.go @@ -92,22 +92,24 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) { // to be used by InitChain later // // TODO: rethink this a bit more.... -func (app *BaseApp) InitState(module, key, value string) (string, error) { +func (app *BaseApp) InitState(module, key, value string) error { state := app.Append() + logger := app.Logger().With("module", module, "key", key) if module == sdk.ModuleNameBase { if key == sdk.ChainKey { app.info.SetChainID(state, value) - return "Success", nil + return nil } - return "", fmt.Errorf("unknown base option: %s", key) + logger.Error("Invalid genesis option") + return fmt.Errorf("Unknown base option: %s", key) } - log, err := app.handler.InitState(app.Logger(), state, module, key, value) + log, err := app.handler.InitState(logger, state, module, key, value) if err != nil { - app.Logger().Error("Genesis App Options", "err", err) + logger.Error("Invalid genesis option", "err", err) } else { - app.Logger().Info(log) + logger.Info(log) } - return log, err + return err } diff --git a/app/doc.go b/app/doc.go new file mode 100644 index 000000000000..d880368658c2 --- /dev/null +++ b/app/doc.go @@ -0,0 +1,19 @@ +/* +Package app contains data structures that provide basic +data storage functionality and act as a bridge between the abci +interface and the internal sdk representations. + +StoreApp handles creating a datastore or loading an existing one +from disk, provides helpers to use in the transaction workflow +(check/deliver/commit), and provides bindings to the ABCI interface +for functionality such as handshaking with tendermint on restart, +querying the data store, and handling begin/end block and commit messages. +It does not handle CheckTx or DeliverTx, or have any logic for modifying +the state, and is quite generic if you don't wish to use the standard Handlers. + +BaseApp embeds StoreApp and extends it for the standard sdk usecase, where +we dispatch all CheckTx/DeliverTx messages to a handler (which may contain +decorators and a router to multiple modules), and supports a Ticker which +is called every BeginBlock. +*/ +package app diff --git a/benchmarks/app_test.go b/benchmarks/app_test.go index 5d72736aa3ee..dc9e54474356 100644 --- a/benchmarks/app_test.go +++ b/benchmarks/app_test.go @@ -65,7 +65,7 @@ func NewBenchApp(h sdk.Handler, chainID string, n int, } app := sdkapp.NewBaseApp(store, h, nil) - _, err = app.InitState("base", "chain_id", chainID) + err = app.InitState("base", "chain_id", chainID) if err != nil { panic("cannot set chain") } @@ -75,7 +75,7 @@ func NewBenchApp(h sdk.Handler, chainID string, n int, accts := make([]*coin.AccountWithKey, n) for i := 0; i < n; i++ { accts[i] = coin.NewAccountWithKey(money) - _, err = app.InitState("coin", "account", accts[i].MakeOption()) + err = app.InitState("coin", "account", accts[i].MakeOption()) if err != nil { panic("can't set account") } diff --git a/examples/counter/plugins/counter/counter_test.go b/examples/counter/plugins/counter/counter_test.go index 07861dc29bac..5c1ef254a2d4 100644 --- a/examples/counter/plugins/counter/counter_test.go +++ b/examples/counter/plugins/counter/counter_test.go @@ -31,13 +31,13 @@ func TestCounterPlugin(t *testing.T) { store, err := app.MockStoreApp("counter", logger) require.Nil(err, "%+v", err) bcApp := app.NewBaseApp(store, h, nil) - _, err = bcApp.InitState("base", "chain_id", chainID) + err = bcApp.InitState("base", "chain_id", chainID) require.Nil(err, "%+v", err) // Account initialization bal := coin.Coins{{"", 1000}, {"gold", 1000}} acct := coin.NewAccountWithKey(bal) - _, err = bcApp.InitState("coin", "account", acct.MakeOption()) + err = bcApp.InitState("coin", "account", acct.MakeOption()) require.Nil(err, "%+v", err) // Deliver a CounterTx diff --git a/genesis/doc.go b/genesis/doc.go new file mode 100644 index 000000000000..40636fc07862 --- /dev/null +++ b/genesis/doc.go @@ -0,0 +1,61 @@ +/* +Package genesis provides some utility functions for parsing +a standard genesis file to initialize your abci application. + +We wish to support using one genesis file to initialize both +tendermint and the application, so this file format is designed +to be embedable in the tendermint genesis.json file. We reuse +the same chain_id field for tendermint, ignore the other fields, +and add a special app_options field that contains information just +for the abci app (and ignored by tendermint). + +The use of this file format for your application is not required by +the sdk and is only used by default in the start command, if you wish +to write your own start command, you can use any other method to +store and parse options for your abci application. The important part is +that the same data is available on every node. + +Example file format: + + { + "chain_id": "foo_bar_chain", + "app_options": { + "accounts": [{ + "address": "C471FB670E44D219EE6DF2FC284BE38793ACBCE1", + "pub_key": { + "type": "ed25519", + "data": "6880DB93598E283A67C4D88FC67A8858AA2DE70F713FE94A5109E29C137100C2" + }, + "coins": [ + { + "denom": "ETH", + "amount": 654321 + } + ] + }], + "plugin_options": [ + "plugin1/key1", "value1", + "profile/set", {"name": "john", age: 37} + ] + } + } + +Note that there are two subfields under app_options. The first one "accounts" +is a special case for the coin module, which is assumed to be used by most +applications. It is simply a list of accounts with an identifier and their +initial balance. The account must be identified by EITHER an address +(20 bytes in hex) or a pubkey (in the go-crypto json format), not both as in +this example. "coins" defines the initial balance of the account. + +Configuration options for every other module should be placed under +"plugin_options" as key value pairs (there must be an even number of items). +The first value must be "/" to define the option to be set. +The second value is parsed as raw json and is the value to pass to the +application. This may be a string, an array, a map or any other valid json +structure that the module can parse. + +Note that we don't use a map for plugin_options, as we will often wish +to have many values for the same key, to run this setup many times, +just as we support setting many accounts. +*/ +package genesis diff --git a/genesis/parse.go b/genesis/parse.go index 6a183464c5a3..67bc32ef1db0 100644 --- a/genesis/parse.go +++ b/genesis/parse.go @@ -19,9 +19,10 @@ type Option struct { } // InitStater is anything that can handle app options -// from genesis file. +// from genesis file. Setting the merkle store, config options, +// or anything else type InitStater interface { - InitState(module, key, value string) (string, error) + InitState(module, key, value string) error } // Load parses the genesis file and sets the initial @@ -35,7 +36,7 @@ func Load(app InitStater, filePath string) error { // execute all the genesis init options // abort on any error for _, opt := range opts { - _, err = app.InitState(opt.Module, opt.Key, opt.Value) + err = app.InitState(opt.Module, opt.Key, opt.Value) if err != nil { return err } From a1a71becbc7e24cfa23c06100425c7a7e7631aa0 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Mon, 23 Oct 2017 14:13:50 -0400 Subject: [PATCH 018/117] docs: some typos --- docs/basecoin-tool.rst | 6 +++--- docs/key-management.rst | 2 +- docs/overview.rst | 4 +++- docs/roles-and-multi-sig.rst | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/basecoin-tool.rst b/docs/basecoin-tool.rst index 020c8bb4b886..8572b7dfb99d 100644 --- a/docs/basecoin-tool.rst +++ b/docs/basecoin-tool.rst @@ -274,9 +274,9 @@ Genesis Any required plugin initialization should be constructed using ``SetOption`` on genesis. When starting a new chain for the first time, -``SetOption`` will be called for each item the genesis file. Within -genesis.json file entries are made in the format: +``SetOption`` will be called for each item the genesis file. Within the +``genesis.json`` file entries are made in the format: ``"/", ""``, where ```` is the plugin name, and ```` and ```` are the strings passed into the plugin -SetOption function. This function is intended to be used to set plugin +``SetOption`` function. This function is intended to be used to set plugin specific information such as the plugin state. diff --git a/docs/key-management.rst b/docs/key-management.rst index fdda0cd7b157..ed22bfff43f2 100644 --- a/docs/key-management.rst +++ b/docs/key-management.rst @@ -179,7 +179,7 @@ which prompts for a new password then the seed: alice-again CBF5D9CE6DDCC32806162979495D07B851C53451 and voila! You've recovered your key. Note that the seed can be typed -our, pasted in, or piped into the command alongside the password. +out, pasted in, or piped into the command alongside the password. To change the password of a key, we can: diff --git a/docs/overview.rst b/docs/overview.rst index 22d26c5f8011..3fbf80472d87 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -31,7 +31,7 @@ Signatures - Chain - Nonce - Fees - Roles - Inter-Blockchain-Communication (IBC) As a part of stack execution the state space provided to each middleware -is isolated ``Data Store`` below. When +is isolated in the ``Data Store`` below. When executing the stack, state-recovery checkpoints can be assigned for stack execution of ``CheckTx`` or ``DeliverTx``. This means, that all state changes will be reverted to the checkpoint state on failure when @@ -42,6 +42,8 @@ end business logic fails; under this situation we would add the business logic. This diagram displays a typical process flow through an execution stack. + + Dispatcher ~~~~~~~~~~ diff --git a/docs/roles-and-multi-sig.rst b/docs/roles-and-multi-sig.rst index 1681d7653192..9b7b528591d1 100644 --- a/docs/roles-and-multi-sig.rst +++ b/docs/roles-and-multi-sig.rst @@ -61,7 +61,7 @@ multi-sig wallet. Let's look a the command and dissect it below: In the first part we are sending a transaction that creates a role, rather than transfering coins. The ``--role`` flag is the name of the -role (in hex only) and must be in double quotes. The ``--min-sigs`` and +role (in hex only). The ``--min-sigs`` and ``--members`` define your multi-sig parameters. Here, we require a minimum of 2 signatures out of 3 members but we could easily say 3 of 5 or 9 of 10, or whatever your application requires. The ``--members`` From 422e67b382bee923ceb8048db639754a26bee184 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Oct 2017 14:32:22 +0200 Subject: [PATCH 019/117] 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 01740b63af0f..08bbc45ed632 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 a4f4ff1ea05d..70184bea6302 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 ad7e4e7c69fd..54c597f60146 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 ebf2ebc0dc24..03ad9bf18fe6 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 d29ea726904b..7219ecc544a7 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 b816c876fa28..2ab75b2df830 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 020/117] 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 2ad14915ab07..a19aa968c943 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 2373d27d3bb3..b301438305e1 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 9866195b4e76..3e4fdb724b34 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 021/117] 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 a19aa968c943..24b465ee9d78 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 08bbc45ed632..8e1284c48d0d 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 13dae0ea856e..4412d3e100a3 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 70184bea6302..c6c05894381d 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 f8031ee8384f..8faff5599b43 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 d55f6db4870d..40a42df725f4 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 ca0cced01352..c1e0d9f55039 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 49250d5e2efd..443cc94080fd 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 6e71e88c6bdc..aa6865d92368 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 e4fec6953f11..fb1da6506764 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 e4652638eab9..860f7b3aacde 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 b27e7512fd83..3a3077616e58 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 fb2b077cf86e..5fbc22405d42 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 022/117] 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 2ae46fce17ec..853aab4b4849 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 b7a4ea9834d2..2b6b3679e39d 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 023/117] 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 45ab13b27338..b43d5793c15a 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 2d2c86de6a4a..e840cbb91c0a 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 c091b32e7feb..1d85f94ccc58 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 1dece90ec96c..77d5f169d10d 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 53eebbe12fea..f1c9a4c05d74 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 f1e52b0acd26..bd3b0dc7fa5d 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 2b6b3679e39d..aaeaca500c63 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 024/117] 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 e840cbb91c0a..076e08e3e4af 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 443cc94080fd..6deaf4494186 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 3a3077616e58..f22601951a65 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 025/117] 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 b43d5793c15a..f5fdf29a57e1 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 026/117] 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 f5fdf29a57e1..ef9c8f6fdc54 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 fcf169aebc69..09ffabb14241 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 89a86d0672c1..c2dc9ec83588 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 027/117] 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 ef9c8f6fdc54..275f4aeae4f5 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 028/117] 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 7219ecc544a7..6f0a9bda06e3 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 029/117] 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 54c597f60146..cdd2ba1eb74e 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 030/117] 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 67bc32ef1db0..a3a937efd37a 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 031/117] 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 a3a937efd37a..e447ac0bc4af 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 032/117] 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 c5e48802293d..39f205f0f7e6 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 24b465ee9d78..faa0d77ce83d 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 cdd2ba1eb74e..9702ff2b447a 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 b301438305e1..7bfabc43752c 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 033/117] 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 9702ff2b447a..2bd6a7394151 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 03ad9bf18fe6..258c028e44f7 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 From 7fad21d800c79000dd102d50cef8e51dfffa67fa Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 20 Oct 2017 19:51:01 +0200 Subject: [PATCH 034/117] Use own ErrNoData, not from light-client --- client/errors.go | 22 ++++++++++++++++++++++ client/errors_test.go | 18 ++++++++++++++++++ client/query.go | 4 ++-- client/query_test.go | 6 +++--- modules/coin/commands/query.go | 5 ++--- modules/coin/rest/handlers.go | 4 ++-- modules/nonce/commands/query.go | 5 ++--- modules/nonce/rest/handlers.go | 4 ++-- 8 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 client/errors.go create mode 100644 client/errors_test.go diff --git a/client/errors.go b/client/errors.go new file mode 100644 index 000000000000..9f69f5e12902 --- /dev/null +++ b/client/errors.go @@ -0,0 +1,22 @@ +package client + +import ( + "fmt" + + "github.com/pkg/errors" +) + +//-------------------------------------------- + +var errNoData = fmt.Errorf("No data returned for query") + +// IsNoDataErr checks whether an error is due to a query returning empty data +func IsNoDataErr(err error) bool { + return errors.Cause(err) == errNoData +} + +func ErrNoData() error { + return errors.WithStack(errNoData) +} + +//-------------------------------------------- diff --git a/client/errors_test.go b/client/errors_test.go new file mode 100644 index 000000000000..c561c35b7af8 --- /dev/null +++ b/client/errors_test.go @@ -0,0 +1,18 @@ +package client + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestErrorNoData(t *testing.T) { + e1 := ErrNoData() + e1.Error() + assert.True(t, IsNoDataErr(e1)) + + e2 := errors.New("foobar") + assert.False(t, IsNoDataErr(e2)) + assert.False(t, IsNoDataErr(nil)) +} diff --git a/client/query.go b/client/query.go index c6c05894381d..96da9bc22c50 100644 --- a/client/query.go +++ b/client/query.go @@ -38,7 +38,7 @@ func GetWithProof(key []byte, reqHeight int, node client.Client, return } if len(resp.Key) == 0 || len(resp.Proof) == 0 { - err = lc.ErrNoData() + err = ErrNoData() return } if resp.Height == 0 { @@ -84,7 +84,7 @@ func GetWithProof(key []byte, reqHeight int, node client.Client, err = errors.Wrap(err, "Couldn't verify proof") return } - err = lc.ErrNoData() + err = ErrNoData() proof = aproof } diff --git a/client/query_test.go b/client/query_test.go index 8faff5599b43..a3b945ba4a01 100644 --- a/client/query_test.go +++ b/client/query_test.go @@ -9,14 +9,14 @@ import ( "github.com/stretchr/testify/require" "github.com/tendermint/go-wire" - lc "github.com/tendermint/light-client" "github.com/tendermint/light-client/certifiers" certclient "github.com/tendermint/light-client/certifiers/client" + "github.com/tendermint/tmlibs/log" + nm "github.com/tendermint/tendermint/node" "github.com/tendermint/tendermint/rpc/client" rpctest "github.com/tendermint/tendermint/rpc/test" "github.com/tendermint/tendermint/types" - "github.com/tendermint/tmlibs/log" sdkapp "github.com/cosmos/cosmos-sdk/app" "github.com/cosmos/cosmos-sdk/modules/eyes" @@ -98,7 +98,7 @@ func TestAppProofs(t *testing.T) { // Test non-existing key. missing := []byte("my-missing-key") bs, _, proof, err = GetWithProof(missing, 0, cl, cert) - require.True(lc.IsNoDataErr(err)) + require.True(IsNoDataErr(err)) require.Nil(bs) require.NotNil(proof) err = proof.Verify(missing, nil, rootHash) diff --git a/modules/coin/commands/query.go b/modules/coin/commands/query.go index c1e0d9f55039..1b13bdd2ac06 100644 --- a/modules/coin/commands/query.go +++ b/modules/coin/commands/query.go @@ -5,8 +5,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - lc "github.com/tendermint/light-client" - + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/commands" "github.com/cosmos/cosmos-sdk/client/commands/query" "github.com/cosmos/cosmos-sdk/modules/coin" @@ -35,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, query.GetHeight(), prove) - if lc.IsNoDataErr(err) { + if client.IsNoDataErr(err) { return errors.Errorf("Account bytes are empty for address %s ", addr) } else if err != nil { return err diff --git a/modules/coin/rest/handlers.go b/modules/coin/rest/handlers.go index 6deaf4494186..a7362c706dcc 100644 --- a/modules/coin/rest/handlers.go +++ b/modules/coin/rest/handlers.go @@ -10,6 +10,7 @@ import ( "github.com/spf13/viper" sdk "github.com/cosmos/cosmos-sdk" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/commands" "github.com/cosmos/cosmos-sdk/client/commands/query" "github.com/cosmos/cosmos-sdk/modules/auth" @@ -18,7 +19,6 @@ import ( "github.com/cosmos/cosmos-sdk/modules/fee" "github.com/cosmos/cosmos-sdk/modules/nonce" "github.com/cosmos/cosmos-sdk/stack" - lightclient "github.com/tendermint/light-client" "github.com/tendermint/tmlibs/common" ) @@ -62,7 +62,7 @@ func doQueryAccount(w http.ResponseWriter, r *http.Request) { account := new(coin.Account) prove := !viper.GetBool(commands.FlagTrustNode) height, err := query.GetParsed(key, account, h, prove) - if lightclient.IsNoDataErr(err) { + if client.IsNoDataErr(err) { err := fmt.Errorf("account bytes are empty for address: %q", signature) common.WriteError(w, err) return diff --git a/modules/nonce/commands/query.go b/modules/nonce/commands/query.go index 860f7b3aacde..7021c8ca5a2c 100644 --- a/modules/nonce/commands/query.go +++ b/modules/nonce/commands/query.go @@ -7,9 +7,8 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - lc "github.com/tendermint/light-client" - sdk "github.com/cosmos/cosmos-sdk" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/commands" "github.com/cosmos/cosmos-sdk/client/commands/query" "github.com/cosmos/cosmos-sdk/modules/nonce" @@ -46,7 +45,7 @@ func doNonceQuery(signers []sdk.Actor) (sequence uint32, height uint64, err erro key := stack.PrefixedKey(nonce.NameNonce, nonce.GetSeqKey(signers)) prove := !viper.GetBool(commands.FlagTrustNode) height, err = query.GetParsed(key, &sequence, query.GetHeight(), prove) - if lc.IsNoDataErr(err) { + if client.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 f22601951a65..05c0b2cd899c 100644 --- a/modules/nonce/rest/handlers.go +++ b/modules/nonce/rest/handlers.go @@ -9,6 +9,7 @@ import ( "github.com/spf13/viper" sdk "github.com/cosmos/cosmos-sdk" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/commands" "github.com/cosmos/cosmos-sdk/client/commands/query" "github.com/cosmos/cosmos-sdk/errors" @@ -16,7 +17,6 @@ import ( "github.com/cosmos/cosmos-sdk/modules/nonce" "github.com/cosmos/cosmos-sdk/stack" wire "github.com/tendermint/go-wire" - lightclient "github.com/tendermint/light-client" "github.com/tendermint/tmlibs/common" ) @@ -48,7 +48,7 @@ func doQueryNonce(w http.ResponseWriter, r *http.Request) { // query sequence number data, height, err := query.Get(key, h, prove) - if lightclient.IsNoDataErr(err) { + if client.IsNoDataErr(err) { err = fmt.Errorf("nonce empty for address: %q", signature) common.WriteError(w, err) return From b5320748e684252ec8c79446726ba5bf513b6d7f Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 20 Oct 2017 19:56:09 +0200 Subject: [PATCH 035/117] Update to reorged light-client --- glide.lock | 9 +++++---- glide.yaml | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/glide.lock b/glide.lock index 2bd6a7394151..eb6f737079ee 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: fbfdd03c0367bb0785ceb81ed34059df219e55d5a9c71c12597e505fbce14165 -updated: 2017-10-23T14:49:22.891642342+02:00 +hash: 01d77eb5791b8963db5ecffcf2c59d3dff7fdab5f627f0260b0c4c298fa3f7e8 +updated: 2017-10-23T15:01:08.294460953+02:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -135,14 +135,15 @@ imports: - name: github.com/tendermint/iavl version: 721710e7aa59f61dbfbf558943a207ba3fe6b926 - name: github.com/tendermint/light-client - version: 569e1583da8a52e499764533f3a05d05be6d56d6 + version: e12516078a89df78ce223ea21a1b82455fd0bc15 subpackages: - certifiers - certifiers/client + - certifiers/errors - certifiers/files - proofs - name: github.com/tendermint/tendermint - version: fa56e8c0ce463f77c87ab17a3d7cf5431d9f2c0b + version: 60b7f2c61b921ef5b760f07f6034e5167396d601 subpackages: - blockchain - cmd/tendermint/commands diff --git a/glide.yaml b/glide.yaml index 258c028e44f7..69be9303f448 100644 --- a/glide.yaml +++ b/glide.yaml @@ -20,7 +20,7 @@ import: subpackages: - data - package: github.com/tendermint/light-client - version: develop + version: feature/make-certifiers-stand-alone subpackages: - proofs - certifiers From 1f897cabdef81dbac331752a53597575c4023af0 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 20 Oct 2017 20:05:07 +0200 Subject: [PATCH 036/117] Fix light-client imports --- client/common.go | 15 +++++++++------ client/query.go | 21 +++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/client/common.go b/client/common.go index f2c0d01412a8..af3a662c2824 100644 --- a/client/common.go +++ b/client/common.go @@ -5,8 +5,11 @@ import ( "github.com/tendermint/light-client/certifiers" certclient "github.com/tendermint/light-client/certifiers/client" + certerr "github.com/tendermint/light-client/certifiers/errors" "github.com/tendermint/light-client/certifiers/files" + "github.com/tendermint/light-client/proofs" + rpcclient "github.com/tendermint/tendermint/rpc/client" ) @@ -18,7 +21,7 @@ func GetNode(url string) rpcclient.Client { // GetRPCProvider retuns a certifier compatible data source using // tendermint RPC func GetRPCProvider(url string) certifiers.Provider { - return certclient.NewHTTP(url) + return certclient.NewHTTPProvider(url) } // GetLocalProvider returns a reference to a file store of headers @@ -33,11 +36,11 @@ func GetLocalProvider(dir string) certifiers.Provider { // GetCertifier initializes an inquiring certifier given a fixed chainID // and a local source of trusted data with at least one seed func GetCertifier(chainID string, trust certifiers.Provider, - source certifiers.Provider) (*certifiers.InquiringCertifier, error) { + source certifiers.Provider) (*certifiers.Inquiring, error) { // this gets the most recent verified seed - seed, err := certifiers.LatestSeed(trust) - if certifiers.IsSeedNotFoundErr(err) { + seed, err := trust.LatestCommit() + if certerr.IsCommitNotFoundErr(err) { return nil, errors.New("Please run init first to establish a root of trust") } if err != nil { @@ -49,6 +52,6 @@ func GetCertifier(chainID string, trust certifiers.Provider, // SecureClient uses a given certifier to wrap an connection to an untrusted // host and return a cryptographically secure rpc client. -func SecureClient(c rpcclient.Client, cert *certifiers.InquiringCertifier) rpcclient.Client { - return certclient.Wrap(c, cert) +func SecureClient(c rpcclient.Client, cert *certifiers.Inquiring) rpcclient.Client { + return proofs.Wrap(c, cert) } diff --git a/client/query.go b/client/query.go index 96da9bc22c50..5aa1e5205ac1 100644 --- a/client/query.go +++ b/client/query.go @@ -5,8 +5,8 @@ import ( "github.com/tendermint/go-wire/data" "github.com/tendermint/iavl" - lc "github.com/tendermint/light-client" "github.com/tendermint/light-client/certifiers" + certerr "github.com/tendermint/light-client/certifiers/errors" "github.com/tendermint/tendermint/rpc/client" ) @@ -47,7 +47,7 @@ func GetWithProof(key []byte, reqHeight int, node client.Client, } // AppHash for height H is in header H+1 - var check lc.Checkpoint + var check *certifiers.Commit check, err = GetCertifiedCheckpoint(int(resp.Height+1), node, cert) if err != nil { return @@ -95,25 +95,22 @@ func GetWithProof(key []byte, reqHeight int, node client.Client, // GetCertifiedCheckpoint gets the signed header for a given height // and certifies it. Returns error if unable to get a proven header. func GetCertifiedCheckpoint(h int, node client.Client, - cert certifiers.Certifier) (empty lc.Checkpoint, err error) { + cert certifiers.Certifier) (empty *certifiers.Commit, err error) { // FIXME: cannot use cert.GetByHeight for now, as it also requires // Validators and will fail on querying tendermint for non-current height. // When this is supported, we should use it instead... client.WaitForHeight(node, h, nil) - commit, err := node.Commit(&h) + cresp, err := node.Commit(&h) if err != nil { return } - check := lc.Checkpoint{ - Header: commit.Header, - Commit: commit.Commit, - } + commit := certifiers.CommitFromResult(cresp) // validate downloaded checkpoint with our request and trust store. - if check.Height() != h { - return empty, lc.ErrHeightMismatch(h, check.Height()) + if commit.Height() != h { + return empty, certerr.ErrHeightMismatch(h, commit.Height()) } - err = cert.Certify(check) - return check, nil + err = cert.Certify(commit) + return commit, nil } From 624133ad929f986e35f69b0b437bf6f0ff5745be Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 20 Oct 2017 20:27:18 +0200 Subject: [PATCH 037/117] Fix lot more lightclient imports --- client/commands/common.go | 2 +- client/commands/init.go | 16 ++++++++-------- client/commands/query/get.go | 2 ++ client/commands/seeds/export.go | 6 ++++-- client/commands/seeds/import.go | 12 ++++++------ client/commands/seeds/show.go | 25 +++++++++++++------------ client/commands/seeds/update.go | 16 ++++++++-------- 7 files changed, 42 insertions(+), 37 deletions(-) diff --git a/client/commands/common.go b/client/commands/common.go index ef8827a99021..c51dbb469bd1 100644 --- a/client/commands/common.go +++ b/client/commands/common.go @@ -74,7 +74,7 @@ func GetProviders() (trusted certifiers.Provider, source certifiers.Provider) { } // GetCertifier constructs a dynamic certifier from the config info -func GetCertifier() (*certifiers.InquiringCertifier, error) { +func GetCertifier() (*certifiers.Inquiring, error) { // load up the latest store.... trust := GetTrustedProvider() source := GetSourceProvider() diff --git a/client/commands/init.go b/client/commands/init.go index a54dbb699335..dc3b0021048b 100644 --- a/client/commands/init.go +++ b/client/commands/init.go @@ -280,14 +280,14 @@ func initSeed() (err error) { trust, source := GetProviders() // load a seed file, or get data from the provider - var seed certifiers.Seed + var seed certifiers.FullCommit seedFile := viper.GetString(SeedFlag) if seedFile == "" { fmt.Println("Loading validator set from tendermint rpc...") - seed, err = certifiers.LatestSeed(source) + seed, err = source.LatestCommit() } else { fmt.Printf("Loading validators from file %s\n", seedFile) - seed, err = certifiers.LoadSeed(seedFile) + seed, err = files.LoadFullCommit(seedFile) } // can't load the seed? abort! if err != nil { @@ -305,8 +305,8 @@ func initSeed() (err error) { if hash != "" { var hashb []byte hashb, err = hex.DecodeString(hash) - if err == nil && !bytes.Equal(hashb, seed.Hash()) { - err = errors.Errorf("Seed hash doesn't match expectation: %X", seed.Hash()) + if err == nil && !bytes.Equal(hashb, seed.ValidatorsHash()) { + err = errors.Errorf("Seed hash doesn't match expectation: %X", seed.ValidatorsHash()) } } else { err = validateHash(seed) @@ -317,14 +317,14 @@ func initSeed() (err error) { } // if accepted, store seed as current state - trust.StoreSeed(seed) + trust.StoreCommit(seed) return nil } -func validateHash(seed certifiers.Seed) error { +func validateHash(seed certifiers.FullCommit) error { // ask the user to verify the validator hash fmt.Println("\nImportant: if this is incorrect, all interaction with the chain will be insecure!") - fmt.Printf(" Given validator hash valid: %X\n", seed.Hash()) + fmt.Printf(" Given validator hash valid: %X\n", seed.ValidatorsHash()) fmt.Println("Is this valid (y/n)?") valid := askForConfirmation() if !valid { diff --git a/client/commands/query/get.go b/client/commands/query/get.go index 8e1284c48d0d..f597cd8bb101 100644 --- a/client/commands/query/get.go +++ b/client/commands/query/get.go @@ -14,6 +14,8 @@ import ( "github.com/tendermint/light-client/proofs" rpcclient "github.com/tendermint/tendermint/rpc/client" + rpcclient "github.com/tendermint/tendermint/rpc/client" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/commands" ) diff --git a/client/commands/seeds/export.go b/client/commands/seeds/export.go index ec381246bd9e..0eeaed01f2dc 100644 --- a/client/commands/seeds/export.go +++ b/client/commands/seeds/export.go @@ -5,6 +5,8 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + "github.com/tendermint/light-client/certifiers/files" + "github.com/cosmos/cosmos-sdk/client/commands" ) @@ -34,11 +36,11 @@ func exportSeed(cmd *cobra.Command, args []string) error { trust, _ := commands.GetProviders() h := viper.GetInt(heightFlag) hash := viper.GetString(hashFlag) - seed, err := loadSeed(trust, h, hash, "") + fc, err := loadCommit(trust, h, hash, "") if err != nil { return err } // now get the output file and write it - return seed.WriteJSON(path) + return files.SaveFullCommitJSON(fc, path) } diff --git a/client/commands/seeds/import.go b/client/commands/seeds/import.go index d231f4c3b58f..d115463c8369 100644 --- a/client/commands/seeds/import.go +++ b/client/commands/seeds/import.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/light-client/certifiers" + "github.com/tendermint/light-client/certifiers/files" "github.com/cosmos/cosmos-sdk/client/commands" ) @@ -42,18 +42,18 @@ func importSeed(cmd *cobra.Command, args []string) error { // parse the input file path := args[0] - seed, err := certifiers.LoadSeedJSON(path) + fc, err := files.LoadFullCommitJSON(path) if err != nil { return err } // just do simple checks in --dry-run if viper.GetBool(dryFlag) { - fmt.Printf("Testing seed %d/%X\n", seed.Height(), seed.Hash()) - err = seed.ValidateBasic(cert.ChainID()) + fmt.Printf("Testing commit %d/%X\n", fc.Height(), fc.ValidatorsHash()) + err = fc.ValidateBasic(cert.ChainID()) } else { - fmt.Printf("Importing seed %d/%X\n", seed.Height(), seed.Hash()) - err = cert.Update(seed.Checkpoint, seed.Validators) + fmt.Printf("Importing commit %d/%X\n", fc.Height(), fc.ValidatorsHash()) + err = cert.Update(fc) } return err } diff --git a/client/commands/seeds/show.go b/client/commands/seeds/show.go index 852cb0b82cef..953548a1a020 100644 --- a/client/commands/seeds/show.go +++ b/client/commands/seeds/show.go @@ -9,6 +9,7 @@ import ( "github.com/spf13/viper" "github.com/tendermint/light-client/certifiers" + "github.com/tendermint/light-client/certifiers/files" "github.com/cosmos/cosmos-sdk/client/commands" ) @@ -21,11 +22,11 @@ const ( var showCmd = &cobra.Command{ Use: "show", - Short: "Show the details of one selected seed", + Short: "Show the details of one selected commit", Long: `Shows the most recent downloaded key by default. If desired, you can select by height, validator hash, or a file. `, - RunE: commands.RequireInit(showSeed), + RunE: commands.RequireInit(showCommit), SilenceUsage: true, } @@ -36,38 +37,38 @@ func init() { RootCmd.AddCommand(showCmd) } -func loadSeed(p certifiers.Provider, h int, hash, file string) (seed certifiers.Seed, err error) { - // load the seed from the proper place +func loadCommit(p certifiers.Provider, h int, hash, file string) (fc certifiers.FullCommit, err error) { + // load the commit from the proper place if h != 0 { - seed, err = p.GetByHeight(h) + fc, err = p.GetByHeight(h) } else if hash != "" { var vhash []byte vhash, err = hex.DecodeString(hash) if err == nil { - seed, err = p.GetByHash(vhash) + fc, err = p.GetByHash(vhash) } } else if file != "" { - seed, err = certifiers.LoadSeedJSON(file) + fc, err = files.LoadFullCommitJSON(file) } else { - // default is latest seed - seed, err = certifiers.LatestSeed(p) + // default is latest commit + fc, err = p.LatestCommit() } return } -func showSeed(cmd *cobra.Command, args []string) error { +func showCommit(cmd *cobra.Command, args []string) error { trust, _ := commands.GetProviders() h := viper.GetInt(heightFlag) hash := viper.GetString(hashFlag) file := viper.GetString(fileFlag) - seed, err := loadSeed(trust, h, hash, file) + fc, err := loadCommit(trust, h, hash, file) if err != nil { return err } // now render it! - data, err := json.MarshalIndent(seed, "", " ") + data, err := json.MarshalIndent(fc, "", " ") fmt.Println(string(data)) return err } diff --git a/client/commands/seeds/update.go b/client/commands/seeds/update.go index df2a9621087c..4d99c59bd133 100644 --- a/client/commands/seeds/update.go +++ b/client/commands/seeds/update.go @@ -13,8 +13,8 @@ import ( var updateCmd = &cobra.Command{ Use: "update", - Short: "Update seed to current height if possible", - RunE: commands.RequireInit(updateSeed), + Short: "Update commit to current height if possible", + RunE: commands.RequireInit(updateCommit), SilenceUsage: true, } @@ -23,27 +23,27 @@ func init() { RootCmd.AddCommand(updateCmd) } -func updateSeed(cmd *cobra.Command, args []string) error { +func updateCommit(cmd *cobra.Command, args []string) error { cert, err := commands.GetCertifier() if err != nil { return err } h := viper.GetInt(heightFlag) - var seed certifiers.Seed + var fc certifiers.FullCommit if h <= 0 { // get the lastest from our source - seed, err = certifiers.LatestSeed(cert.SeedSource) + fc, err = cert.Source.LatestCommit() } else { - seed, err = cert.SeedSource.GetByHeight(h) + fc, err = cert.Source.GetByHeight(h) } if err != nil { return err } // let the certifier do it's magic to update.... - fmt.Printf("Trying to update to height: %d...\n", seed.Height()) - err = cert.Update(seed.Checkpoint, seed.Validators) + fmt.Printf("Trying to update to height: %d...\n", fc.Height()) + err = cert.Update(fc) if err != nil { return err } From 40bb1fdca50afbe1aeaf389c3c9e46f40267f6d8 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 20 Oct 2017 20:36:12 +0200 Subject: [PATCH 038/117] Update ibc imports --- modules/ibc/commands/tx.go | 6 ++--- modules/ibc/ibc_test.go | 46 ++++++++++++++++++------------------ modules/ibc/provider.go | 12 +++++----- modules/ibc/provider_test.go | 8 +++---- modules/ibc/test_helpers.go | 11 ++++----- modules/ibc/tx.go | 4 ++-- 6 files changed, 43 insertions(+), 44 deletions(-) diff --git a/modules/ibc/commands/tx.go b/modules/ibc/commands/tx.go index 487803ca58cb..7ed4bdfd3013 100644 --- a/modules/ibc/commands/tx.go +++ b/modules/ibc/commands/tx.go @@ -80,13 +80,13 @@ func postPacketTxCmd(cmd *cobra.Command, args []string) error { return txcmd.DoTx(post.Wrap()) } -func readSeed() (seed certifiers.Seed, err error) { +func readSeed() (fc certifiers.FullCommit, err error) { name := viper.GetString(FlagSeed) if name == "" { - return seed, errors.New("You must specify a seed file") + return fc, errors.New("You must specify a commit file") } - err = readFile(name, &seed) + err = readFile(name, &fc) return } diff --git a/modules/ibc/ibc_test.go b/modules/ibc/ibc_test.go index 7300746ca257..c588eca5138d 100644 --- a/modules/ibc/ibc_test.go +++ b/modules/ibc/ibc_test.go @@ -28,19 +28,19 @@ func TestIBCRegister(t *testing.T) { appHash2 := []byte{12, 34, 56, 78} // badSeed doesn't validate - badSeed := genEmptySeed(keys2, "chain-2", 123, appHash, len(keys2)) + badSeed := genEmptyCommit(keys2, "chain-2", 123, appHash, len(keys2)) badSeed.Header.AppHash = appHash2 cases := []struct { - seed certifiers.Seed + seed certifiers.FullCommit checker errors.CheckErr }{ { - genEmptySeed(keys, "chain-1", 100, appHash, len(keys)), + genEmptyCommit(keys, "chain-1", 100, appHash, len(keys)), errors.NoErr, }, { - genEmptySeed(keys, "chain-1", 200, appHash, len(keys)), + genEmptyCommit(keys, "chain-1", 200, appHash, len(keys)), IsAlreadyRegisteredErr, }, { @@ -48,7 +48,7 @@ func TestIBCRegister(t *testing.T) { IsInvalidCommitErr, }, { - genEmptySeed(keys2, "chain-2", 123, appHash2, 5), + genEmptyCommit(keys2, "chain-2", 123, appHash2, 5), errors.NoErr, }, } @@ -78,45 +78,45 @@ func TestIBCRegisterPermissions(t *testing.T) { foobaz := sdk.Actor{App: "foo", Address: []byte("baz")} cases := []struct { - seed certifiers.Seed + seed certifiers.FullCommit registrar sdk.Actor signer sdk.Actor checker errors.CheckErr }{ // no sig, no registrar { - seed: genEmptySeed(keys, "chain-1", 100, appHash, len(keys)), + seed: genEmptyCommit(keys, "chain-1", 100, appHash, len(keys)), checker: errors.NoErr, }, // sig, no registrar { - seed: genEmptySeed(keys, "chain-2", 100, appHash, len(keys)), + seed: genEmptyCommit(keys, "chain-2", 100, appHash, len(keys)), signer: foobaz, checker: errors.NoErr, }, // registrar, no sig { - seed: genEmptySeed(keys, "chain-3", 100, appHash, len(keys)), + seed: genEmptyCommit(keys, "chain-3", 100, appHash, len(keys)), registrar: foobar, checker: errors.IsUnauthorizedErr, }, // registrar, wrong sig { - seed: genEmptySeed(keys, "chain-4", 100, appHash, len(keys)), + seed: genEmptyCommit(keys, "chain-4", 100, appHash, len(keys)), signer: foobaz, registrar: foobar, checker: errors.IsUnauthorizedErr, }, // registrar, wrong sig { - seed: genEmptySeed(keys, "chain-5", 100, appHash, len(keys)), + seed: genEmptyCommit(keys, "chain-5", 100, appHash, len(keys)), signer: baz, registrar: foobar, checker: errors.IsUnauthorizedErr, }, // registrar, proper sig { - seed: genEmptySeed(keys, "chain-6", 100, appHash, len(keys)), + seed: genEmptyCommit(keys, "chain-6", 100, appHash, len(keys)), signer: foobar, registrar: foobar, checker: errors.NoErr, @@ -151,7 +151,7 @@ func TestIBCUpdate(t *testing.T) { keys := certifiers.GenValKeys(7) appHash := []byte{0, 4, 7, 23} start := 100 // initial height - root := genEmptySeed(keys, "chain-1", 100, appHash, len(keys)) + root := genEmptyCommit(keys, "chain-1", 100, appHash, len(keys)) keys2 := keys.Extend(2) keys3 := keys2.Extend(2) @@ -165,47 +165,47 @@ func TestIBCUpdate(t *testing.T) { require.Nil(err, "%+v", err) cases := []struct { - seed certifiers.Seed + seed certifiers.FullCommit checker errors.CheckErr }{ // same validator, higher up { - genEmptySeed(keys, "chain-1", start+50, []byte{22}, len(keys)), + genEmptyCommit(keys, "chain-1", start+50, []byte{22}, len(keys)), errors.NoErr, }, // same validator, between existing (not most recent) { - genEmptySeed(keys, "chain-1", start+5, []byte{15, 43}, len(keys)), + genEmptyCommit(keys, "chain-1", start+5, []byte{15, 43}, len(keys)), errors.NoErr, }, // same validators, before root of trust { - genEmptySeed(keys, "chain-1", start-8, []byte{11, 77}, len(keys)), + genEmptyCommit(keys, "chain-1", start-8, []byte{11, 77}, len(keys)), IsHeaderNotFoundErr, }, // insufficient signatures { - genEmptySeed(keys, "chain-1", start+60, []byte{24}, len(keys)/2), + genEmptyCommit(keys, "chain-1", start+60, []byte{24}, len(keys)/2), IsInvalidCommitErr, }, // unregistered chain { - genEmptySeed(keys, "chain-2", start+60, []byte{24}, len(keys)/2), + genEmptyCommit(keys, "chain-2", start+60, []byte{24}, len(keys)/2), IsNotRegisteredErr, }, // too much change (keys -> keys3) { - genEmptySeed(keys3, "chain-1", start+100, []byte{22}, len(keys3)), + genEmptyCommit(keys3, "chain-1", start+100, []byte{22}, len(keys3)), IsInvalidCommitErr, }, // legit update to validator set (keys -> keys2) { - genEmptySeed(keys2, "chain-1", start+90, []byte{33}, len(keys2)), + genEmptyCommit(keys2, "chain-1", start+90, []byte{33}, len(keys2)), errors.NoErr, }, // now impossible jump works (keys -> keys2 -> keys3) { - genEmptySeed(keys3, "chain-1", start+100, []byte{44}, len(keys3)), + genEmptyCommit(keys3, "chain-1", start+100, []byte{44}, len(keys3)), errors.NoErr, }, } @@ -227,7 +227,7 @@ func TestIBCCreatePacket(t *testing.T) { appHash := []byte{1, 2, 3, 4} start := 100 // initial height chainID := "cosmos-hub" - root := genEmptySeed(keys, chainID, start, appHash, len(keys)) + root := genEmptyCommit(keys, chainID, start, appHash, len(keys)) // create the app and register the root of trust (for chain-1) ctx := stack.MockContext("hub", 50) diff --git a/modules/ibc/provider.go b/modules/ibc/provider.go index e308eb79d47f..7dc2302fee6a 100644 --- a/modules/ibc/provider.go +++ b/modules/ibc/provider.go @@ -17,11 +17,11 @@ const ( // newCertifier loads up the current state of this chain to make a proper certifier // it will load the most recent height before block h if h is positive // if h < 0, it will load the latest height -func newCertifier(store state.SimpleDB, chainID string, h int) (*certifiers.InquiringCertifier, error) { +func newCertifier(store state.SimpleDB, chainID string, h int) (*certifiers.Inquiring, error) { // each chain has their own prefixed subspace p := newDBProvider(store) - var seed certifiers.Seed + var seed certifiers.FullCommit var err error if h > 0 { // this gets the most recent verified seed below the specified height @@ -55,7 +55,7 @@ func newDBProvider(store state.SimpleDB) *dbProvider { var _ certifiers.Provider = &dbProvider{} -func (d *dbProvider) StoreSeed(seed certifiers.Seed) error { +func (d *dbProvider) StoreSeed(seed certifiers.FullCommit) error { // TODO: don't duplicate data.... b := wire.BinaryBytes(seed) d.byHash.Set(seed.Hash(), b) @@ -63,7 +63,7 @@ func (d *dbProvider) StoreSeed(seed certifiers.Seed) error { return nil } -func (d *dbProvider) GetByHeight(h int) (seed certifiers.Seed, err error) { +func (d *dbProvider) GetByHeight(h int) (seed certifiers.FullCommit, err error) { b, _ := d.byHeight.LTE(uint64(h)) if b == nil { return seed, certifiers.ErrSeedNotFound() @@ -72,7 +72,7 @@ func (d *dbProvider) GetByHeight(h int) (seed certifiers.Seed, err error) { return } -func (d *dbProvider) GetByHash(hash []byte) (seed certifiers.Seed, err error) { +func (d *dbProvider) GetByHash(hash []byte) (seed certifiers.FullCommit, err error) { b := d.byHash.Get(hash) if b == nil { return seed, certifiers.ErrSeedNotFound() @@ -83,7 +83,7 @@ func (d *dbProvider) GetByHash(hash []byte) (seed certifiers.Seed, err error) { // GetExactHeight is like GetByHeight, but returns an error instead of // closest match if there is no exact match -func (d *dbProvider) GetExactHeight(h int) (seed certifiers.Seed, err error) { +func (d *dbProvider) GetExactHeight(h int) (seed certifiers.FullCommit, err error) { seed, err = d.GetByHeight(h) if err != nil { return diff --git a/modules/ibc/provider_test.go b/modules/ibc/provider_test.go index 96d0ad0ae198..59d573e456d1 100644 --- a/modules/ibc/provider_test.go +++ b/modules/ibc/provider_test.go @@ -10,7 +10,7 @@ import ( "github.com/tendermint/light-client/certifiers" ) -func assertSeedEqual(t *testing.T, s, s2 certifiers.Seed) { +func assertSeedEqual(t *testing.T, s, s2 certifiers.FullCommit) { assert := assert.New(t) assert.Equal(s.Height(), s2.Height()) assert.Equal(s.Hash(), s2.Hash()) @@ -75,16 +75,16 @@ func TestDBProvider(t *testing.T) { checkProvider(t, p, "test-db", "bling") } -func makeSeeds(keys certifiers.ValKeys, count int, chainID, app string) []certifiers.Seed { +func makeSeeds(keys certifiers.ValKeys, count int, chainID, app string) []certifiers.FullCommit { appHash := []byte(app) - seeds := make([]certifiers.Seed, count) + seeds := make([]certifiers.FullCommit, count) for i := 0; i < count; i++ { // two seeds for each validator, to check how we handle dups // (10, 0), (10, 1), (10, 1), (10, 2), (10, 2), ... vals := keys.ToValidators(10, int64(count/2)) h := 20 + 10*i check := keys.GenCheckpoint(chainID, h, nil, vals, appHash, 0, len(keys)) - seeds[i] = certifiers.Seed{check, vals} + seeds[i] = certifiers.FullCommit{check, vals} } return seeds } diff --git a/modules/ibc/test_helpers.go b/modules/ibc/test_helpers.go index 6f0a9bda06e3..9166a9ab92f0 100644 --- a/modules/ibc/test_helpers.go +++ b/modules/ibc/test_helpers.go @@ -32,7 +32,7 @@ func NewMockChain(chainID string, numKeys int) MockChain { // GetRegistrationTx returns a valid tx to register this chain func (m MockChain) GetRegistrationTx(h int) RegisterChainTx { - seed := genEmptySeed(m.keys, m.chainID, h, m.tree.Hash(), len(m.keys)) + seed := genEmptyCommit(m.keys, m.chainID, h, m.tree.Hash(), len(m.keys)) return RegisterChainTx{seed} } @@ -42,18 +42,17 @@ 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+1, m.tree.Hash(), len(m.keys)) + seed := genEmptyCommit(m.keys, m.chainID, h+1, m.tree.Hash(), len(m.keys)) update := UpdateChainTx{seed} return post, update } -func genEmptySeed(keys certifiers.ValKeys, chain string, h int, - appHash []byte, count int) certifiers.Seed { +func genEmptyCommit(keys certifiers.ValKeys, chain string, h int, + appHash []byte, count int) certifiers.FullCommit { vals := keys.ToValidators(10, 0) - cp := keys.GenCheckpoint(chain, h, nil, vals, appHash, 0, count) - return certifiers.Seed{cp, vals} + return keys.GenFullCommit(chain, h, nil, vals, appHash, 0, count) } func makePostPacket(tree *iavl.Tree, packet Packet, fromID string, fromHeight int) PostPacketTx { diff --git a/modules/ibc/tx.go b/modules/ibc/tx.go index c2dc9ec83588..83eb17eb37ca 100644 --- a/modules/ibc/tx.go +++ b/modules/ibc/tx.go @@ -32,7 +32,7 @@ func init() { // RegisterChainTx allows you to register a new chain on this blockchain type RegisterChainTx struct { - Seed certifiers.Seed `json:"seed"` + Seed certifiers.FullCommit `json:"seed"` } // ChainID helps get the chain this tx refers to @@ -56,7 +56,7 @@ func (r RegisterChainTx) Wrap() sdk.Tx { // UpdateChainTx updates the state of this chain type UpdateChainTx struct { - Seed certifiers.Seed `json:"seed"` + Seed certifiers.FullCommit `json:"seed"` } // ChainID helps get the chain this tx refers to From 1b7bec230d6d83a7849e75b5d6104b6dba92f33c Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 20 Oct 2017 20:50:22 +0200 Subject: [PATCH 039/117] make install works --- client/commands/query/get.go | 1 - modules/ibc/handler.go | 14 +++++----- modules/ibc/provider.go | 50 +++++++++++++++++++++--------------- modules/ibc/tx.go | 12 ++++----- 4 files changed, 43 insertions(+), 34 deletions(-) diff --git a/client/commands/query/get.go b/client/commands/query/get.go index f597cd8bb101..7ffc1c1f5d36 100644 --- a/client/commands/query/get.go +++ b/client/commands/query/get.go @@ -12,7 +12,6 @@ import ( "github.com/tendermint/go-wire/data" "github.com/tendermint/iavl" "github.com/tendermint/light-client/proofs" - rpcclient "github.com/tendermint/tendermint/rpc/client" rpcclient "github.com/tendermint/tendermint/rpc/client" diff --git a/modules/ibc/handler.go b/modules/ibc/handler.go index 63bebc3ed177..66c9b16cb805 100644 --- a/modules/ibc/handler.go +++ b/modules/ibc/handler.go @@ -124,14 +124,14 @@ func (h Handler) initSeed(ctx sdk.Context, store state.SimpleDB, // verify that the header looks reasonable chainID := t.ChainID() s := NewChainSet(store) - err = s.Register(chainID, ctx.BlockHeight(), t.Seed.Height()) + err = s.Register(chainID, ctx.BlockHeight(), t.Commit.Height()) if err != nil { return res, err } space := stack.PrefixedStore(chainID, store) provider := newDBProvider(space) - err = provider.StoreSeed(t.Seed) + err = provider.StoreCommit(t.Commit) return res, err } @@ -147,21 +147,21 @@ func (h Handler) updateSeed(ctx sdk.Context, store state.SimpleDB, } // load the certifier for this chain - seed := t.Seed + fc := t.Commit space := stack.PrefixedStore(chainID, store) - cert, err := newCertifier(space, chainID, seed.Height()) + cert, err := newCertifier(space, chainID, fc.Height()) if err != nil { return res, err } - // this will import the seed if it is valid in the current context - err = cert.Update(seed.Checkpoint, seed.Validators) + // this will import the commit if it is valid in the current context + err = cert.Update(fc) if err != nil { return res, ErrInvalidCommit(err) } // update the tracked height in chain info - err = s.Update(chainID, t.Seed.Height()) + err = s.Update(chainID, fc.Height()) return res, err } diff --git a/modules/ibc/provider.go b/modules/ibc/provider.go index 7dc2302fee6a..712b6ee81daa 100644 --- a/modules/ibc/provider.go +++ b/modules/ibc/provider.go @@ -3,6 +3,7 @@ package ibc import ( wire "github.com/tendermint/go-wire" "github.com/tendermint/light-client/certifiers" + certerr "github.com/tendermint/light-client/certifiers/errors" "github.com/cosmos/cosmos-sdk/stack" "github.com/cosmos/cosmos-sdk/state" @@ -21,22 +22,22 @@ func newCertifier(store state.SimpleDB, chainID string, h int) (*certifiers.Inqu // each chain has their own prefixed subspace p := newDBProvider(store) - var seed certifiers.FullCommit + var fc certifiers.FullCommit var err error if h > 0 { - // this gets the most recent verified seed below the specified height - seed, err = p.GetByHeight(h) + // this gets the most recent verified commit below the specified height + fc, err = p.GetByHeight(h) } else { - // 0 or negative means start at latest seed - seed, err = certifiers.LatestSeed(p) + // 0 or negative means start at latest commit + fc, err = p.LatestCommit() } if err != nil { return nil, ErrHeaderNotFound(h) } // we have no source for untrusted keys, but use the db to load trusted history - cert := certifiers.NewInquiring(chainID, seed, p, - certifiers.MissingProvider{}) + cert := certifiers.NewInquiring(chainID, fc, p, + certifiers.NewMissingProvider()) return cert, nil } @@ -55,40 +56,49 @@ func newDBProvider(store state.SimpleDB) *dbProvider { var _ certifiers.Provider = &dbProvider{} -func (d *dbProvider) StoreSeed(seed certifiers.FullCommit) error { +func (d *dbProvider) StoreCommit(fc certifiers.FullCommit) error { // TODO: don't duplicate data.... - b := wire.BinaryBytes(seed) - d.byHash.Set(seed.Hash(), b) - d.byHeight.Set(uint64(seed.Height()), b) + b := wire.BinaryBytes(fc) + d.byHash.Set(fc.ValidatorsHash(), b) + d.byHeight.Set(uint64(fc.Height()), b) return nil } -func (d *dbProvider) GetByHeight(h int) (seed certifiers.FullCommit, err error) { +func (d *dbProvider) LatestCommit() (fc certifiers.FullCommit, err error) { + b, _ := d.byHeight.Top() + if b == nil { + return fc, certerr.ErrCommitNotFound() + } + err = wire.ReadBinaryBytes(b, &fc) + return +} + +func (d *dbProvider) GetByHeight(h int) (fc certifiers.FullCommit, err error) { b, _ := d.byHeight.LTE(uint64(h)) if b == nil { - return seed, certifiers.ErrSeedNotFound() + return fc, certerr.ErrCommitNotFound() } - err = wire.ReadBinaryBytes(b, &seed) + err = wire.ReadBinaryBytes(b, &fc) return } -func (d *dbProvider) GetByHash(hash []byte) (seed certifiers.FullCommit, err error) { +func (d *dbProvider) GetByHash(hash []byte) (fc certifiers.FullCommit, err error) { b := d.byHash.Get(hash) if b == nil { - return seed, certifiers.ErrSeedNotFound() + return fc, certerr.ErrCommitNotFound() } - err = wire.ReadBinaryBytes(b, &seed) + err = wire.ReadBinaryBytes(b, &fc) return } // GetExactHeight is like GetByHeight, but returns an error instead of // closest match if there is no exact match -func (d *dbProvider) GetExactHeight(h int) (seed certifiers.FullCommit, err error) { - seed, err = d.GetByHeight(h) +func (d *dbProvider) GetExactHeight(h int) (fc certifiers.FullCommit, err error) { + fc, err = d.GetByHeight(h) if err != nil { return } - if seed.Height() != h { + if fc.Height() != h { err = ErrHeaderNotFound(h) } return diff --git a/modules/ibc/tx.go b/modules/ibc/tx.go index 83eb17eb37ca..eae5a38f9425 100644 --- a/modules/ibc/tx.go +++ b/modules/ibc/tx.go @@ -32,17 +32,17 @@ func init() { // RegisterChainTx allows you to register a new chain on this blockchain type RegisterChainTx struct { - Seed certifiers.FullCommit `json:"seed"` + Commit certifiers.FullCommit `json:"seed"` } // ChainID helps get the chain this tx refers to func (r RegisterChainTx) ChainID() string { - return r.Seed.Header.ChainID + return r.Commit.Header.ChainID } // ValidateBasic makes sure this is consistent, without checking the sigs func (r RegisterChainTx) ValidateBasic() error { - err := r.Seed.ValidateBasic(r.ChainID()) + err := r.Commit.ValidateBasic(r.ChainID()) if err != nil { err = ErrInvalidCommit(err) } @@ -56,17 +56,17 @@ func (r RegisterChainTx) Wrap() sdk.Tx { // UpdateChainTx updates the state of this chain type UpdateChainTx struct { - Seed certifiers.FullCommit `json:"seed"` + Commit certifiers.FullCommit `json:"seed"` } // ChainID helps get the chain this tx refers to func (u UpdateChainTx) ChainID() string { - return u.Seed.Header.ChainID + return u.Commit.Header.ChainID } // ValidateBasic makes sure this is consistent, without checking the sigs func (u UpdateChainTx) ValidateBasic() error { - err := u.Seed.ValidateBasic(u.ChainID()) + err := u.Commit.ValidateBasic(u.ChainID()) if err != nil { err = ErrInvalidCommit(err) } From 1c446f4b498d121ee89bd37a36c6ccefa0e11ea9 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 15:09:38 +0200 Subject: [PATCH 040/117] fix client tests --- client/query_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/query_test.go b/client/query_test.go index a3b945ba4a01..cb165bc7c119 100644 --- a/client/query_test.go +++ b/client/query_test.go @@ -59,13 +59,13 @@ func TestAppProofs(t *testing.T) { brh := br.Height // This sets up our trust on the node based on some past point. - source := certclient.New(cl) + source := certclient.NewProvider(cl) seed, err := source.GetByHeight(br.Height - 2) require.NoError(err, "%+v", err) cert := certifiers.NewStatic("my-chain", seed.Validators) client.WaitForHeight(cl, 3, nil) - latest, err := source.GetLatestCommit() + latest, err := source.LatestCommit() require.NoError(err, "%+v", err) rootHash := latest.Header.AppHash @@ -75,7 +75,7 @@ func TestAppProofs(t *testing.T) { // 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.True(IsNoDataErr(err)) require.Nil(bs) // but given that block it is good @@ -122,7 +122,7 @@ func TestTxProofs(t *testing.T) { require.EqualValues(0, br.DeliverTx.Code) fmt.Printf("tx height: %d\n", br.Height) - source := certclient.New(cl) + source := certclient.NewProvider(cl) seed, err := source.GetByHeight(br.Height - 2) require.NoError(err, "%+v", err) cert := certifiers.NewStatic("my-chain", seed.Validators) From c4e87dbf1081116c4ed7c816ea80688fcf5d6c2c Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 15:13:22 +0200 Subject: [PATCH 041/117] Fixed ibc tests --- modules/ibc/provider_test.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/modules/ibc/provider_test.go b/modules/ibc/provider_test.go index 59d573e456d1..597eca875bd8 100644 --- a/modules/ibc/provider_test.go +++ b/modules/ibc/provider_test.go @@ -8,12 +8,13 @@ import ( "github.com/cosmos/cosmos-sdk/state" "github.com/tendermint/light-client/certifiers" + certerr "github.com/tendermint/light-client/certifiers/errors" ) func assertSeedEqual(t *testing.T, s, s2 certifiers.FullCommit) { assert := assert.New(t) assert.Equal(s.Height(), s2.Height()) - assert.Equal(s.Hash(), s2.Hash()) + assert.Equal(s.ValidatorsHash(), s2.ValidatorsHash()) // TODO: more } @@ -31,11 +32,11 @@ func TestProviderStore(t *testing.T) { // check it... _, err := p.GetByHeight(20) require.NotNil(err) - assert.True(certifiers.IsSeedNotFoundErr(err)) + assert.True(certerr.IsCommitNotFoundErr(err)) // add a seed for _, s := range seeds { - err = p.StoreSeed(s) + err = p.StoreCommit(s) require.Nil(err) } @@ -54,16 +55,16 @@ func TestProviderStore(t *testing.T) { // below is nothing _, err = p.GetByHeight(s.Height() - 2) - assert.True(certifiers.IsSeedNotFoundErr(err)) + assert.True(certerr.IsCommitNotFoundErr(err)) // make sure we get highest - val, err = certifiers.LatestSeed(p) + val, err = p.LatestCommit() if assert.Nil(err) { assertSeedEqual(t, seeds[3], val) } // make sure by hash also (note all have same hash, so overwritten) - val, err = p.GetByHash(seeds[1].Hash()) + val, err = p.GetByHash(seeds[1].ValidatorsHash()) if assert.Nil(err) { assertSeedEqual(t, seeds[3], val) } @@ -83,8 +84,7 @@ func makeSeeds(keys certifiers.ValKeys, count int, chainID, app string) []certif // (10, 0), (10, 1), (10, 1), (10, 2), (10, 2), ... vals := keys.ToValidators(10, int64(count/2)) h := 20 + 10*i - check := keys.GenCheckpoint(chainID, h, nil, vals, appHash, 0, len(keys)) - seeds[i] = certifiers.FullCommit{check, vals} + seeds[i] = keys.GenFullCommit(chainID, h, nil, vals, appHash, 0, len(keys)) } return seeds } @@ -100,18 +100,18 @@ func checkProvider(t *testing.T, p certifiers.Provider, chainID, app string) { // check provider is empty seed, err := p.GetByHeight(20) require.NotNil(err) - assert.True(certifiers.IsSeedNotFoundErr(err)) + assert.True(certerr.IsCommitNotFoundErr(err)) - seed, err = p.GetByHash(seeds[3].Hash()) + seed, err = p.GetByHash(seeds[3].ValidatorsHash()) require.NotNil(err) - assert.True(certifiers.IsSeedNotFoundErr(err)) + assert.True(certerr.IsCommitNotFoundErr(err)) // now add them all to the provider for _, s := range seeds { - err = p.StoreSeed(s) + err = p.StoreCommit(s) require.Nil(err) // and make sure we can get it back - s2, err := p.GetByHash(s.Hash()) + s2, err := p.GetByHash(s.ValidatorsHash()) assert.Nil(err) assertSeedEqual(t, s, s2) // by height as well From e635a8ff53b83bc741d8a60963e228011e47d320 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 15:28:10 +0200 Subject: [PATCH 042/117] Fix ibc cli test --- examples/basecoin/tests/cli/ibc.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/basecoin/tests/cli/ibc.sh b/examples/basecoin/tests/cli/ibc.sh index 275f4aeae4f5..51affe6172be 100755 --- a/examples/basecoin/tests/cli/ibc.sh +++ b/examples/basecoin/tests/cli/ibc.sh @@ -125,8 +125,8 @@ test02UpdateChains() { assertTrue "line=${LINENO}, export seed failed" $? assertNewHeight "line=${LINENO}" $ROOT_2 $UPDATE_2 # this is used later to check query data - REGISTER_2_HEIGHT=$(cat $ROOT_2 | jq .checkpoint.header.height) - UPDATE_2_HEIGHT=$(cat $UPDATE_2 | jq .checkpoint.header.height) + REGISTER_2_HEIGHT=$(cat $ROOT_2 | jq .commit.header.height) + UPDATE_2_HEIGHT=$(cat $UPDATE_2 | jq .commit.header.height) # update chain2 on chain1 TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \ @@ -236,7 +236,7 @@ test05ReceiveIBCPacket() { assertTrue "line=${LINENO}, export seed failed" $? if [ -n "$DEBUG" ]; then echo "**** SEED ****" - cat $PACKET_SEED | jq .checkpoint.header + cat $PACKET_SEED | jq .commit.header echo fi @@ -270,9 +270,9 @@ test05ReceiveIBCPacket() { # XXX Ex Usage: assertNewHeight $MSG $SEED_1 $SEED_2 # Desc: Asserts that seed2 has a higher block height than seed 1 assertNewHeight() { - H1=$(cat $2 | jq .checkpoint.header.height) - H2=$(cat $3 | jq .checkpoint.header.height) - assertTrue "$MSG" "test $H2 -gt $H1" + H1=$(cat $2 | jq .commit.header.height) + H2=$(cat $3 | jq .commit.header.height) + assertTrue "$1" "test $H2 -gt $H1" return $? } From 9442e7e04ac8ba0002ce7f30bc55cd9d54b3065a Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 19:24:22 +0200 Subject: [PATCH 043/117] Cleaned up naming of seed->commit --- client/commands/init.go | 44 +++++++++++----------- client/commands/query/tx.go | 2 +- client/common.go | 6 +-- client/query.go | 12 +++--- client/query_test.go | 4 +- modules/ibc/commands/tx.go | 18 ++++----- modules/ibc/handler.go | 12 +++--- modules/ibc/ibc_test.go | 16 ++++---- modules/ibc/provider_test.go | 72 ++++++++++++++++++------------------ modules/ibc/test_helpers.go | 8 ++-- 10 files changed, 97 insertions(+), 97 deletions(-) diff --git a/client/commands/init.go b/client/commands/init.go index dc3b0021048b..807dd1c0b27c 100644 --- a/client/commands/init.go +++ b/client/commands/init.go @@ -29,7 +29,7 @@ var ( //nolint const ( - SeedFlag = "seed" + CommitFlag = "commit" HashFlag = "valhash" GenesisFlag = "genesis" FlagTrustNode = "trust-node" @@ -52,7 +52,7 @@ var ResetCmd = &cobra.Command{ func init() { InitCmd.Flags().Bool("force-reset", false, "Wipe clean an existing client store, except for keys") - InitCmd.Flags().String(SeedFlag, "", "Seed file to import (optional)") + InitCmd.Flags().String(CommitFlag, "", "Commit file to import (optional)") InitCmd.Flags().String(HashFlag, "", "Trusted validator hash (must match to accept)") InitCmd.Flags().String(GenesisFlag, "", "Genesis file with chainid and validators (optional)") } @@ -92,7 +92,7 @@ func doInit(cmd *cobra.Command, root string) error { if err != nil { return err } - err = initSeed() + err = initTrust() return err } @@ -275,27 +275,27 @@ func initConfigFile(cmd *cobra.Command) error { return nil } -func initSeed() (err error) { +func initTrust() (err error) { // create a provider.... trust, source := GetProviders() - // load a seed file, or get data from the provider - var seed certifiers.FullCommit - seedFile := viper.GetString(SeedFlag) - if seedFile == "" { + // load a commit file, or get data from the provider + var fc certifiers.FullCommit + commitFile := viper.GetString(CommitFlag) + if commitFile == "" { fmt.Println("Loading validator set from tendermint rpc...") - seed, err = source.LatestCommit() + fc, err = source.LatestCommit() } else { - fmt.Printf("Loading validators from file %s\n", seedFile) - seed, err = files.LoadFullCommit(seedFile) + fmt.Printf("Loading validators from file %s\n", commitFile) + fc, err = files.LoadFullCommit(commitFile) } - // can't load the seed? abort! + // can't load the commit? abort! if err != nil { return err } - // make sure it is a proper seed - err = seed.ValidateBasic(viper.GetString(ChainFlag)) + // make sure it is a proper commit + err = fc.ValidateBasic(viper.GetString(ChainFlag)) if err != nil { return err } @@ -305,30 +305,30 @@ func initSeed() (err error) { if hash != "" { var hashb []byte hashb, err = hex.DecodeString(hash) - if err == nil && !bytes.Equal(hashb, seed.ValidatorsHash()) { - err = errors.Errorf("Seed hash doesn't match expectation: %X", seed.ValidatorsHash()) + if err == nil && !bytes.Equal(hashb, fc.ValidatorsHash()) { + err = errors.Errorf("Validator hash doesn't match expectation: %X", fc.ValidatorsHash()) } } else { - err = validateHash(seed) + err = validateHash(fc) } if err != nil { return err } - // if accepted, store seed as current state - trust.StoreCommit(seed) + // if accepted, store commit as current state + trust.StoreCommit(fc) return nil } -func validateHash(seed certifiers.FullCommit) error { +func validateHash(fc certifiers.FullCommit) error { // ask the user to verify the validator hash fmt.Println("\nImportant: if this is incorrect, all interaction with the chain will be insecure!") - fmt.Printf(" Given validator hash valid: %X\n", seed.ValidatorsHash()) + fmt.Printf(" Given validator hash valid: %X\n", fc.ValidatorsHash()) fmt.Println("Is this valid (y/n)?") valid := askForConfirmation() if !valid { - return errors.New("Invalid validator hash, try init with proper seed later") + return errors.New("Invalid validator hash, try init with proper commit later") } return nil } diff --git a/client/commands/query/tx.go b/client/commands/query/tx.go index 3826fc932efa..8f86c09bb168 100644 --- a/client/commands/query/tx.go +++ b/client/commands/query/tx.go @@ -52,7 +52,7 @@ func txQueryCmd(cmd *cobra.Command, args []string) error { return err } - check, err := client.GetCertifiedCheckpoint(res.Height, node, cert) + check, err := client.GetCertifiedCommit(res.Height, node, cert) if err != nil { return err } diff --git a/client/common.go b/client/common.go index af3a662c2824..5e79b8afbdb3 100644 --- a/client/common.go +++ b/client/common.go @@ -38,15 +38,15 @@ func GetLocalProvider(dir string) certifiers.Provider { func GetCertifier(chainID string, trust certifiers.Provider, source certifiers.Provider) (*certifiers.Inquiring, error) { - // this gets the most recent verified seed - seed, err := trust.LatestCommit() + // this gets the most recent verified commit + fc, err := trust.LatestCommit() if certerr.IsCommitNotFoundErr(err) { return nil, errors.New("Please run init first to establish a root of trust") } if err != nil { return nil, err } - cert := certifiers.NewInquiring(chainID, seed, trust, source) + cert := certifiers.NewInquiring(chainID, fc, trust, source) return cert, nil } diff --git a/client/query.go b/client/query.go index 5aa1e5205ac1..25b3823d6f53 100644 --- a/client/query.go +++ b/client/query.go @@ -47,8 +47,8 @@ func GetWithProof(key []byte, reqHeight int, node client.Client, } // AppHash for height H is in header H+1 - var check *certifiers.Commit - check, err = GetCertifiedCheckpoint(int(resp.Height+1), node, cert) + var commit *certifiers.Commit + commit, err = GetCertifiedCommit(int(resp.Height+1), node, cert) if err != nil { return } @@ -63,7 +63,7 @@ func GetWithProof(key []byte, reqHeight int, node client.Client, } // Validate the proof against the certified header to ensure data integrity. - err = eproof.Verify(resp.Key, resp.Value, check.Header.AppHash) + err = eproof.Verify(resp.Key, resp.Value, commit.Header.AppHash) if err != nil { err = errors.Wrap(err, "Couldn't verify proof") return @@ -79,7 +79,7 @@ func GetWithProof(key []byte, reqHeight int, node client.Client, return } // Validate the proof against the certified header to ensure data integrity. - err = aproof.Verify(resp.Key, nil, check.Header.AppHash) + err = aproof.Verify(resp.Key, nil, commit.Header.AppHash) if err != nil { err = errors.Wrap(err, "Couldn't verify proof") return @@ -92,9 +92,9 @@ func GetWithProof(key []byte, reqHeight int, node client.Client, return } -// GetCertifiedCheckpoint gets the signed header for a given height +// GetCertifiedCommit gets the signed header for a given height // and certifies it. Returns error if unable to get a proven header. -func GetCertifiedCheckpoint(h int, node client.Client, +func GetCertifiedCommit(h int, node client.Client, cert certifiers.Certifier) (empty *certifiers.Commit, err error) { // FIXME: cannot use cert.GetByHeight for now, as it also requires diff --git a/client/query_test.go b/client/query_test.go index cb165bc7c119..0320176eb357 100644 --- a/client/query_test.go +++ b/client/query_test.go @@ -141,8 +141,8 @@ func TestTxProofs(t *testing.T) { err = res.Proof.Validate(key) assert.NoError(err, "%+v", err) - check, err := GetCertifiedCheckpoint(int(br.Height), cl, cert) + commit, err := GetCertifiedCommit(int(br.Height), cl, cert) require.Nil(err, "%+v", err) - require.Equal(res.Proof.RootHash, check.Header.DataHash) + require.Equal(res.Proof.RootHash, commit.Header.DataHash) } diff --git a/modules/ibc/commands/tx.go b/modules/ibc/commands/tx.go index 7ed4bdfd3013..292658721cff 100644 --- a/modules/ibc/commands/tx.go +++ b/modules/ibc/commands/tx.go @@ -39,36 +39,36 @@ var PostPacketTxCmd = &cobra.Command{ //nolint const ( - FlagSeed = "seed" + FlagCommit = "commit" FlagPacket = "packet" ) func init() { fs1 := RegisterChainTxCmd.Flags() - fs1.String(FlagSeed, "", "Filename with a seed file") + fs1.String(FlagCommit, "", "Filename with a commit file") fs2 := UpdateChainTxCmd.Flags() - fs2.String(FlagSeed, "", "Filename with a seed file") + fs2.String(FlagCommit, "", "Filename with a commit file") fs3 := PostPacketTxCmd.Flags() fs3.String(FlagPacket, "", "Filename with a packet to post") } func registerChainTxCmd(cmd *cobra.Command, args []string) error { - seed, err := readSeed() + fc, err := readCommit() if err != nil { return err } - tx := ibc.RegisterChainTx{seed}.Wrap() + tx := ibc.RegisterChainTx{fc}.Wrap() return txcmd.DoTx(tx) } func updateChainTxCmd(cmd *cobra.Command, args []string) error { - seed, err := readSeed() + fc, err := readCommit() if err != nil { return err } - tx := ibc.UpdateChainTx{seed}.Wrap() + tx := ibc.UpdateChainTx{fc}.Wrap() return txcmd.DoTx(tx) } @@ -80,8 +80,8 @@ func postPacketTxCmd(cmd *cobra.Command, args []string) error { return txcmd.DoTx(post.Wrap()) } -func readSeed() (fc certifiers.FullCommit, err error) { - name := viper.GetString(FlagSeed) +func readCommit() (fc certifiers.FullCommit, err error) { + name := viper.GetString(FlagCommit) if name == "" { return fc, errors.New("You must specify a commit file") } diff --git a/modules/ibc/handler.go b/modules/ibc/handler.go index 66c9b16cb805..47b8c56975ad 100644 --- a/modules/ibc/handler.go +++ b/modules/ibc/handler.go @@ -100,20 +100,20 @@ func (h Handler) DeliverTx(ctx sdk.Context, store state.SimpleDB, tx sdk.Tx) (re switch t := tx.Unwrap().(type) { case RegisterChainTx: - return h.initSeed(ctx, store, t) + return h.registerChain(ctx, store, t) case UpdateChainTx: - return h.updateSeed(ctx, store, t) + return h.updateChain(ctx, store, t) case CreatePacketTx: return h.createPacket(ctx, store, t) } return res, errors.ErrUnknownTxType(tx.Unwrap()) } -// initSeed imports the first seed for this chain and +// registerChain imports the first seed for this chain and // accepts it as the root of trust. // // only the registrar, if set, is allowed to do this -func (h Handler) initSeed(ctx sdk.Context, store state.SimpleDB, +func (h Handler) registerChain(ctx sdk.Context, store state.SimpleDB, t RegisterChainTx) (res sdk.DeliverResult, err error) { info := LoadInfo(store) @@ -135,9 +135,9 @@ func (h Handler) initSeed(ctx sdk.Context, store state.SimpleDB, return res, err } -// updateSeed checks the seed against the existing chain data and rejects it if it +// updateChain checks the seed against the existing chain data and rejects it if it // doesn't fit (or no chain data) -func (h Handler) updateSeed(ctx sdk.Context, store state.SimpleDB, +func (h Handler) updateChain(ctx sdk.Context, store state.SimpleDB, t UpdateChainTx) (res sdk.DeliverResult, err error) { chainID := t.ChainID() diff --git a/modules/ibc/ibc_test.go b/modules/ibc/ibc_test.go index c588eca5138d..ceb92237fdbf 100644 --- a/modules/ibc/ibc_test.go +++ b/modules/ibc/ibc_test.go @@ -27,12 +27,12 @@ func TestIBCRegister(t *testing.T) { appHash := []byte{0, 4, 7, 23} appHash2 := []byte{12, 34, 56, 78} - // badSeed doesn't validate - badSeed := genEmptyCommit(keys2, "chain-2", 123, appHash, len(keys2)) - badSeed.Header.AppHash = appHash2 + // badCommit doesn't validate + badCommit := genEmptyCommit(keys2, "chain-2", 123, appHash, len(keys2)) + badCommit.Header.AppHash = appHash2 cases := []struct { - seed certifiers.FullCommit + fc certifiers.FullCommit checker errors.CheckErr }{ { @@ -44,7 +44,7 @@ func TestIBCRegister(t *testing.T) { IsAlreadyRegisteredErr, }, { - badSeed, + badCommit, IsInvalidCommitErr, }, { @@ -58,7 +58,7 @@ func TestIBCRegister(t *testing.T) { app := stack.New().Dispatch(stack.WrapHandler(NewHandler())) for i, tc := range cases { - tx := RegisterChainTx{tc.seed}.Wrap() + tx := RegisterChainTx{tc.fc}.Wrap() _, err := app.DeliverTx(ctx, store, tx) assert.True(tc.checker(err), "%d: %+v", i, err) } @@ -165,7 +165,7 @@ func TestIBCUpdate(t *testing.T) { require.Nil(err, "%+v", err) cases := []struct { - seed certifiers.FullCommit + fc certifiers.FullCommit checker errors.CheckErr }{ // same validator, higher up @@ -211,7 +211,7 @@ func TestIBCUpdate(t *testing.T) { } for i, tc := range cases { - tx := UpdateChainTx{tc.seed}.Wrap() + tx := UpdateChainTx{tc.fc}.Wrap() _, err := app.DeliverTx(ctx, store, tx) assert.True(tc.checker(err), "%d: %+v", i, err) } diff --git a/modules/ibc/provider_test.go b/modules/ibc/provider_test.go index 597eca875bd8..2318f979652e 100644 --- a/modules/ibc/provider_test.go +++ b/modules/ibc/provider_test.go @@ -11,19 +11,19 @@ import ( certerr "github.com/tendermint/light-client/certifiers/errors" ) -func assertSeedEqual(t *testing.T, s, s2 certifiers.FullCommit) { +func assertCommitsEqual(t *testing.T, fc, fc2 certifiers.FullCommit) { assert := assert.New(t) - assert.Equal(s.Height(), s2.Height()) - assert.Equal(s.ValidatorsHash(), s2.ValidatorsHash()) + assert.Equal(fc.Height(), fc2.Height()) + assert.Equal(fc.ValidatorsHash(), fc2.ValidatorsHash()) // TODO: more } func TestProviderStore(t *testing.T) { assert, require := assert.New(t), require.New(t) - // make a few seeds + // make a few commits keys := certifiers.GenValKeys(2) - seeds := makeSeeds(keys, 4, "some-chain", "demo-store") + commits := makeCommits(keys, 4, "some-chain", "demo-store") // make a provider store := state.NewMemKVStore() @@ -34,39 +34,39 @@ func TestProviderStore(t *testing.T) { require.NotNil(err) assert.True(certerr.IsCommitNotFoundErr(err)) - // add a seed - for _, s := range seeds { - err = p.StoreCommit(s) + // add commits + for _, fc := range commits { + err = p.StoreCommit(fc) require.Nil(err) } // make sure we get it... - s := seeds[0] - val, err := p.GetByHeight(s.Height()) + fc := commits[0] + val, err := p.GetByHeight(fc.Height()) if assert.Nil(err) { - assertSeedEqual(t, s, val) + assertCommitsEqual(t, fc, val) } // make sure we get higher - val, err = p.GetByHeight(s.Height() + 2) + val, err = p.GetByHeight(fc.Height() + 2) if assert.Nil(err) { - assertSeedEqual(t, s, val) + assertCommitsEqual(t, fc, val) } // below is nothing - _, err = p.GetByHeight(s.Height() - 2) + _, err = p.GetByHeight(fc.Height() - 2) assert.True(certerr.IsCommitNotFoundErr(err)) // make sure we get highest val, err = p.LatestCommit() if assert.Nil(err) { - assertSeedEqual(t, seeds[3], val) + assertCommitsEqual(t, commits[3], val) } // make sure by hash also (note all have same hash, so overwritten) - val, err = p.GetByHash(seeds[1].ValidatorsHash()) + val, err = p.GetByHash(commits[1].ValidatorsHash()) if assert.Nil(err) { - assertSeedEqual(t, seeds[3], val) + assertCommitsEqual(t, commits[3], val) } } @@ -76,17 +76,17 @@ func TestDBProvider(t *testing.T) { checkProvider(t, p, "test-db", "bling") } -func makeSeeds(keys certifiers.ValKeys, count int, chainID, app string) []certifiers.FullCommit { +func makeCommits(keys certifiers.ValKeys, count int, chainID, app string) []certifiers.FullCommit { appHash := []byte(app) - seeds := make([]certifiers.FullCommit, count) + commits := make([]certifiers.FullCommit, count) for i := 0; i < count; i++ { - // two seeds for each validator, to check how we handle dups + // two commits for each validator, to check how we handle dups // (10, 0), (10, 1), (10, 1), (10, 2), (10, 2), ... vals := keys.ToValidators(10, int64(count/2)) h := 20 + 10*i - seeds[i] = keys.GenFullCommit(chainID, h, nil, vals, appHash, 0, len(keys)) + commits[i] = keys.GenFullCommit(chainID, h, nil, vals, appHash, 0, len(keys)) } - return seeds + return commits } func checkProvider(t *testing.T, p certifiers.Provider, chainID, app string) { @@ -94,43 +94,43 @@ func checkProvider(t *testing.T, p certifiers.Provider, chainID, app string) { keys := certifiers.GenValKeys(5) count := 10 - // make a bunch of seeds... - seeds := makeSeeds(keys, count, chainID, app) + // make a bunch of commits... + commits := makeCommits(keys, count, chainID, app) // check provider is empty - seed, err := p.GetByHeight(20) + fc, err := p.GetByHeight(20) require.NotNil(err) assert.True(certerr.IsCommitNotFoundErr(err)) - seed, err = p.GetByHash(seeds[3].ValidatorsHash()) + fc, err = p.GetByHash(commits[3].ValidatorsHash()) require.NotNil(err) assert.True(certerr.IsCommitNotFoundErr(err)) // now add them all to the provider - for _, s := range seeds { - err = p.StoreCommit(s) + for _, fc := range commits { + err = p.StoreCommit(fc) require.Nil(err) // and make sure we can get it back - s2, err := p.GetByHash(s.ValidatorsHash()) + fc2, err := p.GetByHash(fc.ValidatorsHash()) assert.Nil(err) - assertSeedEqual(t, s, s2) + assertCommitsEqual(t, fc, fc2) // by height as well - s2, err = p.GetByHeight(s.Height()) + fc2, err = p.GetByHeight(fc.Height()) assert.Nil(err) - assertSeedEqual(t, s, s2) + assertCommitsEqual(t, fc, fc2) } // make sure we get the last hash if we overstep - seed, err = p.GetByHeight(5000) + fc, err = p.GetByHeight(5000) if assert.Nil(err) { - assertSeedEqual(t, seeds[count-1], seed) + assertCommitsEqual(t, commits[count-1], fc) } // and middle ones as well - seed, err = p.GetByHeight(47) + fc, err = p.GetByHeight(47) if assert.Nil(err) { // we only step by 10, so 40 must be the one below this - assert.Equal(40, seed.Height()) + assert.Equal(40, fc.Height()) } } diff --git a/modules/ibc/test_helpers.go b/modules/ibc/test_helpers.go index 9166a9ab92f0..79960dadfbd1 100644 --- a/modules/ibc/test_helpers.go +++ b/modules/ibc/test_helpers.go @@ -32,8 +32,8 @@ func NewMockChain(chainID string, numKeys int) MockChain { // GetRegistrationTx returns a valid tx to register this chain func (m MockChain) GetRegistrationTx(h int) RegisterChainTx { - seed := genEmptyCommit(m.keys, m.chainID, h, m.tree.Hash(), len(m.keys)) - return RegisterChainTx{seed} + fc := genEmptyCommit(m.keys, m.chainID, h, m.tree.Hash(), len(m.keys)) + return RegisterChainTx{fc} } // MakePostPacket commits the packet locally and returns the proof, @@ -42,8 +42,8 @@ func (m MockChain) MakePostPacket(packet Packet, h int) ( PostPacketTx, UpdateChainTx) { post := makePostPacket(m.tree, packet, m.chainID, h) - seed := genEmptyCommit(m.keys, m.chainID, h+1, m.tree.Hash(), len(m.keys)) - update := UpdateChainTx{seed} + fc := genEmptyCommit(m.keys, m.chainID, h+1, m.tree.Hash(), len(m.keys)) + update := UpdateChainTx{fc} return post, update } From 6f87b0a42f3636986d353b31a25e417ecc571f6c Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 19:30:36 +0200 Subject: [PATCH 044/117] Rename seeds command to commits --- client/commands/{seeds => commits}/export.go | 14 +++++++------- client/commands/{seeds => commits}/import.go | 10 +++++----- client/commands/{seeds => commits}/root.go | 10 +++++----- client/commands/{seeds => commits}/show.go | 8 ++++---- client/commands/{seeds => commits}/update.go | 2 +- examples/basecoin/cmd/basecli/main.go | 4 ++-- examples/counter/cmd/countercli/main.go | 4 ++-- examples/eyes/cmd/eyescli/main.go | 4 ++-- 8 files changed, 28 insertions(+), 28 deletions(-) rename client/commands/{seeds => commits}/export.go (66%) rename client/commands/{seeds => commits}/import.go (80%) rename client/commands/{seeds => commits}/root.go (52%) rename client/commands/{seeds => commits}/show.go (85%) rename client/commands/{seeds => commits}/update.go (98%) diff --git a/client/commands/seeds/export.go b/client/commands/commits/export.go similarity index 66% rename from client/commands/seeds/export.go rename to client/commands/commits/export.go index 0eeaed01f2dc..c27826fa7664 100644 --- a/client/commands/seeds/export.go +++ b/client/commands/commits/export.go @@ -1,4 +1,4 @@ -package seeds +package commits import ( "github.com/pkg/errors" @@ -12,21 +12,21 @@ import ( var exportCmd = &cobra.Command{ Use: "export ", - Short: "Export selected seeds to given file", - Long: `Exports the most recent seed to a binary file. + Short: "Export selected commits to given file", + Long: `Exports the most recent commit to a binary file. If desired, you can select by an older height or validator hash. `, - RunE: commands.RequireInit(exportSeed), + RunE: commands.RequireInit(exportCommit), SilenceUsage: true, } func init() { - exportCmd.Flags().Int(heightFlag, 0, "Show the seed with closest height to this") - exportCmd.Flags().String(hashFlag, "", "Show the seed matching the validator hash") + exportCmd.Flags().Int(heightFlag, 0, "Show the commit with closest height to this") + exportCmd.Flags().String(hashFlag, "", "Show the commit matching the validator hash") RootCmd.AddCommand(exportCmd) } -func exportSeed(cmd *cobra.Command, args []string) error { +func exportCommit(cmd *cobra.Command, args []string) error { if len(args) != 1 || len(args[0]) == 0 { return errors.New("You must provide a filepath to output") } diff --git a/client/commands/seeds/import.go b/client/commands/commits/import.go similarity index 80% rename from client/commands/seeds/import.go rename to client/commands/commits/import.go index d115463c8369..936d25b06390 100644 --- a/client/commands/seeds/import.go +++ b/client/commands/commits/import.go @@ -1,4 +1,4 @@ -package seeds +package commits import ( "fmt" @@ -18,9 +18,9 @@ const ( var importCmd = &cobra.Command{ Use: "import ", - Short: "Imports a new seed from the given file", - Long: `Validate this file and update to the given seed if secure.`, - RunE: commands.RequireInit(importSeed), + Short: "Imports a new commit from the given file", + Long: `Validate this file and update to the given commit if secure.`, + RunE: commands.RequireInit(importCommit), SilenceUsage: true, } @@ -29,7 +29,7 @@ func init() { RootCmd.AddCommand(importCmd) } -func importSeed(cmd *cobra.Command, args []string) error { +func importCommit(cmd *cobra.Command, args []string) error { if len(args) != 1 || len(args[0]) == 0 { return errors.New("You must provide an input file") } diff --git a/client/commands/seeds/root.go b/client/commands/commits/root.go similarity index 52% rename from client/commands/seeds/root.go rename to client/commands/commits/root.go index b4fc9d66f6c1..513d86873e40 100644 --- a/client/commands/seeds/root.go +++ b/client/commands/commits/root.go @@ -1,15 +1,15 @@ -package seeds +package commits import "github.com/spf13/cobra" // RootCmd represents the base command when called without any subcommands var RootCmd = &cobra.Command{ - Use: "seeds", - Short: "Verify seeds from your local store", - Long: `Seeds allows you to inspect and update the validator set for the chain. + Use: "commits", + Short: "Verify commits from your local store", + Long: `Commits allows you to inspect and update the validator set for the chain. Since all security in a PoS system is based on having the correct validator -set, it is important to inspect the seeds to maintain the security, which +set, it is important to inspect the commits to maintain the security, which is used to verify all header and merkle proofs. `, } diff --git a/client/commands/seeds/show.go b/client/commands/commits/show.go similarity index 85% rename from client/commands/seeds/show.go rename to client/commands/commits/show.go index 953548a1a020..e9cc6ed28f0c 100644 --- a/client/commands/seeds/show.go +++ b/client/commands/commits/show.go @@ -1,4 +1,4 @@ -package seeds +package commits import ( "encoding/hex" @@ -31,9 +31,9 @@ If desired, you can select by height, validator hash, or a file. } func init() { - showCmd.Flags().Int(heightFlag, 0, "Show the seed with closest height to this") - showCmd.Flags().String(hashFlag, "", "Show the seed matching the validator hash") - showCmd.Flags().String(fileFlag, "", "Show the seed stored in the given file") + showCmd.Flags().Int(heightFlag, 0, "Show the commit with closest height to this") + showCmd.Flags().String(hashFlag, "", "Show the commit matching the validator hash") + showCmd.Flags().String(fileFlag, "", "Show the commit stored in the given file") RootCmd.AddCommand(showCmd) } diff --git a/client/commands/seeds/update.go b/client/commands/commits/update.go similarity index 98% rename from client/commands/seeds/update.go rename to client/commands/commits/update.go index 4d99c59bd133..c42144b61b85 100644 --- a/client/commands/seeds/update.go +++ b/client/commands/commits/update.go @@ -1,4 +1,4 @@ -package seeds +package commits import ( "fmt" diff --git a/examples/basecoin/cmd/basecli/main.go b/examples/basecoin/cmd/basecli/main.go index 6145e8642d35..107890a75e22 100644 --- a/examples/basecoin/cmd/basecli/main.go +++ b/examples/basecoin/cmd/basecli/main.go @@ -9,11 +9,11 @@ import ( "github.com/cosmos/cosmos-sdk/client/commands" "github.com/cosmos/cosmos-sdk/client/commands/auto" + "github.com/cosmos/cosmos-sdk/client/commands/commits" "github.com/cosmos/cosmos-sdk/client/commands/keys" "github.com/cosmos/cosmos-sdk/client/commands/proxy" "github.com/cosmos/cosmos-sdk/client/commands/query" rpccmd "github.com/cosmos/cosmos-sdk/client/commands/rpc" - "github.com/cosmos/cosmos-sdk/client/commands/seeds" txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs" authcmd "github.com/cosmos/cosmos-sdk/modules/auth/commands" basecmd "github.com/cosmos/cosmos-sdk/modules/base/commands" @@ -77,7 +77,7 @@ func main() { commands.InitCmd, commands.ResetCmd, keys.RootCmd, - seeds.RootCmd, + commits.RootCmd, rpccmd.RootCmd, query.RootCmd, txcmd.RootCmd, diff --git a/examples/counter/cmd/countercli/main.go b/examples/counter/cmd/countercli/main.go index 0e7c251e67ac..d2845aefc9b1 100644 --- a/examples/counter/cmd/countercli/main.go +++ b/examples/counter/cmd/countercli/main.go @@ -8,10 +8,10 @@ import ( "github.com/tendermint/tmlibs/cli" "github.com/cosmos/cosmos-sdk/client/commands" + "github.com/cosmos/cosmos-sdk/client/commands/commits" "github.com/cosmos/cosmos-sdk/client/commands/keys" "github.com/cosmos/cosmos-sdk/client/commands/proxy" "github.com/cosmos/cosmos-sdk/client/commands/query" - "github.com/cosmos/cosmos-sdk/client/commands/seeds" txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs" bcount "github.com/cosmos/cosmos-sdk/examples/counter/cmd/countercli/commands" @@ -74,7 +74,7 @@ func main() { commands.ResetCmd, commands.VersionCmd, keys.RootCmd, - seeds.RootCmd, + commits.RootCmd, query.RootCmd, txcmd.RootCmd, proxy.RootCmd, diff --git a/examples/eyes/cmd/eyescli/main.go b/examples/eyes/cmd/eyescli/main.go index 374e59d07421..d23a0e8dc303 100644 --- a/examples/eyes/cmd/eyescli/main.go +++ b/examples/eyes/cmd/eyescli/main.go @@ -9,9 +9,9 @@ import ( "github.com/cosmos/cosmos-sdk/client/commands" "github.com/cosmos/cosmos-sdk/client/commands/auto" + "github.com/cosmos/cosmos-sdk/client/commands/commits" "github.com/cosmos/cosmos-sdk/client/commands/query" rpccmd "github.com/cosmos/cosmos-sdk/client/commands/rpc" - "github.com/cosmos/cosmos-sdk/client/commands/seeds" txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs" eyescmd "github.com/cosmos/cosmos-sdk/modules/eyes/commands" ) @@ -50,7 +50,7 @@ func main() { // we use out own init command to not require address arg commands.InitCmd, commands.ResetCmd, - seeds.RootCmd, + commits.RootCmd, rpccmd.RootCmd, query.RootCmd, txcmd.RootCmd, From 7926a6494d196566f1efbf5c71dd45ea9c6ae163 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 19:35:56 +0200 Subject: [PATCH 045/117] Update ibc test script for new commands --- docs/architecture/API.md | 4 +-- examples/basecoin/tests/cli/ibc.sh | 54 +++++++++++++++--------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/docs/architecture/API.md b/docs/architecture/API.md index ddabc8a8cee2..de4abd0614c9 100644 --- a/docs/architecture/API.md +++ b/docs/architecture/API.md @@ -237,7 +237,7 @@ info about self... } ``` -`/seeds` +`/commits` ``` { @@ -246,4 +246,4 @@ info about self... } ``` -info on last seed +info on last commit diff --git a/examples/basecoin/tests/cli/ibc.sh b/examples/basecoin/tests/cli/ibc.sh index 51affe6172be..ed8a277d96f1 100755 --- a/examples/basecoin/tests/cli/ibc.sh +++ b/examples/basecoin/tests/cli/ibc.sh @@ -84,18 +84,18 @@ test00GetAccount() { } test01RegisterChains() { - # let's get the root seeds to cross-register them - ROOT_1="$BASE_DIR_1/root_seed.json" - ${CLIENT_EXE} seeds export $ROOT_1 --home=${CLIENT_1} - assertTrue "line=${LINENO}, export seed failed" $? + # let's get the root commits to cross-register them + ROOT_1="$BASE_DIR_1/root_commit.json" + ${CLIENT_EXE} commits export $ROOT_1 --home=${CLIENT_1} + assertTrue "line=${LINENO}, export commit failed" $? - ROOT_2="$BASE_DIR_2/root_seed.json" - ${CLIENT_EXE} seeds export $ROOT_2 --home=${CLIENT_2} - assertTrue "line=${LINENO}, export seed failed" $? + ROOT_2="$BASE_DIR_2/root_commit.json" + ${CLIENT_EXE} commits export $ROOT_2 --home=${CLIENT_2} + assertTrue "line=${LINENO}, export commit failed" $? # register chain2 on chain1 TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-register \ - --sequence=1 --seed=${ROOT_2} --name=$POOR --home=${CLIENT_1}) + --sequence=1 --commit=${ROOT_2} --name=$POOR --home=${CLIENT_1}) txSucceeded $? "$TX" "register chain2 on chain 1" # an example to quit early if there is no point in more tests if [ $? != 0 ]; then echo "aborting!"; return 1; fi @@ -104,25 +104,25 @@ test01RegisterChains() { # register chain1 on chain2 (no money needed... yet) TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-register \ - --sequence=1 --seed=${ROOT_1} --name=$POOR --home=${CLIENT_2}) + --sequence=1 --commit=${ROOT_1} --name=$POOR --home=${CLIENT_2}) txSucceeded $? "$TX" "register 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 } test02UpdateChains() { - # let's get the root seeds to cross-register them + # let's get the root commits to cross-register them UPDATE_1="$BASE_DIR_1/seed_1.json" - ${CLIENT_EXE} seeds update --home=${CLIENT_1} > /dev/null - ${CLIENT_EXE} seeds export $UPDATE_1 --home=${CLIENT_1} - assertTrue "line=${LINENO}, export seed failed" $? + ${CLIENT_EXE} commits update --home=${CLIENT_1} > /dev/null + ${CLIENT_EXE} commits export $UPDATE_1 --home=${CLIENT_1} + assertTrue "line=${LINENO}, export commit failed" $? # make sure it is newer than the other.... assertNewHeight "line=${LINENO}" $ROOT_1 $UPDATE_1 UPDATE_2="$BASE_DIR_2/seed_2.json" - ${CLIENT_EXE} seeds update --home=${CLIENT_2} > /dev/null - ${CLIENT_EXE} seeds export $UPDATE_2 --home=${CLIENT_2} - assertTrue "line=${LINENO}, export seed failed" $? + ${CLIENT_EXE} commits update --home=${CLIENT_2} > /dev/null + ${CLIENT_EXE} commits export $UPDATE_2 --home=${CLIENT_2} + assertTrue "line=${LINENO}, export commit failed" $? assertNewHeight "line=${LINENO}" $ROOT_2 $UPDATE_2 # this is used later to check query data REGISTER_2_HEIGHT=$(cat $ROOT_2 | jq .commit.header.height) @@ -130,14 +130,14 @@ test02UpdateChains() { # update chain2 on chain1 TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \ - --sequence=2 --seed=${UPDATE_2} --name=$POOR --home=${CLIENT_1}) + --sequence=2 --commit=${UPDATE_2} --name=$POOR --home=${CLIENT_1}) txSucceeded $? "$TX" "update chain2 on chain 1" # an example to quit early if there is no point in more tests if [ $? != 0 ]; then echo "aborting!"; return 1; fi # update chain1 on chain2 (no money needed... yet) TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \ - --sequence=2 --seed=${UPDATE_1} --name=$POOR --home=${CLIENT_2}) + --sequence=2 --commit=${UPDATE_1} --name=$POOR --home=${CLIENT_2}) txSucceeded $? "$TX" "update 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 @@ -224,24 +224,24 @@ test05ReceiveIBCPacket() { # now, we try to post it.... (this is PACKET from last test) - # get the seed with the proof and post it + # get the commit with the proof and post it SRC_HEIGHT=$(echo $PACKET | jq .src_height) PROOF_HEIGHT=$(expr $SRC_HEIGHT + 1) # FIXME: this should auto-update on proofs... - ${CLIENT_EXE} seeds update --height=$PROOF_HEIGHT --home=${CLIENT_1} > /dev/null - assertTrue "line=${LINENO}, update seed failed" $? + ${CLIENT_EXE} commits update --height=$PROOF_HEIGHT --home=${CLIENT_1} > /dev/null + assertTrue "line=${LINENO}, update commit failed" $? - PACKET_SEED="$BASE_DIR_1/packet_seed.json" - ${CLIENT_EXE} seeds export $PACKET_SEED --home=${CLIENT_1} --height=$PROOF_HEIGHT - assertTrue "line=${LINENO}, export seed failed" $? + PACKET_COMMIT="$BASE_DIR_1/packet_commit.json" + ${CLIENT_EXE} commits export $PACKET_COMMIT --home=${CLIENT_1} --height=$PROOF_HEIGHT + assertTrue "line=${LINENO}, export commit failed" $? if [ -n "$DEBUG" ]; then echo "**** SEED ****" - cat $PACKET_SEED | jq .commit.header + cat $PACKET_COMMIT | jq .commit.header echo fi TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \ - --seed=${PACKET_SEED} --name=$POOR --sequence=3) + --commit=${PACKET_COMMIT} --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 @@ -268,7 +268,7 @@ test05ReceiveIBCPacket() { } # XXX Ex Usage: assertNewHeight $MSG $SEED_1 $SEED_2 -# Desc: Asserts that seed2 has a higher block height than seed 1 +# Desc: Asserts that seed2 has a higher block height than commit 1 assertNewHeight() { H1=$(cat $2 | jq .commit.header.height) H2=$(cat $3 | jq .commit.header.height) From 995feb532cd03afdd56aa8664911f6f2da174a3b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 25 Oct 2017 19:31:29 +0200 Subject: [PATCH 046/117] Update after rebase --- glide.lock | 84 ++++++++++++++++++++---------------- glide.yaml | 2 +- modules/coin/handler_test.go | 2 +- 3 files changed, 50 insertions(+), 38 deletions(-) diff --git a/glide.lock b/glide.lock index eb6f737079ee..e0ea8a99dd39 100644 --- a/glide.lock +++ b/glide.lock @@ -1,22 +1,24 @@ -hash: 01d77eb5791b8963db5ecffcf2c59d3dff7fdab5f627f0260b0c4c298fa3f7e8 -updated: 2017-10-23T15:01:08.294460953+02:00 +hash: fbfdd03c0367bb0785ceb81ed34059df219e55d5a9c71c12597e505fbce14165 +updated: 2017-10-25T19:24:51.90002008+02:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd - name: github.com/btcsuite/btcd - version: b8df516b4b267acf2de46be593a9d948d1d2c420 + version: c7588cbf7690cd9f047a28efa2dcd8f2435a4e5e subpackages: - btcec -- name: github.com/btcsuite/fastsha256 - version: 637e656429416087660c84436a2a035d69d54e2e - name: github.com/BurntSushi/toml version: a368813c5e648fee92e5f6c30e3944ff9d5e8895 - name: github.com/ebuchman/fail-test version: 95f809107225be108efcf10a3509e4ea6ceef3c4 +- name: github.com/ethanfrey/ledger + version: 5e432577be582bd18a3b4a9cd75dae7a317ade36 +- name: github.com/flynn/hid + version: ed06a31c6245d4552e8dbba7e32e5b010b875d65 - name: github.com/fsnotify/fsnotify version: 4da3e2cfbabc9f751898f250b49f2439785783a1 - name: github.com/go-kit/kit - version: d67bb4c202e3b91377d1079b110a6c9ce23ab2f8 + version: e2b298466b32c7cd5579a9b9b07e968fc9d9452c subpackages: - log - log/level @@ -24,18 +26,21 @@ imports: - name: github.com/go-logfmt/logfmt version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 - name: github.com/go-playground/locales - version: 1e5f1161c6416a5ff48840eb8724a394e48cc534 + version: e4cbcb5d0652150d40ad0646651076b6bd2be4f6 subpackages: - currency - name: github.com/go-playground/universal-translator version: 71201497bace774495daed26a3874fd339e0b538 - name: github.com/go-stack/stack - version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 + version: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf - name: github.com/golang/protobuf - version: 18c9bb3261723cd5401db4d0c9fbc5c3b6c70fe8 + version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9 subpackages: - proto + - ptypes - ptypes/any + - ptypes/duration + - ptypes/timestamp - name: github.com/golang/snappy version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/gorilla/context @@ -43,9 +48,9 @@ imports: - name: github.com/gorilla/mux version: 24fca303ac6da784b9e8269f724ddeb0b2eea5e7 - name: github.com/gorilla/websocket - version: a91eba7f97777409bc2c443f5534d41dd20c5720 + version: 71fa72d4842364bc5f74185f4161e0099ea3624a - name: github.com/hashicorp/hcl - version: 392dba7d905ed5d04a5794ba89f558b27e2ba1ca + version: 23c074d0eceb2b8a5bfdbb271ab780cde70f05a8 subpackages: - hcl/ast - hcl/parser @@ -64,11 +69,11 @@ imports: - name: github.com/kr/logfmt version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/magiconair/properties - version: 51463bfca2576e06c62a8504b5c0f06d61312647 + version: 8d7837e64d3c1ee4e54a880c5a920ab4316fc90a - name: github.com/mattn/go-isatty version: a5cdd64afdee435007ee3e9f6ed4684af949d568 - name: github.com/mitchellh/mapstructure - version: cc8532a8e9a55ea36402aa21efdf403a60d34096 + version: 06020f85339e21b2478f756a78e295255ffa4d6a - name: github.com/pelletier/go-buffruneio version: c37440a7cf42ac63b919c752ca73a85067e05992 - name: github.com/pelletier/go-toml @@ -78,21 +83,21 @@ imports: - name: github.com/rcrowley/go-metrics version: 1f30fe9094a513ce4c700b9a54458bbb0c96996c - name: github.com/spf13/afero - version: 9be650865eab0c12963d8753212f4f9c66cdcf12 + version: 5660eeed305fe5f69c8fc6cf899132a459a97064 subpackages: - mem - name: github.com/spf13/cast version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 - name: github.com/spf13/cobra - version: 4cdb38c072b86bf795d2c81de50784d9fdd6eb77 + version: 7b2c5ac9fc04fc5efafb60700713d4fa609b777b - name: github.com/spf13/jwalterweatherman - version: 8f07c835e5cc1450c082fe3a439cf87b0cbb2d99 + version: 12bd96e66386c1960ab0f74ced1362f66f552f7b - name: github.com/spf13/pflag - version: e57e3eeb33f795204c1ca35f56c44f83227c6e66 + version: 97afa5e7ca8a08a383cb259e06636b5e2cc7897f - name: github.com/spf13/viper - version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2 + version: 8ef37cbca71638bf32f3d5e194117d4cb46da163 - name: github.com/syndtr/goleveldb - version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 + version: b89cc31ef7977104127d34c1bd31ebd1a9db2199 subpackages: - leveldb - leveldb/cache @@ -119,7 +124,7 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-crypto - version: 8e7f0e7701f92206679ad093d013b9b162427631 + version: 0a5b1d979a1bc86200c9ff829fbbcd575799a1b6 subpackages: - bcrypt - keys @@ -127,15 +132,16 @@ imports: - keys/storage/filestorage - keys/storage/memstorage - keys/wordlist + - nano - name: github.com/tendermint/go-wire - version: 55ae61f1fc83cfaa57ab7d54250d7a1a2be0b83c + version: 99d2169a1e39c65983eacaa1da867d6f3218e1c9 subpackages: - data - data/base58 - name: github.com/tendermint/iavl - version: 721710e7aa59f61dbfbf558943a207ba3fe6b926 + version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653 - name: github.com/tendermint/light-client - version: e12516078a89df78ce223ea21a1b82455fd0bc15 + version: 76313d625e662ed7b284d066d68ff71edd7a9fac subpackages: - certifiers - certifiers/client @@ -143,7 +149,7 @@ imports: - certifiers/files - proofs - name: github.com/tendermint/tendermint - version: 60b7f2c61b921ef5b760f07f6034e5167396d601 + version: b2d5546cf8f71e0e168072e118d9836862384e6c subpackages: - blockchain - cmd/tendermint/commands @@ -171,7 +177,7 @@ imports: - types - version - name: github.com/tendermint/tmlibs - version: 8e5266a9ef2527e68a1571f932db8228a331b556 + version: 0a652499ead7cd20a57a6a592f0491a2b493bb85 subpackages: - autofile - cli @@ -185,7 +191,7 @@ imports: - logger - merkle - name: golang.org/x/crypto - version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e + version: edd5e9b0879d13ee6970a50153d85b8fec9f7686 subpackages: - blowfish - curve25519 @@ -197,7 +203,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: feeb485667d1fdabe727840fe00adc22431bc86e + version: cd69bc3fc700721b709c3a59e16e24c67b58f6ff subpackages: - context - http2 @@ -207,43 +213,49 @@ imports: - lex/httplex - trace - name: golang.org/x/sys - version: e62c3de784db939836898e5c19ffd41bece347da + version: 8dbc5d05d6edcc104950cc299a1ce6641235bc86 subpackages: - unix - name: golang.org/x/text - version: 470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4 + version: c01e4764d870b77f8abe5096ee19ad20d80e8075 subpackages: - secure/bidirule - transform - unicode/bidi - unicode/norm - name: google.golang.org/genproto - version: 411e09b969b1170a9f0c467558eb4c4c110d9c77 + version: f676e0f3ac6395ff1a529ae59a6670878a8371a6 subpackages: - googleapis/rpc/status - name: google.golang.org/grpc - version: 844f573616520565fdc6fb4db242321b5456fd6d + version: a5986a5c88227370a9c0a82e5277167229c034cd subpackages: + - balancer + - balancer/roundrobin - codes + - connectivity - credentials - - grpclb/grpc_lb_v1 + - grpclb/grpc_lb_v1/messages - grpclog - internal - keepalive - metadata - naming - peer + - resolver + - resolver/dns + - resolver/passthrough - stats - status - tap - transport - name: gopkg.in/go-playground/validator.v9 - version: 6d8c18553ea1ac493d049edd6f102f52e618f085 + version: 1304298bf10d085adec514b076772a79c9cadb6b - name: gopkg.in/yaml.v2 - version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b + version: eb3733d160e74a9c7e442f435eb3bea458e1d19f testImports: - name: github.com/davecgh/go-spew - version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 + version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 subpackages: - spew - name: github.com/pmezard/go-difflib @@ -251,7 +263,7 @@ testImports: subpackages: - difflib - name: github.com/stretchr/testify - version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 + version: 2aa2c176b9dab406a6970f6a55f513e8a8c8b18f subpackages: - assert - require diff --git a/glide.yaml b/glide.yaml index 69be9303f448..258c028e44f7 100644 --- a/glide.yaml +++ b/glide.yaml @@ -20,7 +20,7 @@ import: subpackages: - data - package: github.com/tendermint/light-client - version: feature/make-certifiers-stand-alone + version: develop subpackages: - proofs - certifiers diff --git a/modules/coin/handler_test.go b/modules/coin/handler_test.go index 3df51d8e56b0..20941a860402 100644 --- a/modules/coin/handler_test.go +++ b/modules/coin/handler_test.go @@ -252,7 +252,7 @@ func TestSetIssuer(t *testing.T) { }{ {sdk.Actor{App: "sig", Address: []byte("gwkfgk")}}, // and set back to empty (nil is valid, but assert.Equals doesn't match) - {sdk.Actor{Address: []byte{}}}, + {sdk.Actor{}}, {sdk.Actor{ChainID: "other", App: "role", Address: []byte("vote")}}, } From 2cc53beca73503587d398bb2e7cacc89e74abd99 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 13 Sep 2017 13:47:04 +0200 Subject: [PATCH 047/117] CLI supports creating ledger keys --- client/commands/keys/new.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/commands/keys/new.go b/client/commands/keys/new.go index 0a1a5a607152..f1f422a20aaf 100644 --- a/client/commands/keys/new.go +++ b/client/commands/keys/new.go @@ -42,7 +42,7 @@ passed as a command line argument for security.`, } func init() { - newCmd.Flags().StringP(flagType, "t", "ed25519", "Type of key (ed25519|secp256k1)") + newCmd.Flags().StringP(flagType, "t", "ed25519", "Type of key (ed25519|secp256k1|ledger") newCmd.Flags().Bool(flagNoBackup, false, "Don't print out seed phrase (if others are watching the terminal)") } From 615a257316268cecb410a59cc3e72a0281b370e9 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 26 Oct 2017 16:08:41 +0200 Subject: [PATCH 048/117] Import certifiers from tendermint not light-client --- client/commands/commits/export.go | 2 +- client/commands/commits/import.go | 2 +- client/commands/commits/show.go | 4 ++-- client/commands/commits/update.go | 2 +- client/commands/common.go | 2 +- client/commands/init.go | 4 ++-- client/common.go | 8 ++++---- client/query.go | 4 ++-- client/query_test.go | 4 ++-- glide.lock | 24 ++++++++++++------------ modules/ibc/commands/tx.go | 2 +- modules/ibc/ibc_test.go | 2 +- modules/ibc/provider.go | 4 ++-- modules/ibc/provider_test.go | 4 ++-- modules/ibc/test_helpers.go | 2 +- modules/ibc/tx.go | 2 +- 16 files changed, 36 insertions(+), 36 deletions(-) diff --git a/client/commands/commits/export.go b/client/commands/commits/export.go index c27826fa7664..b0b1c2a64cc2 100644 --- a/client/commands/commits/export.go +++ b/client/commands/commits/export.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/light-client/certifiers/files" + "github.com/tendermint/tendermint/certifiers/files" "github.com/cosmos/cosmos-sdk/client/commands" ) diff --git a/client/commands/commits/import.go b/client/commands/commits/import.go index 936d25b06390..3af3d79e6a4d 100644 --- a/client/commands/commits/import.go +++ b/client/commands/commits/import.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/light-client/certifiers/files" + "github.com/tendermint/tendermint/certifiers/files" "github.com/cosmos/cosmos-sdk/client/commands" ) diff --git a/client/commands/commits/show.go b/client/commands/commits/show.go index e9cc6ed28f0c..67152044c900 100644 --- a/client/commands/commits/show.go +++ b/client/commands/commits/show.go @@ -8,8 +8,8 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/light-client/certifiers" - "github.com/tendermint/light-client/certifiers/files" + "github.com/tendermint/tendermint/certifiers" + "github.com/tendermint/tendermint/certifiers/files" "github.com/cosmos/cosmos-sdk/client/commands" ) diff --git a/client/commands/commits/update.go b/client/commands/commits/update.go index c42144b61b85..f522a914a345 100644 --- a/client/commands/commits/update.go +++ b/client/commands/commits/update.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/light-client/certifiers" + "github.com/tendermint/tendermint/certifiers" "github.com/cosmos/cosmos-sdk/client/commands" ) diff --git a/client/commands/common.go b/client/commands/common.go index c51dbb469bd1..ff93a05a69c2 100644 --- a/client/commands/common.go +++ b/client/commands/common.go @@ -12,7 +12,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/light-client/certifiers" + "github.com/tendermint/tendermint/certifiers" "github.com/tendermint/tmlibs/cli" cmn "github.com/tendermint/tmlibs/common" diff --git a/client/commands/init.go b/client/commands/init.go index 807dd1c0b27c..c290d1e14a6e 100644 --- a/client/commands/init.go +++ b/client/commands/init.go @@ -15,8 +15,8 @@ import ( "github.com/spf13/pflag" "github.com/spf13/viper" - "github.com/tendermint/light-client/certifiers" - "github.com/tendermint/light-client/certifiers/files" + "github.com/tendermint/tendermint/certifiers" + "github.com/tendermint/tendermint/certifiers/files" "github.com/tendermint/tmlibs/cli" cmn "github.com/tendermint/tmlibs/common" diff --git a/client/common.go b/client/common.go index 5e79b8afbdb3..901c74483463 100644 --- a/client/common.go +++ b/client/common.go @@ -3,10 +3,10 @@ package client import ( "errors" - "github.com/tendermint/light-client/certifiers" - certclient "github.com/tendermint/light-client/certifiers/client" - certerr "github.com/tendermint/light-client/certifiers/errors" - "github.com/tendermint/light-client/certifiers/files" + "github.com/tendermint/tendermint/certifiers" + certclient "github.com/tendermint/tendermint/certifiers/client" + certerr "github.com/tendermint/tendermint/certifiers/errors" + "github.com/tendermint/tendermint/certifiers/files" "github.com/tendermint/light-client/proofs" diff --git a/client/query.go b/client/query.go index 25b3823d6f53..27606289bce2 100644 --- a/client/query.go +++ b/client/query.go @@ -5,8 +5,8 @@ import ( "github.com/tendermint/go-wire/data" "github.com/tendermint/iavl" - "github.com/tendermint/light-client/certifiers" - certerr "github.com/tendermint/light-client/certifiers/errors" + "github.com/tendermint/tendermint/certifiers" + certerr "github.com/tendermint/tendermint/certifiers/errors" "github.com/tendermint/tendermint/rpc/client" ) diff --git a/client/query_test.go b/client/query_test.go index 0320176eb357..3d4a5a387517 100644 --- a/client/query_test.go +++ b/client/query_test.go @@ -9,8 +9,8 @@ import ( "github.com/stretchr/testify/require" "github.com/tendermint/go-wire" - "github.com/tendermint/light-client/certifiers" - certclient "github.com/tendermint/light-client/certifiers/client" + "github.com/tendermint/tendermint/certifiers" + certclient "github.com/tendermint/tendermint/certifiers/client" "github.com/tendermint/tmlibs/log" nm "github.com/tendermint/tendermint/node" diff --git a/glide.lock b/glide.lock index e0ea8a99dd39..0dab715f7776 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: fbfdd03c0367bb0785ceb81ed34059df219e55d5a9c71c12597e505fbce14165 -updated: 2017-10-25T19:24:51.90002008+02:00 +updated: 2017-10-26T15:57:25.483144016+02:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -11,10 +11,10 @@ imports: version: a368813c5e648fee92e5f6c30e3944ff9d5e8895 - name: github.com/ebuchman/fail-test version: 95f809107225be108efcf10a3509e4ea6ceef3c4 +- name: github.com/ethanfrey/hid + version: f379bda1dbc8e79333b04563f71a12e86206efe5 - name: github.com/ethanfrey/ledger - version: 5e432577be582bd18a3b4a9cd75dae7a317ade36 -- name: github.com/flynn/hid - version: ed06a31c6245d4552e8dbba7e32e5b010b875d65 + version: 3689ce9be93e1a5bef836b1cc2abb18381c79176 - name: github.com/fsnotify/fsnotify version: 4da3e2cfbabc9f751898f250b49f2439785783a1 - name: github.com/go-kit/kit @@ -48,7 +48,7 @@ imports: - name: github.com/gorilla/mux version: 24fca303ac6da784b9e8269f724ddeb0b2eea5e7 - name: github.com/gorilla/websocket - version: 71fa72d4842364bc5f74185f4161e0099ea3624a + version: ea4d1f681babbce9545c9c5f3d5194a789c89f5b - name: github.com/hashicorp/hcl version: 23c074d0eceb2b8a5bfdbb271ab780cde70f05a8 subpackages: @@ -95,7 +95,7 @@ imports: - name: github.com/spf13/pflag version: 97afa5e7ca8a08a383cb259e06636b5e2cc7897f - name: github.com/spf13/viper - version: 8ef37cbca71638bf32f3d5e194117d4cb46da163 + version: 25b30aa063fc18e48662b86996252eabdcf2f0c7 - name: github.com/syndtr/goleveldb version: b89cc31ef7977104127d34c1bd31ebd1a9db2199 subpackages: @@ -112,7 +112,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: bb9bb4aa465a31fd6a272765be381888e6898c74 + version: a0e38dc58374f485481ea07b23659d85f670a694 subpackages: - client - example/dummy @@ -124,7 +124,7 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-crypto - version: 0a5b1d979a1bc86200c9ff829fbbcd575799a1b6 + version: db5603e37435933c13665a708055fadd18222f5f subpackages: - bcrypt - keys @@ -134,7 +134,7 @@ imports: - keys/wordlist - nano - name: github.com/tendermint/go-wire - version: 99d2169a1e39c65983eacaa1da867d6f3218e1c9 + version: 3180c867ca52bcd9ba6c905ce63613f8d8e9837c subpackages: - data - data/base58 @@ -149,7 +149,7 @@ imports: - certifiers/files - proofs - name: github.com/tendermint/tendermint - version: b2d5546cf8f71e0e168072e118d9836862384e6c + version: bb6c15b00a07e2aafc7fe245b3acfb33b9c25abe subpackages: - blockchain - cmd/tendermint/commands @@ -177,7 +177,7 @@ imports: - types - version - name: github.com/tendermint/tmlibs - version: 0a652499ead7cd20a57a6a592f0491a2b493bb85 + version: b30e3ba26d4077edeed83c50a4e0c38b0ec9ddb3 subpackages: - autofile - cli @@ -228,7 +228,7 @@ imports: subpackages: - googleapis/rpc/status - name: google.golang.org/grpc - version: a5986a5c88227370a9c0a82e5277167229c034cd + version: f7bf885db0b7479a537ec317c6e48ce53145f3db subpackages: - balancer - balancer/roundrobin diff --git a/modules/ibc/commands/tx.go b/modules/ibc/commands/tx.go index 292658721cff..f5ed752973ac 100644 --- a/modules/ibc/commands/tx.go +++ b/modules/ibc/commands/tx.go @@ -11,7 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/commands" txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs" "github.com/cosmos/cosmos-sdk/modules/ibc" - "github.com/tendermint/light-client/certifiers" + "github.com/tendermint/tendermint/certifiers" ) // RegisterChainTxCmd is CLI command to register a new chain for ibc diff --git a/modules/ibc/ibc_test.go b/modules/ibc/ibc_test.go index ceb92237fdbf..e491f94a2a95 100644 --- a/modules/ibc/ibc_test.go +++ b/modules/ibc/ibc_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" wire "github.com/tendermint/go-wire" - "github.com/tendermint/light-client/certifiers" + "github.com/tendermint/tendermint/certifiers" "github.com/tendermint/tmlibs/log" sdk "github.com/cosmos/cosmos-sdk" diff --git a/modules/ibc/provider.go b/modules/ibc/provider.go index 712b6ee81daa..a01b7504fd28 100644 --- a/modules/ibc/provider.go +++ b/modules/ibc/provider.go @@ -2,8 +2,8 @@ package ibc import ( wire "github.com/tendermint/go-wire" - "github.com/tendermint/light-client/certifiers" - certerr "github.com/tendermint/light-client/certifiers/errors" + "github.com/tendermint/tendermint/certifiers" + certerr "github.com/tendermint/tendermint/certifiers/errors" "github.com/cosmos/cosmos-sdk/stack" "github.com/cosmos/cosmos-sdk/state" diff --git a/modules/ibc/provider_test.go b/modules/ibc/provider_test.go index 2318f979652e..abdb93faacd7 100644 --- a/modules/ibc/provider_test.go +++ b/modules/ibc/provider_test.go @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/state" - "github.com/tendermint/light-client/certifiers" - certerr "github.com/tendermint/light-client/certifiers/errors" + "github.com/tendermint/tendermint/certifiers" + certerr "github.com/tendermint/tendermint/certifiers/errors" ) func assertCommitsEqual(t *testing.T, fc, fc2 certifiers.FullCommit) { diff --git a/modules/ibc/test_helpers.go b/modules/ibc/test_helpers.go index 79960dadfbd1..456e3076f0ee 100644 --- a/modules/ibc/test_helpers.go +++ b/modules/ibc/test_helpers.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/tendermint/iavl" - "github.com/tendermint/light-client/certifiers" + "github.com/tendermint/tendermint/certifiers" "github.com/tendermint/tmlibs/log" sdk "github.com/cosmos/cosmos-sdk" diff --git a/modules/ibc/tx.go b/modules/ibc/tx.go index eae5a38f9425..2686080ce80b 100644 --- a/modules/ibc/tx.go +++ b/modules/ibc/tx.go @@ -3,7 +3,7 @@ package ibc import ( "github.com/tendermint/go-wire/data" "github.com/tendermint/iavl" - "github.com/tendermint/light-client/certifiers" + "github.com/tendermint/tendermint/certifiers" sdk "github.com/cosmos/cosmos-sdk" ) From 4c1b4add4aa2e5653042ae9733ffafd726327889 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 26 Oct 2017 16:16:30 +0200 Subject: [PATCH 049/117] Crash-merge light-client/proofs into client/proofs --- client/commands/query/get.go | 2 +- client/common.go | 2 +- client/proofs/app.go | 109 +++++++++++++++++++ client/proofs/app_test.go | 116 ++++++++++++++++++++ client/proofs/block.go | 40 +++++++ client/proofs/errors.go | 22 ++++ client/proofs/errors_test.go | 18 ++++ client/proofs/interface.go | 28 +++++ client/proofs/main_test.go | 38 +++++++ client/proofs/presenters.go | 89 +++++++++++++++ client/proofs/tx.go | 81 ++++++++++++++ client/proofs/tx_test.go | 66 ++++++++++++ client/proofs/wrapper.go | 204 +++++++++++++++++++++++++++++++++++ client/query.go | 17 +-- 14 files changed, 822 insertions(+), 10 deletions(-) create mode 100644 client/proofs/app.go create mode 100644 client/proofs/app_test.go create mode 100644 client/proofs/block.go create mode 100644 client/proofs/errors.go create mode 100644 client/proofs/errors_test.go create mode 100644 client/proofs/interface.go create mode 100644 client/proofs/main_test.go create mode 100644 client/proofs/presenters.go create mode 100644 client/proofs/tx.go create mode 100644 client/proofs/tx_test.go create mode 100644 client/proofs/wrapper.go diff --git a/client/commands/query/get.go b/client/commands/query/get.go index 7ffc1c1f5d36..048241a3bea3 100644 --- a/client/commands/query/get.go +++ b/client/commands/query/get.go @@ -11,7 +11,7 @@ import ( wire "github.com/tendermint/go-wire" "github.com/tendermint/go-wire/data" "github.com/tendermint/iavl" - "github.com/tendermint/light-client/proofs" + "github.com/cosmos/cosmos-sdk/client/proofs" rpcclient "github.com/tendermint/tendermint/rpc/client" diff --git a/client/common.go b/client/common.go index 901c74483463..ea80cc11b0e1 100644 --- a/client/common.go +++ b/client/common.go @@ -8,7 +8,7 @@ import ( certerr "github.com/tendermint/tendermint/certifiers/errors" "github.com/tendermint/tendermint/certifiers/files" - "github.com/tendermint/light-client/proofs" + "github.com/cosmos/cosmos-sdk/client/proofs" rpcclient "github.com/tendermint/tendermint/rpc/client" ) diff --git a/client/proofs/app.go b/client/proofs/app.go new file mode 100644 index 000000000000..58d762962674 --- /dev/null +++ b/client/proofs/app.go @@ -0,0 +1,109 @@ +package proofs + +import ( + "github.com/pkg/errors" + + wire "github.com/tendermint/go-wire" + data "github.com/tendermint/go-wire/data" + "github.com/tendermint/iavl" + + "github.com/tendermint/tendermint/rpc/client" + + "github.com/tendermint/tendermint/certifiers" + certerr "github.com/tendermint/tendermint/certifiers/errors" +) + +var _ Prover = AppProver{} +var _ Proof = AppProof{} + +// we limit proofs to 1MB to stop overflow attacks +const appLimit = 1000 * 1000 + +// AppProver provides positive proofs of key-value pairs in the abciapp. +// +// TODO: also support negative proofs (this key is not set) +type AppProver struct { + node client.Client +} + +func NewAppProver(node client.Client) AppProver { + return AppProver{node: node} +} + +// Get tries to download a merkle hash for app state on this key from +// the tendermint node. +func (a AppProver) Get(key []byte, h uint64) (Proof, error) { + resp, err := a.node.ABCIQuery("/key", key) + if err != nil { + return nil, err + } + + // make sure the proof is the proper height + if !resp.Code.IsOK() { + return nil, errors.Errorf("Query error %d: %s", resp.Code, resp.Code.String()) + } + if len(resp.Key) == 0 || len(resp.Value) == 0 || len(resp.Proof) == 0 { + return nil, ErrNoData() + } + if resp.Height == 0 { + resp.Height = h + } + if h != 0 && h != resp.Height { + return nil, certerr.ErrHeightMismatch(int(h), int(resp.Height)) + } + proof := AppProof{ + Height: resp.Height, + Key: resp.Key, + Value: resp.Value, + Proof: resp.Proof, + } + return proof, nil +} + +func (a AppProver) Unmarshal(data []byte) (Proof, error) { + var proof AppProof + err := errors.WithStack(wire.ReadBinaryBytes(data, &proof)) + return proof, err +} + +// AppProof containts a key-value pair at a given height. +// It also contains the merkle proof from that key-value pair to the root hash, +// which can be verified against a signed header. +type AppProof struct { + Height uint64 + Key data.Bytes + Value data.Bytes + Proof data.Bytes +} + +func (p AppProof) Data() []byte { + return p.Value +} + +func (p AppProof) BlockHeight() uint64 { + return p.Height +} + +func (p AppProof) Validate(check certifiers.Commit) error { + if uint64(check.Height()) != p.Height { + return certerr.ErrHeightMismatch(int(p.Height), check.Height()) + } + + proof, err := iavl.ReadKeyExistsProof(p.Proof) + if err != nil { + return errors.WithStack(err) + } + + err = proof.Verify(p.Key, p.Value, check.Header.AppHash) + if err != nil { + return err + } + + // LGTM! + return nil +} + +func (p AppProof) Marshal() ([]byte, error) { + data := wire.BinaryBytes(p) + return data, nil +} diff --git a/client/proofs/app_test.go b/client/proofs/app_test.go new file mode 100644 index 000000000000..a32e8b2a1347 --- /dev/null +++ b/client/proofs/app_test.go @@ -0,0 +1,116 @@ +package proofs_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + ctest "github.com/tendermint/tmlibs/test" + + "github.com/tendermint/tendermint/certifiers" + certcli "github.com/tendermint/tendermint/certifiers/client" + "github.com/tendermint/tendermint/rpc/client" + + "github.com/cosmos/cosmos-sdk/client/proofs" +) + +func getCurrentCheck(t *testing.T, cl client.Client) certifiers.Commit { + stat, err := cl.Status() + require.Nil(t, err, "%+v", err) + return getCheckForHeight(t, cl, stat.LatestBlockHeight) +} + +func getCheckForHeight(t *testing.T, cl client.Client, h int) certifiers.Commit { + client.WaitForHeight(cl, h, nil) + commit, err := cl.Commit(&h) + require.Nil(t, err, "%+v", err) + return certcli.CommitFromResult(commit) +} + +func TestAppProofs(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + cl := getLocalClient() + prover := proofs.NewAppProver(cl) + time.Sleep(200 * time.Millisecond) + + precheck := getCurrentCheck(t, cl) + + // great, let's store some data here, and make more checks.... + k, v, tx := MakeTxKV() + br, err := cl.BroadcastTxCommit(tx) + require.Nil(err, "%+v", err) + require.EqualValues(0, br.CheckTx.Code) + require.EqualValues(0, br.DeliverTx.Code) + h := br.Height + 1 + + // unfortunately we cannot tell the server to give us any height + // other than the most recent, so 0 is the only choice :( + pr, err := prover.Get(k, uint64(h)) + require.Nil(err, "%+v", err) + check := getCheckForHeight(t, cl, h) + + // matches and validates with post-tx header + err = pr.Validate(check) + assert.Nil(err, "%+v", err) + + // doesn't matches with pre-tx header + err = pr.Validate(precheck) + assert.NotNil(err) + + // make sure it has the values we want + apk, ok := pr.(proofs.AppProof) + if assert.True(ok) { + assert.EqualValues(k, apk.Key) + assert.EqualValues(v, apk.Value) + } + + // make sure we read/write properly, and any changes to the serialized + // object are invalid proof (2000 random attempts) + + // TODO: iavl panics, fix this + // testSerialization(t, prover, pr, check, 2000) +} + +// testSerialization makes sure the proof will un/marshal properly +// and validate with the checkpoint. It also does lots of modifications +// to the binary data and makes sure no mods validates properly +func testSerialization(t *testing.T, prover proofs.Prover, pr proofs.Proof, + check certifiers.Commit, mods int) { + + require := require.New(t) + + // first, make sure that we can serialize and deserialize + err := pr.Validate(check) + require.Nil(err, "%+v", err) + + // store the data + data, err := pr.Marshal() + require.Nil(err, "%+v", err) + + // recover the data and make sure it still checks out + npr, err := prover.Unmarshal(data) + require.Nil(err, "%+v", err) + err = npr.Validate(check) + require.Nil(err, "%#v\n%+v", npr, err) + + // now let's go mod... + for i := 0; i < mods; i++ { + bdata := ctest.MutateByteSlice(data) + bpr, err := prover.Unmarshal(bdata) + if err == nil { + assert.NotNil(t, bpr.Validate(check)) + } + } +} + +// // validate all tx in the block +// block, err := cl.Block(check.Height()) +// require.Nil(err, "%+v", err) +// err = check.CheckTxs(block.Block.Data.Txs) +// assert.Nil(err, "%+v", err) + +// oh, i would like the know the hieght of the broadcast_commit..... +// so i could verify that tx :( diff --git a/client/proofs/block.go b/client/proofs/block.go new file mode 100644 index 000000000000..8200f8b779b8 --- /dev/null +++ b/client/proofs/block.go @@ -0,0 +1,40 @@ +package proofs + +import ( + "bytes" + "errors" + + "github.com/tendermint/tendermint/types" + + "github.com/tendermint/tendermint/certifiers" + certerr "github.com/tendermint/tendermint/certifiers/errors" +) + +func ValidateBlockMeta(meta *types.BlockMeta, check certifiers.Commit) error { + // TODO: check the BlockID?? + return ValidateHeader(meta.Header, check) +} + +func ValidateBlock(meta *types.Block, check certifiers.Commit) error { + err := ValidateHeader(meta.Header, check) + if err != nil { + return err + } + if !bytes.Equal(meta.Data.Hash(), meta.Header.DataHash) { + return errors.New("Data hash doesn't match header") + } + return nil +} + +func ValidateHeader(head *types.Header, check certifiers.Commit) error { + // make sure they are for the same height (obvious fail) + if head.Height != check.Height() { + return certerr.ErrHeightMismatch(head.Height, check.Height()) + } + // check if they are equal by using hashes + chead := check.Header + if !bytes.Equal(head.Hash(), chead.Hash()) { + return errors.New("Headers don't match") + } + return nil +} diff --git a/client/proofs/errors.go b/client/proofs/errors.go new file mode 100644 index 000000000000..8a728ca1828d --- /dev/null +++ b/client/proofs/errors.go @@ -0,0 +1,22 @@ +package proofs + +import ( + "fmt" + + "github.com/pkg/errors" +) + +//-------------------------------------------- + +var errNoData = fmt.Errorf("No data returned for query") + +// IsNoDataErr checks whether an error is due to a query returning empty data +func IsNoDataErr(err error) bool { + return errors.Cause(err) == errNoData +} + +func ErrNoData() error { + return errors.WithStack(errNoData) +} + +//-------------------------------------------- diff --git a/client/proofs/errors_test.go b/client/proofs/errors_test.go new file mode 100644 index 000000000000..addb128715a1 --- /dev/null +++ b/client/proofs/errors_test.go @@ -0,0 +1,18 @@ +package proofs + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestErrorNoData(t *testing.T) { + e1 := ErrNoData() + e1.Error() + assert.True(t, IsNoDataErr(e1)) + + e2 := errors.New("foobar") + assert.False(t, IsNoDataErr(e2)) + assert.False(t, IsNoDataErr(nil)) +} diff --git a/client/proofs/interface.go b/client/proofs/interface.go new file mode 100644 index 000000000000..7585fd39b58e --- /dev/null +++ b/client/proofs/interface.go @@ -0,0 +1,28 @@ +package proofs + +import "github.com/tendermint/tendermint/certifiers" + +// Prover is anything that can provide proofs. +// Such as a AppProver (for merkle proofs of app state) +// or TxProver (for merkle proofs that a tx is in a block) +type Prover interface { + // Get returns the key for the given block height + // The prover should accept h=0 for latest height + Get(key []byte, h uint64) (Proof, error) + Unmarshal([]byte) (Proof, error) +} + +// Proof is a generic interface for data along with the cryptographic proof +// of it's validity, tied to a checkpoint. +// +// Every implementation should offer some method to recover the data itself +// that was proven (like k-v pair, tx bytes, etc....) +type Proof interface { + BlockHeight() uint64 + // Validates this Proof matches the checkpoint + Validate(certifiers.Commit) error + // Marshal prepares for storage + Marshal() ([]byte, error) + // Data extracts the query result we want to see + Data() []byte +} diff --git a/client/proofs/main_test.go b/client/proofs/main_test.go new file mode 100644 index 000000000000..24b37b1edc27 --- /dev/null +++ b/client/proofs/main_test.go @@ -0,0 +1,38 @@ +package proofs_test + +import ( + "os" + "testing" + + "github.com/tendermint/abci/example/dummy" + cmn "github.com/tendermint/tmlibs/common" + + nm "github.com/tendermint/tendermint/node" + "github.com/tendermint/tendermint/rpc/client" + rpctest "github.com/tendermint/tendermint/rpc/test" +) + +var node *nm.Node + +func getLocalClient() client.Local { + return client.NewLocal(node) +} + +func TestMain(m *testing.M) { + // start a tendermint node (and merkleeyes) in the background to test against + app := dummy.NewDummyApplication() + node = rpctest.StartTendermint(app) + code := m.Run() + + // and shut down proper at the end + node.Stop() + node.Wait() + os.Exit(code) +} + +func MakeTxKV() ([]byte, []byte, []byte) { + k := cmn.RandStr(8) + v := cmn.RandStr(8) + tx := k + "=" + v + return []byte(k), []byte(v), []byte(tx) +} diff --git a/client/proofs/presenters.go b/client/proofs/presenters.go new file mode 100644 index 000000000000..a7408811a50c --- /dev/null +++ b/client/proofs/presenters.go @@ -0,0 +1,89 @@ +package proofs + +import ( + "encoding/hex" + + "github.com/pkg/errors" + + data "github.com/tendermint/go-wire/data" + cmn "github.com/tendermint/tmlibs/common" +) + +const Raw = "raw" + +// Presenter allows us to encode queries and parse results in an app-specific way +type Presenter interface { + MakeKey(string) ([]byte, error) + ParseData([]byte) (interface{}, error) +} + +type Presenters map[string]Presenter + +// NewPresenters gives you a default raw presenter +func NewPresenters() Presenters { + return Presenters{} +} + +// Lookup tries to find a registered presenter, or the raw presenter +func (p Presenters) Lookup(app string) (Presenter, error) { + if app == Raw { + return RawPresenter{}, nil + } + res, ok := p[app] + if !ok { + return nil, errors.Errorf("No presenter registered for %s", app) + } + return res, nil +} + +// Register adds this app to the lookup table to parse it +func (p Presenters) Register(app string, pres Presenter) { + p[app] = pres +} + +// BruteForce will try all regitered parsers in random order, +// before calling RawPresenter. Use if we have no idea how to +// interpret the data (eg. decoding all tx in a block) +func (p Presenters) BruteForce(raw []byte) (interface{}, error) { + for _, pr := range p { + res, err := pr.ParseData(raw) + if err == nil { + return res, err + } + } + // no luck with any of them...just go raw + return RawPresenter{}.ParseData(raw) +} + +var _ Presenter = RawPresenter{} + +// RawPresenter just hex-encodes/decodes text. Useful as default, +// or to embed in other structs for the MakeKey implementation +// +// If you set a prefix, it will be prepended to all your data +// after hex-decoding them +type RawPresenter struct { + KeyMaker +} + +// ParseData on the raw-presenter, just provides a hex-encoding of the bytes +func (p RawPresenter) ParseData(raw []byte) (interface{}, error) { + return data.Bytes(raw), nil +} + +// KeyMaker can be embedded for a basic and flexible key encoder +type KeyMaker struct { + Prefix []byte +} + +func (k KeyMaker) MakeKey(str string) ([]byte, error) { + r, err := hex.DecodeString(cmn.StripHex(str)) + if err == nil && len(k.Prefix) > 0 { + r = append(k.Prefix, r...) + } + return r, errors.WithStack(err) +} + +func ParseHexKey(str string) ([]byte, error) { + return KeyMaker{}.MakeKey(str) +} diff --git a/client/proofs/tx.go b/client/proofs/tx.go new file mode 100644 index 000000000000..200c7ac4c5ce --- /dev/null +++ b/client/proofs/tx.go @@ -0,0 +1,81 @@ +package proofs + +import ( + "github.com/pkg/errors" + + wire "github.com/tendermint/go-wire" + + "github.com/tendermint/tendermint/rpc/client" + "github.com/tendermint/tendermint/types" + + "github.com/tendermint/tendermint/certifiers" + certerr "github.com/tendermint/tendermint/certifiers/errors" +) + +var _ Prover = TxProver{} +var _ Proof = TxProof{} + +// we store up to 10MB as a proof, as we need an entire block! right now +const txLimit = 10 * 1000 * 1000 + +// TxProver provides positive proofs of key-value pairs in the abciapp. +// +// TODO: also support negative proofs (this key is not set) +type TxProver struct { + node client.Client +} + +func NewTxProver(node client.Client) TxProver { + return TxProver{node: node} +} + +// Get tries to download a merkle hash for app state on this key from +// the tendermint node. +// +// Important: key must be Tx.Hash() +// Height is completely ignored for now :( +func (t TxProver) Get(key []byte, h uint64) (Proof, error) { + res, err := t.node.Tx(key, true) + if err != nil { + return nil, err + } + + // and build a proof for lighter storage + proof := TxProof{ + Height: uint64(res.Height), + Proof: res.Proof, + } + return proof, err +} + +func (t TxProver) Unmarshal(data []byte) (pr Proof, err error) { + var proof TxProof + err = errors.WithStack(wire.ReadBinaryBytes(data, &proof)) + return proof, err +} + +// TxProof checks ALL txs for one block... we need a better way! +type TxProof struct { + Height uint64 + Proof types.TxProof +} + +func (p TxProof) Data() []byte { + return p.Proof.Data +} + +func (p TxProof) BlockHeight() uint64 { + return p.Height +} + +func (p TxProof) Validate(check certifiers.Commit) error { + if uint64(check.Height()) != p.Height { + return certerr.ErrHeightMismatch(int(p.Height), check.Height()) + } + return p.Proof.Validate(check.Header.DataHash) +} + +func (p TxProof) Marshal() ([]byte, error) { + data := wire.BinaryBytes(p) + return data, nil +} diff --git a/client/proofs/tx_test.go b/client/proofs/tx_test.go new file mode 100644 index 000000000000..bb28c5207595 --- /dev/null +++ b/client/proofs/tx_test.go @@ -0,0 +1,66 @@ +package proofs_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/client/proofs" + "github.com/tendermint/tendermint/types" +) + +func TestTxProofs(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + cl := getLocalClient() + prover := proofs.NewTxProver(cl) + time.Sleep(200 * time.Millisecond) + + precheck := getCurrentCheck(t, cl) + + // great, let's store some data here, and make more checks.... + _, _, btx := MakeTxKV() + tx := types.Tx(btx) + br, err := cl.BroadcastTxCommit(tx) + require.Nil(err, "%+v", err) + require.EqualValues(0, br.CheckTx.Code) + require.EqualValues(0, br.DeliverTx.Code) + h := br.Height + + // let's get a proof for our tx + pr, err := prover.Get(tx.Hash(), uint64(h)) + require.Nil(err, "%+v", err) + + // it should also work for 0 height (using indexer) + pr2, err := prover.Get(tx.Hash(), 0) + require.Nil(err, "%+v", err) + require.Equal(pr, pr2) + + // make sure bad queries return errors + _, err = prover.Get([]byte("no-such-tx"), uint64(h)) + require.NotNil(err) + _, err = prover.Get(tx, uint64(h+1)) + require.NotNil(err) + + // matches and validates with post-tx header + check := getCheckForHeight(t, cl, h) + err = pr.Validate(check) + assert.Nil(err, "%+v", err) + + // doesn't matches with pre-tx header + err = pr.Validate(precheck) + assert.NotNil(err) + + // make sure it has the values we want + txpr, ok := pr.(proofs.TxProof) + if assert.True(ok) { + assert.EqualValues(tx, txpr.Data()) + } + + // make sure we read/write properly, and any changes to the serialized + // object are invalid proof (2000 random attempts) + + // TODO: iavl panics, fix that + // testSerialization(t, prover, pr, check, 2000) +} diff --git a/client/proofs/wrapper.go b/client/proofs/wrapper.go new file mode 100644 index 000000000000..ea5a6653f5a3 --- /dev/null +++ b/client/proofs/wrapper.go @@ -0,0 +1,204 @@ +package proofs + +import ( + "fmt" + + "github.com/tendermint/go-wire/data" + "github.com/tendermint/tmlibs/events" + + "github.com/tendermint/tendermint/certifiers" + "github.com/tendermint/tendermint/certifiers/client" + rpcclient "github.com/tendermint/tendermint/rpc/client" + ctypes "github.com/tendermint/tendermint/rpc/core/types" + "github.com/tendermint/tendermint/types" +) + +var _ rpcclient.Client = Wrapper{} + +type Wrapper struct { + rpcclient.Client + cert *certifiers.Inquiring +} + +func Wrap(c rpcclient.Client, cert *certifiers.Inquiring) Wrapper { + wrap := Wrapper{c, cert} + // if we wrap http client, then we can swap out the event switch to filter + if hc, ok := c.(*rpcclient.HTTP); ok { + evt := hc.WSEvents.EventSwitch + hc.WSEvents.EventSwitch = WrappedSwitch{evt, wrap} + } + return wrap +} + +func (w Wrapper) ABCIQueryWithOptions(path string, data data.Bytes, opts rpcclient.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) { + r, err := w.Client.ABCIQuery(path, data) + if opts.Trusted || err != nil { + return r, err + } + + return w.proveQuery(r) +} + +func (w Wrapper) ABCIQuery(path string, data data.Bytes) (*ctypes.ResultABCIQuery, error) { + // default always with proof + r, err := w.Client.ABCIQuery(path, data) + if err != nil { + return nil, err + } + + return w.proveQuery(r) +} + +func (w Wrapper) proveQuery(r *ctypes.ResultABCIQuery) (*ctypes.ResultABCIQuery, error) { + // get a verified commit to validate from + h := int(r.Height) + c, err := w.Commit(&h) + if err != nil { + return nil, err + } + // make sure the checkpoint and proof match up + check := client.CommitFromResult(c) + // verify query + proof := AppProof{ + Height: r.Height, + Key: r.Key, + Value: r.Value, + Proof: r.Proof, + } + err = proof.Validate(check) + return r, err +} + +func (w Wrapper) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) { + r, err := w.Client.Tx(hash, prove) + if !prove || err != nil { + return r, err + } + // get a verified commit to validate from + c, err := w.Commit(&r.Height) + if err != nil { + return nil, err + } + // make sure the checkpoint and proof match up + check := client.CommitFromResult(c) + // verify tx + proof := TxProof{ + Height: uint64(r.Height), + Proof: r.Proof, + } + err = proof.Validate(check) + return r, err +} + +func (w Wrapper) BlockchainInfo(minHeight, maxHeight int) (*ctypes.ResultBlockchainInfo, error) { + r, err := w.Client.BlockchainInfo(minHeight, maxHeight) + if err != nil { + return nil, err + } + + // go and verify every blockmeta in the result.... + for _, meta := range r.BlockMetas { + // get a checkpoint to verify from + c, err := w.Commit(&meta.Header.Height) + if err != nil { + return nil, err + } + check := client.CommitFromResult(c) + err = ValidateBlockMeta(meta, check) + if err != nil { + return nil, err + } + } + + return r, nil +} + +func (w Wrapper) Block(height *int) (*ctypes.ResultBlock, error) { + r, err := w.Client.Block(height) + if err != nil { + return nil, err + } + // get a checkpoint to verify from + c, err := w.Commit(height) + if err != nil { + return nil, err + } + check := client.CommitFromResult(c) + + // now verify + err = ValidateBlockMeta(r.BlockMeta, check) + if err != nil { + return nil, err + } + err = ValidateBlock(r.Block, check) + if err != nil { + return nil, err + } + return r, nil +} + +// Commit downloads the Commit and certifies it with the certifiers. +// +// This is the foundation for all other verification in this module +func (w Wrapper) Commit(height *int) (*ctypes.ResultCommit, error) { + rpcclient.WaitForHeight(w.Client, *height, nil) + r, err := w.Client.Commit(height) + // if we got it, then certify it + if err == nil { + check := client.CommitFromResult(r) + err = w.cert.Certify(check) + } + return r, err +} + +type WrappedSwitch struct { + types.EventSwitch + client rpcclient.Client +} + +func (s WrappedSwitch) FireEvent(event string, data events.EventData) { + tm, ok := data.(types.TMEventData) + if !ok { + fmt.Printf("bad type %#v\n", data) + return + } + + // check to validate it if possible, and drop if not valid + switch t := tm.Unwrap().(type) { + case types.EventDataNewBlockHeader: + err := verifyHeader(s.client, t.Header) + if err != nil { + fmt.Printf("Invalid header: %#v\n", err) + return + } + case types.EventDataNewBlock: + err := verifyBlock(s.client, t.Block) + if err != nil { + fmt.Printf("Invalid block: %#v\n", err) + return + } + } + + // looks good, we fire it + s.EventSwitch.FireEvent(event, data) +} + +func verifyHeader(c rpcclient.Client, head *types.Header) error { + // get a checkpoint to verify from + commit, err := c.Commit(&head.Height) + if err != nil { + return err + } + check := client.CommitFromResult(commit) + return ValidateHeader(head, check) +} + +func verifyBlock(c rpcclient.Client, block *types.Block) error { + // get a checkpoint to verify from + commit, err := c.Commit(&block.Height) + if err != nil { + return err + } + check := client.CommitFromResult(commit) + return ValidateBlock(block, check) +} diff --git a/client/query.go b/client/query.go index 27606289bce2..20ce9af31656 100644 --- a/client/query.go +++ b/client/query.go @@ -6,9 +6,10 @@ import ( "github.com/tendermint/go-wire/data" "github.com/tendermint/iavl" "github.com/tendermint/tendermint/certifiers" + "github.com/tendermint/tendermint/certifiers/client" certerr "github.com/tendermint/tendermint/certifiers/errors" - "github.com/tendermint/tendermint/rpc/client" + rpcclient "github.com/tendermint/tendermint/rpc/client" ) // GetWithProof will query the key on the given node, and verify it has @@ -17,7 +18,7 @@ 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, reqHeight int, node client.Client, +func GetWithProof(key []byte, reqHeight int, node rpcclient.Client, cert certifiers.Certifier) ( val data.Bytes, height uint64, proof iavl.KeyProof, err error) { @@ -27,7 +28,7 @@ func GetWithProof(key []byte, reqHeight int, node client.Client, } resp, err := node.ABCIQueryWithOptions("/key", key, - client.ABCIQueryOptions{Height: uint64(reqHeight)}) + rpcclient.ABCIQueryOptions{Height: uint64(reqHeight)}) if err != nil { return } @@ -47,7 +48,7 @@ func GetWithProof(key []byte, reqHeight int, node client.Client, } // AppHash for height H is in header H+1 - var commit *certifiers.Commit + var commit certifiers.Commit commit, err = GetCertifiedCommit(int(resp.Height+1), node, cert) if err != nil { return @@ -94,18 +95,18 @@ func GetWithProof(key []byte, reqHeight int, node client.Client, // GetCertifiedCommit gets the signed header for a given height // and certifies it. Returns error if unable to get a proven header. -func GetCertifiedCommit(h int, node client.Client, - cert certifiers.Certifier) (empty *certifiers.Commit, err error) { +func GetCertifiedCommit(h int, node rpcclient.Client, + cert certifiers.Certifier) (empty certifiers.Commit, err error) { // FIXME: cannot use cert.GetByHeight for now, as it also requires // Validators and will fail on querying tendermint for non-current height. // When this is supported, we should use it instead... - client.WaitForHeight(node, h, nil) + rpcclient.WaitForHeight(node, h, nil) cresp, err := node.Commit(&h) if err != nil { return } - commit := certifiers.CommitFromResult(cresp) + commit := client.CommitFromResult(cresp) // validate downloaded checkpoint with our request and trust store. if commit.Height() != h { From a9de936d2950ee8bd4da10a728268bd3928d0872 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 26 Oct 2017 16:26:00 +0200 Subject: [PATCH 050/117] Update deps, no more light-client --- glide.lock | 18 ++++++------------ glide.yaml | 10 +++------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/glide.lock b/glide.lock index 0dab715f7776..f25122a5b7a2 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: fbfdd03c0367bb0785ceb81ed34059df219e55d5a9c71c12597e505fbce14165 -updated: 2017-10-26T15:57:25.483144016+02:00 +hash: 809845bf4c18a4abc85cf5d7b5ee7a17e0f437cd377b22e158787c718272261a +updated: 2017-10-26T16:18:37.833408343+02:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -140,18 +140,14 @@ imports: - data/base58 - name: github.com/tendermint/iavl version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653 -- name: github.com/tendermint/light-client - version: 76313d625e662ed7b284d066d68ff71edd7a9fac +- name: github.com/tendermint/tendermint + version: bb6c15b00a07e2aafc7fe245b3acfb33b9c25abe subpackages: + - blockchain - certifiers - certifiers/client - certifiers/errors - certifiers/files - - proofs -- name: github.com/tendermint/tendermint - version: bb6c15b00a07e2aafc7fe245b3acfb33b9c25abe - subpackages: - - blockchain - cmd/tendermint/commands - config - consensus @@ -190,6 +186,7 @@ imports: - log - logger - merkle + - test - name: golang.org/x/crypto version: edd5e9b0879d13ee6970a50153d85b8fec9f7686 subpackages: @@ -231,7 +228,6 @@ imports: version: f7bf885db0b7479a537ec317c6e48ce53145f3db subpackages: - balancer - - balancer/roundrobin - codes - connectivity - credentials @@ -243,8 +239,6 @@ imports: - naming - peer - resolver - - resolver/dns - - resolver/passthrough - stats - status - tap diff --git a/glide.yaml b/glide.yaml index 258c028e44f7..97630213545a 100644 --- a/glide.yaml +++ b/glide.yaml @@ -19,18 +19,14 @@ import: version: develop subpackages: - data -- package: github.com/tendermint/light-client - version: develop - subpackages: - - proofs - - certifiers - - certifiers/client - - certifiers/files - package: github.com/tendermint/iavl version: develop - package: github.com/tendermint/tendermint version: develop subpackages: + - certifiers + - certifiers/client + - certifiers/files - config - node - proxy From f41bf63c9c0697ca53deb9a85dc0407bb5c5052c Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 26 Oct 2017 18:54:50 +0200 Subject: [PATCH 051/117] noop cleanup --- client/errors_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/client/errors_test.go b/client/errors_test.go index c561c35b7af8..11a846a6de08 100644 --- a/client/errors_test.go +++ b/client/errors_test.go @@ -9,7 +9,6 @@ import ( func TestErrorNoData(t *testing.T) { e1 := ErrNoData() - e1.Error() assert.True(t, IsNoDataErr(e1)) e2 := errors.New("foobar") From 68c7ed8798a03d7874659c87dfb93f867f546d22 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 26 Oct 2017 19:39:32 +0200 Subject: [PATCH 052/117] Refactored query, use it in proxy --- client/common.go | 8 ---- client/proofs/errors_test.go | 1 - client/proofs/presenters.go | 89 ------------------------------------ client/proofs/terminal.glue | 1 + client/proofs/wrapper.go | 59 ++++++++---------------- client/query.go | 77 ++++++++++++++++--------------- 6 files changed, 58 insertions(+), 177 deletions(-) delete mode 100644 client/proofs/presenters.go create mode 100644 client/proofs/terminal.glue diff --git a/client/common.go b/client/common.go index ea80cc11b0e1..17ff9a1ba1d3 100644 --- a/client/common.go +++ b/client/common.go @@ -8,8 +8,6 @@ import ( certerr "github.com/tendermint/tendermint/certifiers/errors" "github.com/tendermint/tendermint/certifiers/files" - "github.com/cosmos/cosmos-sdk/client/proofs" - rpcclient "github.com/tendermint/tendermint/rpc/client" ) @@ -49,9 +47,3 @@ func GetCertifier(chainID string, trust certifiers.Provider, cert := certifiers.NewInquiring(chainID, fc, trust, source) return cert, nil } - -// SecureClient uses a given certifier to wrap an connection to an untrusted -// host and return a cryptographically secure rpc client. -func SecureClient(c rpcclient.Client, cert *certifiers.Inquiring) rpcclient.Client { - return proofs.Wrap(c, cert) -} diff --git a/client/proofs/errors_test.go b/client/proofs/errors_test.go index addb128715a1..88d6a39e5832 100644 --- a/client/proofs/errors_test.go +++ b/client/proofs/errors_test.go @@ -9,7 +9,6 @@ import ( func TestErrorNoData(t *testing.T) { e1 := ErrNoData() - e1.Error() assert.True(t, IsNoDataErr(e1)) e2 := errors.New("foobar") diff --git a/client/proofs/presenters.go b/client/proofs/presenters.go deleted file mode 100644 index a7408811a50c..000000000000 --- a/client/proofs/presenters.go +++ /dev/null @@ -1,89 +0,0 @@ -package proofs - -import ( - "encoding/hex" - - "github.com/pkg/errors" - - data "github.com/tendermint/go-wire/data" - cmn "github.com/tendermint/tmlibs/common" -) - -const Raw = "raw" - -// Presenter allows us to encode queries and parse results in an app-specific way -type Presenter interface { - MakeKey(string) ([]byte, error) - ParseData([]byte) (interface{}, error) -} - -type Presenters map[string]Presenter - -// NewPresenters gives you a default raw presenter -func NewPresenters() Presenters { - return Presenters{} -} - -// Lookup tries to find a registered presenter, or the raw presenter -func (p Presenters) Lookup(app string) (Presenter, error) { - if app == Raw { - return RawPresenter{}, nil - } - res, ok := p[app] - if !ok { - return nil, errors.Errorf("No presenter registered for %s", app) - } - return res, nil -} - -// Register adds this app to the lookup table to parse it -func (p Presenters) Register(app string, pres Presenter) { - p[app] = pres -} - -// BruteForce will try all regitered parsers in random order, -// before calling RawPresenter. Use if we have no idea how to -// interpret the data (eg. decoding all tx in a block) -func (p Presenters) BruteForce(raw []byte) (interface{}, error) { - for _, pr := range p { - res, err := pr.ParseData(raw) - if err == nil { - return res, err - } - } - // no luck with any of them...just go raw - return RawPresenter{}.ParseData(raw) -} - -var _ Presenter = RawPresenter{} - -// RawPresenter just hex-encodes/decodes text. Useful as default, -// or to embed in other structs for the MakeKey implementation -// -// If you set a prefix, it will be prepended to all your data -// after hex-decoding them -type RawPresenter struct { - KeyMaker -} - -// ParseData on the raw-presenter, just provides a hex-encoding of the bytes -func (p RawPresenter) ParseData(raw []byte) (interface{}, error) { - return data.Bytes(raw), nil -} - -// KeyMaker can be embedded for a basic and flexible key encoder -type KeyMaker struct { - Prefix []byte -} - -func (k KeyMaker) MakeKey(str string) ([]byte, error) { - r, err := hex.DecodeString(cmn.StripHex(str)) - if err == nil && len(k.Prefix) > 0 { - r = append(k.Prefix, r...) - } - return r, errors.WithStack(err) -} - -func ParseHexKey(str string) ([]byte, error) { - return KeyMaker{}.MakeKey(str) -} diff --git a/client/proofs/terminal.glue b/client/proofs/terminal.glue new file mode 100644 index 000000000000..0519ecba6ea9 --- /dev/null +++ b/client/proofs/terminal.glue @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/proofs/wrapper.go b/client/proofs/wrapper.go index ea5a6653f5a3..51c1a02ad0d7 100644 --- a/client/proofs/wrapper.go +++ b/client/proofs/wrapper.go @@ -7,10 +7,12 @@ import ( "github.com/tendermint/tmlibs/events" "github.com/tendermint/tendermint/certifiers" - "github.com/tendermint/tendermint/certifiers/client" + certclient "github.com/tendermint/tendermint/certifiers/client" rpcclient "github.com/tendermint/tendermint/rpc/client" ctypes "github.com/tendermint/tendermint/rpc/core/types" "github.com/tendermint/tendermint/types" + + "github.com/cosmos/cosmos-sdk/client" ) var _ rpcclient.Client = Wrapper{} @@ -20,7 +22,9 @@ type Wrapper struct { cert *certifiers.Inquiring } -func Wrap(c rpcclient.Client, cert *certifiers.Inquiring) Wrapper { +// SecureClient uses a given certifier to wrap an connection to an untrusted +// host and return a cryptographically secure rpc client. +func SecureClient(c rpcclient.Client, cert *certifiers.Inquiring) Wrapper { wrap := Wrapper{c, cert} // if we wrap http client, then we can swap out the event switch to filter if hc, ok := c.(*rpcclient.HTTP); ok { @@ -31,42 +35,12 @@ func Wrap(c rpcclient.Client, cert *certifiers.Inquiring) Wrapper { } func (w Wrapper) ABCIQueryWithOptions(path string, data data.Bytes, opts rpcclient.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) { - r, err := w.Client.ABCIQuery(path, data) - if opts.Trusted || err != nil { - return r, err - } - - return w.proveQuery(r) + res, _, err := client.GetWithProofOptions(path, data, opts, w.Client, w.cert) + return res, err } func (w Wrapper) ABCIQuery(path string, data data.Bytes) (*ctypes.ResultABCIQuery, error) { - // default always with proof - r, err := w.Client.ABCIQuery(path, data) - if err != nil { - return nil, err - } - - return w.proveQuery(r) -} - -func (w Wrapper) proveQuery(r *ctypes.ResultABCIQuery) (*ctypes.ResultABCIQuery, error) { - // get a verified commit to validate from - h := int(r.Height) - c, err := w.Commit(&h) - if err != nil { - return nil, err - } - // make sure the checkpoint and proof match up - check := client.CommitFromResult(c) - // verify query - proof := AppProof{ - Height: r.Height, - Key: r.Key, - Value: r.Value, - Proof: r.Proof, - } - err = proof.Validate(check) - return r, err + return w.ABCIQueryWithOptions(path, data, rpcclient.DefaultABCIQueryOptions) } func (w Wrapper) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) { @@ -80,7 +54,9 @@ func (w Wrapper) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) { return nil, err } // make sure the checkpoint and proof match up - check := client.CommitFromResult(c) + check := certclient.CommitFromResult(c) + + // TODO: 2 // verify tx proof := TxProof{ Height: uint64(r.Height), @@ -103,7 +79,8 @@ func (w Wrapper) BlockchainInfo(minHeight, maxHeight int) (*ctypes.ResultBlockch if err != nil { return nil, err } - check := client.CommitFromResult(c) + check := certclient.CommitFromResult(c) + // TODO: 3 err = ValidateBlockMeta(meta, check) if err != nil { return nil, err @@ -123,7 +100,7 @@ func (w Wrapper) Block(height *int) (*ctypes.ResultBlock, error) { if err != nil { return nil, err } - check := client.CommitFromResult(c) + check := certclient.CommitFromResult(c) // now verify err = ValidateBlockMeta(r.BlockMeta, check) @@ -145,7 +122,7 @@ func (w Wrapper) Commit(height *int) (*ctypes.ResultCommit, error) { r, err := w.Client.Commit(height) // if we got it, then certify it if err == nil { - check := client.CommitFromResult(r) + check := certclient.CommitFromResult(r) err = w.cert.Certify(check) } return r, err @@ -189,7 +166,7 @@ func verifyHeader(c rpcclient.Client, head *types.Header) error { if err != nil { return err } - check := client.CommitFromResult(commit) + check := certclient.CommitFromResult(commit) return ValidateHeader(head, check) } @@ -199,6 +176,6 @@ func verifyBlock(c rpcclient.Client, block *types.Block) error { if err != nil { return err } - check := client.CommitFromResult(commit) + check := certclient.CommitFromResult(commit) return ValidateBlock(block, check) } diff --git a/client/query.go b/client/query.go index 20ce9af31656..6a0c3469a90a 100644 --- a/client/query.go +++ b/client/query.go @@ -5,11 +5,12 @@ import ( "github.com/tendermint/go-wire/data" "github.com/tendermint/iavl" + "github.com/tendermint/tendermint/certifiers" "github.com/tendermint/tendermint/certifiers/client" certerr "github.com/tendermint/tendermint/certifiers/errors" - rpcclient "github.com/tendermint/tendermint/rpc/client" + ctypes "github.com/tendermint/tendermint/rpc/core/types" ) // GetWithProof will query the key on the given node, and verify it has @@ -27,70 +28,70 @@ func GetWithProof(key []byte, reqHeight int, node rpcclient.Client, return } - resp, err := node.ABCIQueryWithOptions("/key", key, - rpcclient.ABCIQueryOptions{Height: uint64(reqHeight)}) + resp, proof, err := GetWithProofOptions("/key", key, + rpcclient.ABCIQueryOptions{Height: uint64(reqHeight)}, + node, cert) + if resp != nil { + val, height = resp.Value, resp.Height + } + return val, height, proof, err +} + +// GetWithProofOptions is useful if you want full access to the ABCIQueryOptions +func GetWithProofOptions(path string, key []byte, opts rpcclient.ABCIQueryOptions, + node rpcclient.Client, cert certifiers.Certifier) ( + *ctypes.ResultABCIQuery, iavl.KeyProof, error) { + + resp, err := node.ABCIQueryWithOptions(path, key, opts) if err != nil { - return + return nil, nil, err } // make sure the proof is the proper height if !resp.Code.IsOK() { err = errors.Errorf("Query error %d: %s", resp.Code, resp.Code.String()) - return + return nil, nil, err } if len(resp.Key) == 0 || len(resp.Proof) == 0 { - err = ErrNoData() - return + return nil, nil, ErrNoData() } if resp.Height == 0 { - err = errors.New("Height returned is zero") - return + return nil, nil, errors.New("Height returned is zero") } // AppHash for height H is in header H+1 - var commit certifiers.Commit - commit, err = GetCertifiedCommit(int(resp.Height+1), node, cert) + commit, err := GetCertifiedCommit(int(resp.Height+1), node, cert) if err != nil { - return + return nil, nil, err } if len(resp.Value) > 0 { // The key was found, construct a proof of existence. - var eproof *iavl.KeyExistsProof - eproof, err = iavl.ReadKeyExistsProof(resp.Proof) + eproof, err := iavl.ReadKeyExistsProof(resp.Proof) if err != nil { - err = errors.Wrap(err, "Error reading proof") - return + return nil, nil, errors.Wrap(err, "Error reading proof") } // Validate the proof against the certified header to ensure data integrity. err = eproof.Verify(resp.Key, resp.Value, commit.Header.AppHash) if err != nil { - err = errors.Wrap(err, "Couldn't verify proof") - return - } - val = data.Bytes(resp.Value) - proof = eproof - } else { - // The key wasn't found, construct a proof of non-existence. - var aproof *iavl.KeyAbsentProof - aproof, err = iavl.ReadKeyAbsentProof(resp.Proof) - if err != nil { - err = errors.Wrap(err, "Error reading proof") - return - } - // Validate the proof against the certified header to ensure data integrity. - err = aproof.Verify(resp.Key, nil, commit.Header.AppHash) - if err != nil { - err = errors.Wrap(err, "Couldn't verify proof") - return + return nil, nil, errors.Wrap(err, "Couldn't verify proof") } - err = ErrNoData() - proof = aproof + return resp, eproof, nil } - height = resp.Height - return + // The key wasn't found, construct a proof of non-existence. + var aproof *iavl.KeyAbsentProof + aproof, err = iavl.ReadKeyAbsentProof(resp.Proof) + if err != nil { + return nil, nil, errors.Wrap(err, "Error reading proof") + } + // Validate the proof against the certified header to ensure data integrity. + err = aproof.Verify(resp.Key, nil, commit.Header.AppHash) + if err != nil { + return nil, nil, errors.Wrap(err, "Couldn't verify proof") + } + return resp, aproof, ErrNoData() } // GetCertifiedCommit gets the signed header for a given height From dcb1f468d9d8af9210552544c5673d9207a71612 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 26 Oct 2017 19:43:17 +0200 Subject: [PATCH 053/117] Replace custom tx verification in proxy --- client/proofs/app.go | 109 ----------------------------------- client/proofs/app_test.go | 116 -------------------------------------- client/proofs/tx.go | 81 -------------------------- client/proofs/tx_test.go | 66 ---------------------- client/proofs/wrapper.go | 22 ++------ 5 files changed, 6 insertions(+), 388 deletions(-) delete mode 100644 client/proofs/app.go delete mode 100644 client/proofs/app_test.go delete mode 100644 client/proofs/tx.go delete mode 100644 client/proofs/tx_test.go diff --git a/client/proofs/app.go b/client/proofs/app.go deleted file mode 100644 index 58d762962674..000000000000 --- a/client/proofs/app.go +++ /dev/null @@ -1,109 +0,0 @@ -package proofs - -import ( - "github.com/pkg/errors" - - wire "github.com/tendermint/go-wire" - data "github.com/tendermint/go-wire/data" - "github.com/tendermint/iavl" - - "github.com/tendermint/tendermint/rpc/client" - - "github.com/tendermint/tendermint/certifiers" - certerr "github.com/tendermint/tendermint/certifiers/errors" -) - -var _ Prover = AppProver{} -var _ Proof = AppProof{} - -// we limit proofs to 1MB to stop overflow attacks -const appLimit = 1000 * 1000 - -// AppProver provides positive proofs of key-value pairs in the abciapp. -// -// TODO: also support negative proofs (this key is not set) -type AppProver struct { - node client.Client -} - -func NewAppProver(node client.Client) AppProver { - return AppProver{node: node} -} - -// Get tries to download a merkle hash for app state on this key from -// the tendermint node. -func (a AppProver) Get(key []byte, h uint64) (Proof, error) { - resp, err := a.node.ABCIQuery("/key", key) - if err != nil { - return nil, err - } - - // make sure the proof is the proper height - if !resp.Code.IsOK() { - return nil, errors.Errorf("Query error %d: %s", resp.Code, resp.Code.String()) - } - if len(resp.Key) == 0 || len(resp.Value) == 0 || len(resp.Proof) == 0 { - return nil, ErrNoData() - } - if resp.Height == 0 { - resp.Height = h - } - if h != 0 && h != resp.Height { - return nil, certerr.ErrHeightMismatch(int(h), int(resp.Height)) - } - proof := AppProof{ - Height: resp.Height, - Key: resp.Key, - Value: resp.Value, - Proof: resp.Proof, - } - return proof, nil -} - -func (a AppProver) Unmarshal(data []byte) (Proof, error) { - var proof AppProof - err := errors.WithStack(wire.ReadBinaryBytes(data, &proof)) - return proof, err -} - -// AppProof containts a key-value pair at a given height. -// It also contains the merkle proof from that key-value pair to the root hash, -// which can be verified against a signed header. -type AppProof struct { - Height uint64 - Key data.Bytes - Value data.Bytes - Proof data.Bytes -} - -func (p AppProof) Data() []byte { - return p.Value -} - -func (p AppProof) BlockHeight() uint64 { - return p.Height -} - -func (p AppProof) Validate(check certifiers.Commit) error { - if uint64(check.Height()) != p.Height { - return certerr.ErrHeightMismatch(int(p.Height), check.Height()) - } - - proof, err := iavl.ReadKeyExistsProof(p.Proof) - if err != nil { - return errors.WithStack(err) - } - - err = proof.Verify(p.Key, p.Value, check.Header.AppHash) - if err != nil { - return err - } - - // LGTM! - return nil -} - -func (p AppProof) Marshal() ([]byte, error) { - data := wire.BinaryBytes(p) - return data, nil -} diff --git a/client/proofs/app_test.go b/client/proofs/app_test.go deleted file mode 100644 index a32e8b2a1347..000000000000 --- a/client/proofs/app_test.go +++ /dev/null @@ -1,116 +0,0 @@ -package proofs_test - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - ctest "github.com/tendermint/tmlibs/test" - - "github.com/tendermint/tendermint/certifiers" - certcli "github.com/tendermint/tendermint/certifiers/client" - "github.com/tendermint/tendermint/rpc/client" - - "github.com/cosmos/cosmos-sdk/client/proofs" -) - -func getCurrentCheck(t *testing.T, cl client.Client) certifiers.Commit { - stat, err := cl.Status() - require.Nil(t, err, "%+v", err) - return getCheckForHeight(t, cl, stat.LatestBlockHeight) -} - -func getCheckForHeight(t *testing.T, cl client.Client, h int) certifiers.Commit { - client.WaitForHeight(cl, h, nil) - commit, err := cl.Commit(&h) - require.Nil(t, err, "%+v", err) - return certcli.CommitFromResult(commit) -} - -func TestAppProofs(t *testing.T) { - assert, require := assert.New(t), require.New(t) - - cl := getLocalClient() - prover := proofs.NewAppProver(cl) - time.Sleep(200 * time.Millisecond) - - precheck := getCurrentCheck(t, cl) - - // great, let's store some data here, and make more checks.... - k, v, tx := MakeTxKV() - br, err := cl.BroadcastTxCommit(tx) - require.Nil(err, "%+v", err) - require.EqualValues(0, br.CheckTx.Code) - require.EqualValues(0, br.DeliverTx.Code) - h := br.Height + 1 - - // unfortunately we cannot tell the server to give us any height - // other than the most recent, so 0 is the only choice :( - pr, err := prover.Get(k, uint64(h)) - require.Nil(err, "%+v", err) - check := getCheckForHeight(t, cl, h) - - // matches and validates with post-tx header - err = pr.Validate(check) - assert.Nil(err, "%+v", err) - - // doesn't matches with pre-tx header - err = pr.Validate(precheck) - assert.NotNil(err) - - // make sure it has the values we want - apk, ok := pr.(proofs.AppProof) - if assert.True(ok) { - assert.EqualValues(k, apk.Key) - assert.EqualValues(v, apk.Value) - } - - // make sure we read/write properly, and any changes to the serialized - // object are invalid proof (2000 random attempts) - - // TODO: iavl panics, fix this - // testSerialization(t, prover, pr, check, 2000) -} - -// testSerialization makes sure the proof will un/marshal properly -// and validate with the checkpoint. It also does lots of modifications -// to the binary data and makes sure no mods validates properly -func testSerialization(t *testing.T, prover proofs.Prover, pr proofs.Proof, - check certifiers.Commit, mods int) { - - require := require.New(t) - - // first, make sure that we can serialize and deserialize - err := pr.Validate(check) - require.Nil(err, "%+v", err) - - // store the data - data, err := pr.Marshal() - require.Nil(err, "%+v", err) - - // recover the data and make sure it still checks out - npr, err := prover.Unmarshal(data) - require.Nil(err, "%+v", err) - err = npr.Validate(check) - require.Nil(err, "%#v\n%+v", npr, err) - - // now let's go mod... - for i := 0; i < mods; i++ { - bdata := ctest.MutateByteSlice(data) - bpr, err := prover.Unmarshal(bdata) - if err == nil { - assert.NotNil(t, bpr.Validate(check)) - } - } -} - -// // validate all tx in the block -// block, err := cl.Block(check.Height()) -// require.Nil(err, "%+v", err) -// err = check.CheckTxs(block.Block.Data.Txs) -// assert.Nil(err, "%+v", err) - -// oh, i would like the know the hieght of the broadcast_commit..... -// so i could verify that tx :( diff --git a/client/proofs/tx.go b/client/proofs/tx.go deleted file mode 100644 index 200c7ac4c5ce..000000000000 --- a/client/proofs/tx.go +++ /dev/null @@ -1,81 +0,0 @@ -package proofs - -import ( - "github.com/pkg/errors" - - wire "github.com/tendermint/go-wire" - - "github.com/tendermint/tendermint/rpc/client" - "github.com/tendermint/tendermint/types" - - "github.com/tendermint/tendermint/certifiers" - certerr "github.com/tendermint/tendermint/certifiers/errors" -) - -var _ Prover = TxProver{} -var _ Proof = TxProof{} - -// we store up to 10MB as a proof, as we need an entire block! right now -const txLimit = 10 * 1000 * 1000 - -// TxProver provides positive proofs of key-value pairs in the abciapp. -// -// TODO: also support negative proofs (this key is not set) -type TxProver struct { - node client.Client -} - -func NewTxProver(node client.Client) TxProver { - return TxProver{node: node} -} - -// Get tries to download a merkle hash for app state on this key from -// the tendermint node. -// -// Important: key must be Tx.Hash() -// Height is completely ignored for now :( -func (t TxProver) Get(key []byte, h uint64) (Proof, error) { - res, err := t.node.Tx(key, true) - if err != nil { - return nil, err - } - - // and build a proof for lighter storage - proof := TxProof{ - Height: uint64(res.Height), - Proof: res.Proof, - } - return proof, err -} - -func (t TxProver) Unmarshal(data []byte) (pr Proof, err error) { - var proof TxProof - err = errors.WithStack(wire.ReadBinaryBytes(data, &proof)) - return proof, err -} - -// TxProof checks ALL txs for one block... we need a better way! -type TxProof struct { - Height uint64 - Proof types.TxProof -} - -func (p TxProof) Data() []byte { - return p.Proof.Data -} - -func (p TxProof) BlockHeight() uint64 { - return p.Height -} - -func (p TxProof) Validate(check certifiers.Commit) error { - if uint64(check.Height()) != p.Height { - return certerr.ErrHeightMismatch(int(p.Height), check.Height()) - } - return p.Proof.Validate(check.Header.DataHash) -} - -func (p TxProof) Marshal() ([]byte, error) { - data := wire.BinaryBytes(p) - return data, nil -} diff --git a/client/proofs/tx_test.go b/client/proofs/tx_test.go deleted file mode 100644 index bb28c5207595..000000000000 --- a/client/proofs/tx_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package proofs_test - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/client/proofs" - "github.com/tendermint/tendermint/types" -) - -func TestTxProofs(t *testing.T) { - assert, require := assert.New(t), require.New(t) - - cl := getLocalClient() - prover := proofs.NewTxProver(cl) - time.Sleep(200 * time.Millisecond) - - precheck := getCurrentCheck(t, cl) - - // great, let's store some data here, and make more checks.... - _, _, btx := MakeTxKV() - tx := types.Tx(btx) - br, err := cl.BroadcastTxCommit(tx) - require.Nil(err, "%+v", err) - require.EqualValues(0, br.CheckTx.Code) - require.EqualValues(0, br.DeliverTx.Code) - h := br.Height - - // let's get a proof for our tx - pr, err := prover.Get(tx.Hash(), uint64(h)) - require.Nil(err, "%+v", err) - - // it should also work for 0 height (using indexer) - pr2, err := prover.Get(tx.Hash(), 0) - require.Nil(err, "%+v", err) - require.Equal(pr, pr2) - - // make sure bad queries return errors - _, err = prover.Get([]byte("no-such-tx"), uint64(h)) - require.NotNil(err) - _, err = prover.Get(tx, uint64(h+1)) - require.NotNil(err) - - // matches and validates with post-tx header - check := getCheckForHeight(t, cl, h) - err = pr.Validate(check) - assert.Nil(err, "%+v", err) - - // doesn't matches with pre-tx header - err = pr.Validate(precheck) - assert.NotNil(err) - - // make sure it has the values we want - txpr, ok := pr.(proofs.TxProof) - if assert.True(ok) { - assert.EqualValues(tx, txpr.Data()) - } - - // make sure we read/write properly, and any changes to the serialized - // object are invalid proof (2000 random attempts) - - // TODO: iavl panics, fix that - // testSerialization(t, prover, pr, check, 2000) -} diff --git a/client/proofs/wrapper.go b/client/proofs/wrapper.go index 51c1a02ad0d7..edc26dd525e0 100644 --- a/client/proofs/wrapper.go +++ b/client/proofs/wrapper.go @@ -44,26 +44,16 @@ func (w Wrapper) ABCIQuery(path string, data data.Bytes) (*ctypes.ResultABCIQuer } func (w Wrapper) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) { - r, err := w.Client.Tx(hash, prove) + res, err := w.Client.Tx(hash, prove) if !prove || err != nil { - return r, err + return res, err } - // get a verified commit to validate from - c, err := w.Commit(&r.Height) + check, err := client.GetCertifiedCommit(res.Height, w.Client, w.cert) if err != nil { - return nil, err - } - // make sure the checkpoint and proof match up - check := certclient.CommitFromResult(c) - - // TODO: 2 - // verify tx - proof := TxProof{ - Height: uint64(r.Height), - Proof: r.Proof, + return res, err } - err = proof.Validate(check) - return r, err + err = res.Proof.Validate(check.Header.DataHash) + return res, err } func (w Wrapper) BlockchainInfo(minHeight, maxHeight int) (*ctypes.ResultBlockchainInfo, error) { From 78b87dd5388c272618d2ed6e70b67bcba27d514f Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 26 Oct 2017 19:45:18 +0200 Subject: [PATCH 054/117] more cleanup --- client/proofs/interface.go | 28 ---------------------------- client/proofs/main_test.go | 38 -------------------------------------- 2 files changed, 66 deletions(-) delete mode 100644 client/proofs/interface.go delete mode 100644 client/proofs/main_test.go diff --git a/client/proofs/interface.go b/client/proofs/interface.go deleted file mode 100644 index 7585fd39b58e..000000000000 --- a/client/proofs/interface.go +++ /dev/null @@ -1,28 +0,0 @@ -package proofs - -import "github.com/tendermint/tendermint/certifiers" - -// Prover is anything that can provide proofs. -// Such as a AppProver (for merkle proofs of app state) -// or TxProver (for merkle proofs that a tx is in a block) -type Prover interface { - // Get returns the key for the given block height - // The prover should accept h=0 for latest height - Get(key []byte, h uint64) (Proof, error) - Unmarshal([]byte) (Proof, error) -} - -// Proof is a generic interface for data along with the cryptographic proof -// of it's validity, tied to a checkpoint. -// -// Every implementation should offer some method to recover the data itself -// that was proven (like k-v pair, tx bytes, etc....) -type Proof interface { - BlockHeight() uint64 - // Validates this Proof matches the checkpoint - Validate(certifiers.Commit) error - // Marshal prepares for storage - Marshal() ([]byte, error) - // Data extracts the query result we want to see - Data() []byte -} diff --git a/client/proofs/main_test.go b/client/proofs/main_test.go deleted file mode 100644 index 24b37b1edc27..000000000000 --- a/client/proofs/main_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package proofs_test - -import ( - "os" - "testing" - - "github.com/tendermint/abci/example/dummy" - cmn "github.com/tendermint/tmlibs/common" - - nm "github.com/tendermint/tendermint/node" - "github.com/tendermint/tendermint/rpc/client" - rpctest "github.com/tendermint/tendermint/rpc/test" -) - -var node *nm.Node - -func getLocalClient() client.Local { - return client.NewLocal(node) -} - -func TestMain(m *testing.M) { - // start a tendermint node (and merkleeyes) in the background to test against - app := dummy.NewDummyApplication() - node = rpctest.StartTendermint(app) - code := m.Run() - - // and shut down proper at the end - node.Stop() - node.Wait() - os.Exit(code) -} - -func MakeTxKV() ([]byte, []byte, []byte) { - k := cmn.RandStr(8) - v := cmn.RandStr(8) - tx := k + "=" + v - return []byte(k), []byte(v), []byte(tx) -} From d5bce4b9ec47a0711ab8124081cee89b26f32122 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 26 Oct 2017 19:53:47 +0200 Subject: [PATCH 055/117] Collapse remnants of proofs into client --- client/{proofs => }/block.go | 6 +++--- client/commands/query/get.go | 6 ++++-- client/proofs/errors.go | 22 ---------------------- client/proofs/errors_test.go | 17 ----------------- client/proofs/terminal.glue | 1 - client/{proofs => }/wrapper.go | 8 +++----- 6 files changed, 10 insertions(+), 50 deletions(-) rename client/{proofs => }/block.go (96%) delete mode 100644 client/proofs/errors.go delete mode 100644 client/proofs/errors_test.go delete mode 100644 client/proofs/terminal.glue rename client/{proofs => }/wrapper.go (95%) diff --git a/client/proofs/block.go b/client/block.go similarity index 96% rename from client/proofs/block.go rename to client/block.go index 8200f8b779b8..2bf3f39a8208 100644 --- a/client/proofs/block.go +++ b/client/block.go @@ -1,13 +1,13 @@ -package proofs +package client import ( "bytes" - "errors" - "github.com/tendermint/tendermint/types" + "github.com/pkg/errors" "github.com/tendermint/tendermint/certifiers" certerr "github.com/tendermint/tendermint/certifiers/errors" + "github.com/tendermint/tendermint/types" ) func ValidateBlockMeta(meta *types.BlockMeta, check certifiers.Commit) error { diff --git a/client/commands/query/get.go b/client/commands/query/get.go index 048241a3bea3..59c44c05f8c5 100644 --- a/client/commands/query/get.go +++ b/client/commands/query/get.go @@ -1,6 +1,7 @@ package query import ( + "encoding/hex" "fmt" "io" "os" @@ -11,7 +12,7 @@ import ( wire "github.com/tendermint/go-wire" "github.com/tendermint/go-wire/data" "github.com/tendermint/iavl" - "github.com/cosmos/cosmos-sdk/client/proofs" + cmn "github.com/tendermint/tmlibs/common" rpcclient "github.com/tendermint/tendermint/rpc/client" @@ -87,7 +88,8 @@ func ParseHexKey(args []string, argname string) ([]byte, error) { return nil, errors.Errorf("[%s] argument must be non-empty ", argname) } // with tx, we always just parse key as hex and use to lookup - return proofs.ParseHexKey(rawkey) + key, err := hex.DecodeString(cmn.StripHex(rawkey)) + return key, errors.WithStack(err) } // GetHeight reads the viper config for the query height diff --git a/client/proofs/errors.go b/client/proofs/errors.go deleted file mode 100644 index 8a728ca1828d..000000000000 --- a/client/proofs/errors.go +++ /dev/null @@ -1,22 +0,0 @@ -package proofs - -import ( - "fmt" - - "github.com/pkg/errors" -) - -//-------------------------------------------- - -var errNoData = fmt.Errorf("No data returned for query") - -// IsNoDataErr checks whether an error is due to a query returning empty data -func IsNoDataErr(err error) bool { - return errors.Cause(err) == errNoData -} - -func ErrNoData() error { - return errors.WithStack(errNoData) -} - -//-------------------------------------------- diff --git a/client/proofs/errors_test.go b/client/proofs/errors_test.go deleted file mode 100644 index 88d6a39e5832..000000000000 --- a/client/proofs/errors_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package proofs - -import ( - "errors" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestErrorNoData(t *testing.T) { - e1 := ErrNoData() - assert.True(t, IsNoDataErr(e1)) - - e2 := errors.New("foobar") - assert.False(t, IsNoDataErr(e2)) - assert.False(t, IsNoDataErr(nil)) -} diff --git a/client/proofs/terminal.glue b/client/proofs/terminal.glue deleted file mode 100644 index 0519ecba6ea9..000000000000 --- a/client/proofs/terminal.glue +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/client/proofs/wrapper.go b/client/wrapper.go similarity index 95% rename from client/proofs/wrapper.go rename to client/wrapper.go index edc26dd525e0..508069c77047 100644 --- a/client/proofs/wrapper.go +++ b/client/wrapper.go @@ -1,4 +1,4 @@ -package proofs +package client import ( "fmt" @@ -11,8 +11,6 @@ import ( rpcclient "github.com/tendermint/tendermint/rpc/client" ctypes "github.com/tendermint/tendermint/rpc/core/types" "github.com/tendermint/tendermint/types" - - "github.com/cosmos/cosmos-sdk/client" ) var _ rpcclient.Client = Wrapper{} @@ -35,7 +33,7 @@ func SecureClient(c rpcclient.Client, cert *certifiers.Inquiring) Wrapper { } func (w Wrapper) ABCIQueryWithOptions(path string, data data.Bytes, opts rpcclient.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) { - res, _, err := client.GetWithProofOptions(path, data, opts, w.Client, w.cert) + res, _, err := GetWithProofOptions(path, data, opts, w.Client, w.cert) return res, err } @@ -48,7 +46,7 @@ func (w Wrapper) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) { if !prove || err != nil { return res, err } - check, err := client.GetCertifiedCommit(res.Height, w.Client, w.cert) + check, err := GetCertifiedCommit(res.Height, w.Client, w.cert) if err != nil { return res, err } From c514176abc084c73892362b7d1e9beea735f6899 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 26 Oct 2017 20:01:53 +0200 Subject: [PATCH 056/117] Add godoc --- client/wrapper.go | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/client/wrapper.go b/client/wrapper.go index 508069c77047..3bebd822192a 100644 --- a/client/wrapper.go +++ b/client/wrapper.go @@ -15,6 +15,8 @@ import ( var _ rpcclient.Client = Wrapper{} +// Wrapper wraps a rpcclient with a Certifier and double-checks any input that is +// provable before passing it along. Allows you to make any rpcclient fully secure. type Wrapper struct { rpcclient.Client cert *certifiers.Inquiring @@ -22,6 +24,8 @@ type Wrapper struct { // SecureClient uses a given certifier to wrap an connection to an untrusted // host and return a cryptographically secure rpc client. +// +// If it is wrapping an HTTP rpcclient, it will also wrap the websocket interface func SecureClient(c rpcclient.Client, cert *certifiers.Inquiring) Wrapper { wrap := Wrapper{c, cert} // if we wrap http client, then we can swap out the event switch to filter @@ -32,15 +36,18 @@ func SecureClient(c rpcclient.Client, cert *certifiers.Inquiring) Wrapper { return wrap } +// ABCIQueryWithOptions exposes all options for the ABCI query and verifies the returned proof func (w Wrapper) ABCIQueryWithOptions(path string, data data.Bytes, opts rpcclient.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) { res, _, err := GetWithProofOptions(path, data, opts, w.Client, w.cert) return res, err } +// ABCIQuery uses default options for the ABCI query and verifies the returned proof func (w Wrapper) ABCIQuery(path string, data data.Bytes) (*ctypes.ResultABCIQuery, error) { return w.ABCIQueryWithOptions(path, data, rpcclient.DefaultABCIQueryOptions) } +// Tx queries for a given tx and verifies the proof if it was requested func (w Wrapper) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) { res, err := w.Client.Tx(hash, prove) if !prove || err != nil { @@ -54,6 +61,10 @@ func (w Wrapper) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) { return res, err } +// BlockchainInfo requests a list of headers and verifies them all... +// Rather expensive. +// +// TODO: optimize this if used for anything needing performance func (w Wrapper) BlockchainInfo(minHeight, maxHeight int) (*ctypes.ResultBlockchainInfo, error) { r, err := w.Client.BlockchainInfo(minHeight, maxHeight) if err != nil { @@ -68,7 +79,6 @@ func (w Wrapper) BlockchainInfo(minHeight, maxHeight int) (*ctypes.ResultBlockch return nil, err } check := certclient.CommitFromResult(c) - // TODO: 3 err = ValidateBlockMeta(meta, check) if err != nil { return nil, err @@ -78,6 +88,7 @@ func (w Wrapper) BlockchainInfo(minHeight, maxHeight int) (*ctypes.ResultBlockch return r, nil } +// Block returns an entire block and verifies all signatures func (w Wrapper) Block(height *int) (*ctypes.ResultBlock, error) { r, err := w.Client.Block(height) if err != nil { @@ -116,11 +127,17 @@ func (w Wrapper) Commit(height *int) (*ctypes.ResultCommit, error) { return r, err } +// WrappedSwitch creates a websocket connection that auto-verifies any info +// coming through before passing it along. +// +// Since the verification takes 1-2 rpc calls, this is obviously only for +// relatively low-throughput situations that can tolerate a bit extra latency type WrappedSwitch struct { types.EventSwitch client rpcclient.Client } +// FireEvent verifies any block or header returned from the eventswitch func (s WrappedSwitch) FireEvent(event string, data events.EventData) { tm, ok := data.(types.TMEventData) if !ok { @@ -142,6 +159,7 @@ func (s WrappedSwitch) FireEvent(event string, data events.EventData) { fmt.Printf("Invalid block: %#v\n", err) return } + // TODO: can we verify tx as well? anything else } // looks good, we fire it From e6096d3e1fd0cd54342591b908da116e2f3c7972 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 27 Oct 2017 16:52:00 +0200 Subject: [PATCH 057/117] Test fails: app hash changes on reading data --- state/merkle_test.go | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/state/merkle_test.go b/state/merkle_test.go index 3e4fdb724b34..5fc7e9e56a91 100644 --- a/state/merkle_test.go +++ b/state/merkle_test.go @@ -99,3 +99,48 @@ func TestStateCommitHash(t *testing.T) { } } + +// Ensure getting data doesn't cause it to write +func TestGetDoesntWrite(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + // make the store... + tree := iavl.NewVersionedTree(0, db.NewMemDB()) + store := NewState(tree, 5) + + k, v := []byte("foo"), []byte("bar") + k2, v2 := []byte("abc"), []byte("def") + nok := []byte("baz") + + // one set should change something + store.Append().Set(k, v) + hash, err := store.Commit(1) + require.NoError(err) + require.NotNil(hash) + // calling hash returns last committed state + hash1 := store.LatestHash() + require.Equal(hash, hash1) + + // a second set will update the state + store.Append().Set(k2, v2) + hash, err = store.Commit(2) + require.NoError(err) + assert.NotEqual(hash1, hash) + // calling hash returns last committed state + hash2 := store.LatestHash() + require.Equal(hash, hash2) + + // a missed get will not do anything.... + val := store.Append().Get(nok) + assert.Nil(val) + hash, err = store.Commit(3) + require.NoError(err) + assert.Equal(hash2, hash) + + // a proper get will not do anything.... + val = store.Append().Get(k2) + assert.Equal(v2, val) + hash, err = store.Commit(4) + require.NoError(err) + assert.Equal(hash2, hash) +} From aa878581035b55062fd32e92a9ee63cfc438b44a Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 27 Oct 2017 17:02:36 +0200 Subject: [PATCH 058/117] Separate out read and write caches --- state/kvcache.go | 65 ++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/state/kvcache.go b/state/kvcache.go index 25ec29f9e672..666c9e37a4ce 100644 --- a/state/kvcache.go +++ b/state/kvcache.go @@ -2,8 +2,9 @@ package state // MemKVCache is designed to wrap MemKVStore as a cache type MemKVCache struct { - store SimpleDB - cache *MemKVStore + store SimpleDB + readCache *MemKVStore + writeCache *MemKVStore } var _ SimpleDB = (*MemKVCache)(nil) @@ -18,23 +19,34 @@ func NewMemKVCache(store SimpleDB) *MemKVCache { } return &MemKVCache{ - store: store, - cache: NewMemKVStore(), + store: store, + readCache: NewMemKVStore(), + writeCache: NewMemKVStore(), } } // Set sets a key, fulfills KVStore interface func (c *MemKVCache) Set(key []byte, value []byte) { - c.cache.Set(key, value) + // if we write it, remove from read cache + c.readCache.Remove(key) + c.writeCache.Set(key, value) } // Get gets a key, fulfills KVStore interface func (c *MemKVCache) Get(key []byte) (value []byte) { - value, ok := c.cache.m[string(key)] - if !ok { - value = c.store.Get(key) - c.cache.Set(key, value) + // see if we have a cached write + value, ok := c.writeCache.m[string(key)] + if ok { + return value + } + // then a cached read + value, ok = c.readCache.m[string(key)] + if ok { + return value } + // then read directly and cache it + value = c.store.Get(key) + c.readCache.Set(key, value) return value } @@ -44,19 +56,19 @@ func (c *MemKVCache) Has(key []byte) bool { return value != nil } -// Remove uses nil value as a flag to delete... not ideal but good enough -// for testing +// Remove uses nil value as a flag to delete... +// not ideal but good enough for testing func (c *MemKVCache) Remove(key []byte) (value []byte) { value = c.Get(key) - c.cache.Set(key, nil) + c.Set(key, nil) return value } // List is also inefficiently implemented... func (c *MemKVCache) List(start, end []byte, limit int) []Model { orig := c.store.List(start, end, 0) - cached := c.cache.List(start, end, 0) - keys := c.combineLists(orig, cached) + writen := c.writeCache.List(start, end, 0) + keys := c.combineLists(orig, writen) // apply limit (too late) if limit > 0 && len(keys) > 0 { @@ -69,19 +81,17 @@ func (c *MemKVCache) List(start, end []byte, limit int) []Model { return keys } -func (c *MemKVCache) combineLists(orig, cache []Model) []Model { +func (c *MemKVCache) combineLists(lists ...[]Model) []Model { store := NewMemKVStore() - for _, m := range orig { - store.Set(m.Key, m.Value) - } - for _, m := range cache { - if m.Value == nil { - store.Remove([]byte(m.Key)) - } else { - store.Set([]byte(m.Key), m.Value) + for _, cache := range lists { + for _, m := range cache { + if m.Value == nil { + store.Remove([]byte(m.Key)) + } else { + store.Set([]byte(m.Key), m.Value) + } } } - return store.List(nil, nil, 0) } @@ -131,8 +141,8 @@ func (c *MemKVCache) Commit(sub SimpleDB) error { // applyCache will apply all the cache methods to the underlying store func (c *MemKVCache) applyCache() { - for _, k := range c.cache.keysInRange(nil, nil) { - v := c.cache.m[k] + for _, k := range c.writeCache.keysInRange(nil, nil) { + v := c.writeCache.m[k] if v == nil { c.store.Remove([]byte(k)) } else { @@ -143,5 +153,6 @@ func (c *MemKVCache) applyCache() { // Discard will remove reference to this func (c *MemKVCache) Discard() { - c.cache = NewMemKVStore() + c.readCache = NewMemKVStore() + c.writeCache = NewMemKVStore() } From 0e14fd69102c6ecf49ac62c945030faae98a42eb Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Thu, 9 Nov 2017 09:40:23 -0500 Subject: [PATCH 059/117] Make function call defensive --- tests/cli/common.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/cli/common.sh b/tests/cli/common.sh index aaeaca500c63..76d5e9030766 100644 --- a/tests/cli/common.sh +++ b/tests/cli/common.sh @@ -15,6 +15,12 @@ quickSetup() { BASE_DIR=$HOME/$1 CHAIN_ID=$2 + # TODO Make this more robust + if [ "$BASE_DIR" == "$HOME/" ]; then + echo "quickSetup() must be called with argument, or it will wipe your home directory" + exit 1 + fi + rm -rf $BASE_DIR 2>/dev/null mkdir -p $BASE_DIR From 9067ae1d81b964eafb9bb0c959fbc55d92ccf00a Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Fri, 17 Nov 2017 14:16:57 +0000 Subject: [PATCH 060/117] remove RELEASE.md --- RELEASE.md | 56 ------------------------------------------------------ 1 file changed, 56 deletions(-) delete mode 100644 RELEASE.md diff --git a/RELEASE.md b/RELEASE.md deleted file mode 100644 index f45008261d66..000000000000 --- a/RELEASE.md +++ /dev/null @@ -1,56 +0,0 @@ -# Release Process - -Basecoin is the heart of most demo apps and the testnets, but the last few releases have been a little chaotic. In order to guarantee a higher, production-quality release in the future, we will work on a release process to check before the push to master. This is a work-in-progress and should be trialed on the 0.6.x patches, and used for the 0.7.0 release. - -This is a rough-guide. Please add comments here, let's try it out for 0.6.1 and see what is annoying and useless, and what is missing and useful. - -## Planning - -* Create issues (and invite others to do so) -* Create WIP PR for release as placeholder - * Clarify scope of release in text -* Create labels, eg. (0.6.1 and 0.6.x) -* Tag all issues for this release with 0.6.1 - * Other, less urgent enhancements should get the 0.6.x label - -## Coding - -* Freeze tagging more issues for this release - * Update PR to note this - * If you want an exception, you need a good excuse ;) -* Handle all issues - * Write code - * Update CHANGELOG - * Review and merge -* Update version -* Remove WIP flag on PR -* Organize QA -* Prepare blog post (optional for patch/bugfix releases?) - -## QA - -Once we have a PR for the release and think it is ready, we should test it out internally: - -* Code review - * Hopefully dealt with by individual code reviews on the merged issues - * A general run-through is always good to find dead-code, things to cleanup -* Review blog post (and run-through) -* Manual run-through of tutorials (and feedback on bad UX) -* Deployment of a private testnet, multiple users test out manually (feedback on bugs, or annoying UX) -* Test out upgrading existing testnet from last version, document or add tools for easier upgrade. -* If problems arrise here: - * Create bugfix issues - * Fix them - * Repeat QA - -## Release - -Once QA passes, we need to orchestrate the release. - -* Merge to master -* Set all glide dependencies to proper master versions of repos -* Push code with new version tag -* Link CHANGELOG to the [github release](https://github.com/tendermint/basecoin/releases) -* Package up new version as binaries (and upload to s3) -* Upgrade our public-facing testnets with the latest versions -* Release blog post From b6a4fe50f9fa649fe76cb0c6cb531988e84e0fb8 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Fri, 17 Nov 2017 14:21:02 +0000 Subject: [PATCH 061/117] update README, closes #272 --- README.md | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 3e759ebc337f..15a606179f51 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ master | [![CircleCI](https://circleci.com/gh/cosmos/cosmos-sdk/tree/master.s The Cosmos SDK is the middleware platform that the [Cosmos Hub](https://cosmos.network) is constructed from. The Hub is a blockchain (or, internet of blockchains) in which the Atom supply resides. The Atoms supply is defined at genesis and can change based on the rules of the Hub. -Under the hood, the Cosmos SDK is an [ABCI application](https://github.com/tendermint/abci) designed to be used with the [Tendermint consensus engine](https://tendermint.com/) to form a Proof-of-Stake cryptocurrency. It also provides a general purpose framework +Under the hood, the Cosmos SDK is an [ABCI application](https://github.com/tendermint/abci) designed to be used with the [Tendermint consensus engine](https://github.com/tendermint/tendermint) to form a Proof-of-Stake cryptocurrency. It also provides a general purpose framework for extending the feature-set of the cryptocurrency by implementing plugins. This SDK affords you all the tools you need to rapidly develop @@ -45,23 +45,13 @@ Within this repository, the `basecoin` app serves as a reference implementation * [golang](https://golang.org/doc/install) -## Installation +## Installation and Documentation ``` go get -u github.com/cosmos/cosmos-sdk/cmd/basecoin ``` -See the [install guide](/docs/guide/install.md) for more details. - -## Guides - -* Getting started with the [Basecoin basics](/docs/guide/basecoin-basics.md) -* Learn to [use the plugin system](/docs/guide/basecoin-plugins.md) -* More features of the [Basecoin tool](/docs/guide/basecoin-tool.md) -* Learn how to use [Inter-Blockchain Communication (IBC)](/docs/guide/ibc.md) -* See [more examples](https://github.com/cosmos/cosmos-academy) - -To deploy a testnet, see our [repository of deployment tools](https://github.com/tendermint/tools). +See the [Cosmos SDK Documentation](http://cosmos-sdk.readthedocs.io/en/latest/) for complete installation details and usage documentation. To deploy a testnet, see our [repository of deployment tools](https://github.com/tendermint/tools). # Inspiration From 8da0f3f38ab815a05dcfce995ca355a9c13ac8af Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 22 Nov 2017 16:07:10 +0100 Subject: [PATCH 062/117] Updated to latest develop, removed websocket from proxy due to changes --- client/proxy.go | 7 ++- client/wrapper.go | 88 ++++++++++++++++++------------------ glide.lock | 30 ++++++------ modules/coin/handler_test.go | 2 +- 4 files changed, 65 insertions(+), 62 deletions(-) diff --git a/client/proxy.go b/client/proxy.go index 6518dfadbcd5..0acb79031ad0 100644 --- a/client/proxy.go +++ b/client/proxy.go @@ -24,7 +24,12 @@ func StartProxy(c rpcclient.Client, bind string, logger log.Logger) error { // build the handler... mux := http.NewServeMux() rpc.RegisterRPCFuncs(mux, r, logger) - wm := rpc.NewWebsocketManager(r, c) + + onDisconnect := rpc.OnDisconnect(func(remoteAddr string) { + // FIXME: TODO + // n.eventBus.UnsubscribeAll(context.Background(), remoteAddr) + }) + wm := rpc.NewWebsocketManager(r, onDisconnect) wm.SetLogger(logger) core.SetLogger(logger) mux.HandleFunc(wsEndpoint, wm.WebsocketHandler) diff --git a/client/wrapper.go b/client/wrapper.go index 3bebd822192a..b01235902a9c 100644 --- a/client/wrapper.go +++ b/client/wrapper.go @@ -1,10 +1,7 @@ package client import ( - "fmt" - "github.com/tendermint/go-wire/data" - "github.com/tendermint/tmlibs/events" "github.com/tendermint/tendermint/certifiers" certclient "github.com/tendermint/tendermint/certifiers/client" @@ -28,11 +25,12 @@ type Wrapper struct { // If it is wrapping an HTTP rpcclient, it will also wrap the websocket interface func SecureClient(c rpcclient.Client, cert *certifiers.Inquiring) Wrapper { wrap := Wrapper{c, cert} + // TODO: no longer possible as no more such interface exposed.... // if we wrap http client, then we can swap out the event switch to filter - if hc, ok := c.(*rpcclient.HTTP); ok { - evt := hc.WSEvents.EventSwitch - hc.WSEvents.EventSwitch = WrappedSwitch{evt, wrap} - } + // if hc, ok := c.(*rpcclient.HTTP); ok { + // evt := hc.WSEvents.EventSwitch + // hc.WSEvents.EventSwitch = WrappedSwitch{evt, wrap} + // } return wrap } @@ -127,44 +125,44 @@ func (w Wrapper) Commit(height *int) (*ctypes.ResultCommit, error) { return r, err } -// WrappedSwitch creates a websocket connection that auto-verifies any info -// coming through before passing it along. -// -// Since the verification takes 1-2 rpc calls, this is obviously only for -// relatively low-throughput situations that can tolerate a bit extra latency -type WrappedSwitch struct { - types.EventSwitch - client rpcclient.Client -} - -// FireEvent verifies any block or header returned from the eventswitch -func (s WrappedSwitch) FireEvent(event string, data events.EventData) { - tm, ok := data.(types.TMEventData) - if !ok { - fmt.Printf("bad type %#v\n", data) - return - } - - // check to validate it if possible, and drop if not valid - switch t := tm.Unwrap().(type) { - case types.EventDataNewBlockHeader: - err := verifyHeader(s.client, t.Header) - if err != nil { - fmt.Printf("Invalid header: %#v\n", err) - return - } - case types.EventDataNewBlock: - err := verifyBlock(s.client, t.Block) - if err != nil { - fmt.Printf("Invalid block: %#v\n", err) - return - } - // TODO: can we verify tx as well? anything else - } - - // looks good, we fire it - s.EventSwitch.FireEvent(event, data) -} +// // WrappedSwitch creates a websocket connection that auto-verifies any info +// // coming through before passing it along. +// // +// // Since the verification takes 1-2 rpc calls, this is obviously only for +// // relatively low-throughput situations that can tolerate a bit extra latency +// type WrappedSwitch struct { +// types.EventSwitch +// client rpcclient.Client +// } + +// // FireEvent verifies any block or header returned from the eventswitch +// func (s WrappedSwitch) FireEvent(event string, data events.EventData) { +// tm, ok := data.(types.TMEventData) +// if !ok { +// fmt.Printf("bad type %#v\n", data) +// return +// } + +// // check to validate it if possible, and drop if not valid +// switch t := tm.Unwrap().(type) { +// case types.EventDataNewBlockHeader: +// err := verifyHeader(s.client, t.Header) +// if err != nil { +// fmt.Printf("Invalid header: %#v\n", err) +// return +// } +// case types.EventDataNewBlock: +// err := verifyBlock(s.client, t.Block) +// if err != nil { +// fmt.Printf("Invalid block: %#v\n", err) +// return +// } +// // TODO: can we verify tx as well? anything else +// } + +// // looks good, we fire it +// s.EventSwitch.FireEvent(event, data) +// } func verifyHeader(c rpcclient.Client, head *types.Header) error { // get a checkpoint to verify from diff --git a/glide.lock b/glide.lock index f25122a5b7a2..923e95eaad70 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 809845bf4c18a4abc85cf5d7b5ee7a17e0f437cd377b22e158787c718272261a -updated: 2017-10-26T16:18:37.833408343+02:00 +updated: 2017-11-22T12:10:57.995842504+01:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -12,9 +12,9 @@ imports: - name: github.com/ebuchman/fail-test version: 95f809107225be108efcf10a3509e4ea6ceef3c4 - name: github.com/ethanfrey/hid - version: f379bda1dbc8e79333b04563f71a12e86206efe5 + version: dce75af84cf849c60f39bf1b8192fb5cd597b5d9 - name: github.com/ethanfrey/ledger - version: 3689ce9be93e1a5bef836b1cc2abb18381c79176 + version: f7f2f056357db77db845a79aa1abdadc3ae66369 - name: github.com/fsnotify/fsnotify version: 4da3e2cfbabc9f751898f250b49f2439785783a1 - name: github.com/go-kit/kit @@ -89,7 +89,7 @@ imports: - name: github.com/spf13/cast version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 - name: github.com/spf13/cobra - version: 7b2c5ac9fc04fc5efafb60700713d4fa609b777b + version: 19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f - name: github.com/spf13/jwalterweatherman version: 12bd96e66386c1960ab0f74ced1362f66f552f7b - name: github.com/spf13/pflag @@ -112,21 +112,20 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: a0e38dc58374f485481ea07b23659d85f670a694 + version: bee7c5c7aa09443c4d9aa74217a891f8229d9ea3 subpackages: - client - example/dummy - server - types - name: github.com/tendermint/ed25519 - version: 1f52c6f8b8a5c7908aff4497c186af344b428925 + version: d8387025d2b9d158cf4efb07e7ebf814bcce2057 subpackages: - edwards25519 - extra25519 - name: github.com/tendermint/go-crypto - version: db5603e37435933c13665a708055fadd18222f5f + version: b4f04f196cd719660e43b91202cd60d9a95b1837 subpackages: - - bcrypt - keys - keys/cryptostore - keys/storage/filestorage @@ -134,14 +133,14 @@ imports: - keys/wordlist - nano - name: github.com/tendermint/go-wire - version: 3180c867ca52bcd9ba6c905ce63613f8d8e9837c + version: 7d50b38b3815efe313728de77e2995c8813ce13f subpackages: - data - data/base58 - name: github.com/tendermint/iavl version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653 - name: github.com/tendermint/tendermint - version: bb6c15b00a07e2aafc7fe245b3acfb33b9c25abe + version: e997db7a23d3e51b2b265f892226e980ae4c8300 subpackages: - blockchain - certifiers @@ -155,6 +154,7 @@ imports: - mempool - node - p2p + - p2p/trust - p2p/upnp - proxy - rpc/client @@ -173,7 +173,7 @@ imports: - types - version - name: github.com/tendermint/tmlibs - version: b30e3ba26d4077edeed83c50a4e0c38b0ec9ddb3 + version: 135a1a7cd78215105a55308c167b3331c225e00b subpackages: - autofile - cli @@ -186,11 +186,11 @@ imports: - log - logger - merkle - - test + - pubsub + - pubsub/query - name: golang.org/x/crypto version: edd5e9b0879d13ee6970a50153d85b8fec9f7686 subpackages: - - blowfish - curve25519 - nacl/box - nacl/secretbox @@ -249,7 +249,7 @@ imports: version: eb3733d160e74a9c7e442f435eb3bea458e1d19f testImports: - name: github.com/davecgh/go-spew - version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 + version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 subpackages: - spew - name: github.com/pmezard/go-difflib @@ -257,7 +257,7 @@ testImports: subpackages: - difflib - name: github.com/stretchr/testify - version: 2aa2c176b9dab406a6970f6a55f513e8a8c8b18f + version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 subpackages: - assert - require diff --git a/modules/coin/handler_test.go b/modules/coin/handler_test.go index 20941a860402..3df51d8e56b0 100644 --- a/modules/coin/handler_test.go +++ b/modules/coin/handler_test.go @@ -252,7 +252,7 @@ func TestSetIssuer(t *testing.T) { }{ {sdk.Actor{App: "sig", Address: []byte("gwkfgk")}}, // and set back to empty (nil is valid, but assert.Equals doesn't match) - {sdk.Actor{}}, + {sdk.Actor{Address: []byte{}}}, {sdk.Actor{ChainID: "other", App: "role", Address: []byte("vote")}}, } From a84c9bfc71ec91a724f038cf47eed41e397fd97c Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 20 Oct 2017 12:50:08 +0200 Subject: [PATCH 063/117] fixing CommitHash not available --- Makefile | 4 ++-- examples/basecoin/Makefile | 5 +++-- examples/counter/Makefile | 5 +++-- examples/eyes/Makefile | 3 ++- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 02cd94cc2c92..5f4c701ce45e 100644 --- a/Makefile +++ b/Makefile @@ -6,8 +6,8 @@ TUTORIALS=$(shell find docs/guide -name "*md" -type f) EXAMPLES := counter eyes basecoin INSTALL_EXAMPLES := $(addprefix install_,${EXAMPLES}) TEST_EXAMPLES := $(addprefix testex_,${EXAMPLES}) - -LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=`git rev-parse --short HEAD`" +COMMIT_HASH := $(shell git rev-parse --short HEAD) +LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=${COMMIT_HASH}" all: get_vendor_deps install test diff --git a/examples/basecoin/Makefile b/examples/basecoin/Makefile index 78dd637e898e..debe051e9fd8 100644 --- a/examples/basecoin/Makefile +++ b/examples/basecoin/Makefile @@ -1,7 +1,8 @@ -LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=`git rev-parse --short HEAD`" +COMMIT_HASH := $(shell git rev-parse --short HEAD) +LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=${COMMIT_HASH}" install: - @go install -ldflags $(LINKER_FLAGS) ./cmd/... + go install -ldflags $(LINKER_FLAGS) ./cmd/... test: test_unit test_cli diff --git a/examples/counter/Makefile b/examples/counter/Makefile index 9fd61be897f6..4bd53fc9a5ac 100644 --- a/examples/counter/Makefile +++ b/examples/counter/Makefile @@ -1,4 +1,5 @@ -LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=`git rev-parse --short HEAD`" +COMMIT_HASH := $(shell git rev-parse --short HEAD) +LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=${COMMIT_HASH}" install: @go install -ldflags $(LINKER_FLAGS) ./cmd/... @@ -11,4 +12,4 @@ test_unit: test_cli: ./tests/cli/counter.sh -.PHONY: install test test_unit test_cli +.PHONY: install test test_unit test_cli \ No newline at end of file diff --git a/examples/eyes/Makefile b/examples/eyes/Makefile index e543a4ccf09c..632736e3bd33 100644 --- a/examples/eyes/Makefile +++ b/examples/eyes/Makefile @@ -1,4 +1,5 @@ -LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=`git rev-parse --short HEAD`" +COMMIT_HASH := $(shell git rev-parse --short HEAD) +LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=${COMMIT_HASH}" install: @go install -ldflags $(LINKER_FLAGS) ./cmd/... From bf6b88434c3afa8bb47013cc4ba22c7f7ef02026 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 20 Oct 2017 12:50:51 +0200 Subject: [PATCH 064/117] making install silent again --- examples/basecoin/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/basecoin/Makefile b/examples/basecoin/Makefile index debe051e9fd8..6474c9a97062 100644 --- a/examples/basecoin/Makefile +++ b/examples/basecoin/Makefile @@ -2,7 +2,7 @@ COMMIT_HASH := $(shell git rev-parse --short HEAD) LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=${COMMIT_HASH}" install: - go install -ldflags $(LINKER_FLAGS) ./cmd/... + @go install -ldflags $(LINKER_FLAGS) ./cmd/... test: test_unit test_cli From 1ec14f59289ca1e876cf6ee1a539ab648498f0a0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Nov 2017 16:21:36 +0100 Subject: [PATCH 065/117] fix backticks not available on windows --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 5f4c701ce45e..d8f63456be52 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,7 @@ INSTALL_EXAMPLES := $(addprefix install_,${EXAMPLES}) TEST_EXAMPLES := $(addprefix testex_,${EXAMPLES}) COMMIT_HASH := $(shell git rev-parse --short HEAD) LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=${COMMIT_HASH}" +NOVENDOR := $(shell glide novendor) all: get_vendor_deps install test @@ -21,7 +22,7 @@ $(TEST_EXAMPLES): testex_%: cd ./examples/$* && make test_cli install: $(INSTALL_EXAMPLES) - @go install -ldflags $(LINKER_FLAGS) ./cmd/... + go install -ldflags $(LINKER_FLAGS) ./cmd/... dist: @bash publish/dist.sh @@ -34,7 +35,7 @@ benchmark: test: test_unit test_cli test_unit: - @go test `glide novendor` + @go test $(NOVENDOR) test_cli: $(TEST_EXAMPLES) # sudo apt-get install jq From 3c2e93df31baad083f9a586dfee75d51fc4136ab Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Nov 2017 16:26:13 +0100 Subject: [PATCH 066/117] removing more backticks --- examples/basecoin/Makefile | 3 ++- examples/counter/Makefile | 3 ++- examples/eyes/Makefile | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/basecoin/Makefile b/examples/basecoin/Makefile index 6474c9a97062..17f8d5295c26 100644 --- a/examples/basecoin/Makefile +++ b/examples/basecoin/Makefile @@ -1,5 +1,6 @@ COMMIT_HASH := $(shell git rev-parse --short HEAD) LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=${COMMIT_HASH}" +NOVENDOR := $(shell glide novendor) install: @go install -ldflags $(LINKER_FLAGS) ./cmd/... @@ -7,7 +8,7 @@ install: test: test_unit test_cli test_unit: - @go test `glide novendor` + @go test $(NOVENDOR) test_cli: ./tests/cli/keys.sh diff --git a/examples/counter/Makefile b/examples/counter/Makefile index 4bd53fc9a5ac..24ee75a35abe 100644 --- a/examples/counter/Makefile +++ b/examples/counter/Makefile @@ -1,5 +1,6 @@ COMMIT_HASH := $(shell git rev-parse --short HEAD) LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=${COMMIT_HASH}" +NOVENDOR := $(shell glide novendor) install: @go install -ldflags $(LINKER_FLAGS) ./cmd/... @@ -7,7 +8,7 @@ install: test: test_unit test_cli test_unit: - @go test `glide novendor` + @go test $(NOVENDOR) test_cli: ./tests/cli/counter.sh diff --git a/examples/eyes/Makefile b/examples/eyes/Makefile index 632736e3bd33..91a799664fa6 100644 --- a/examples/eyes/Makefile +++ b/examples/eyes/Makefile @@ -1,5 +1,6 @@ COMMIT_HASH := $(shell git rev-parse --short HEAD) LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=${COMMIT_HASH}" +NOVENDOR := $(shell glide novendor) install: @go install -ldflags $(LINKER_FLAGS) ./cmd/... @@ -7,7 +8,7 @@ install: test: test_unit test_cli test_unit: - @go test `glide novendor` + @go test $(NOVENDOR) test_cli: ./tests/cli/eyes.sh From 032a2907b2c16672eb587ab026c557b7a35752aa Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 30 Nov 2017 16:49:50 +0100 Subject: [PATCH 067/117] Update glide to branch with indexing --- app/base.go | 19 ++++++------- app/store.go | 16 ++++++----- client/block.go | 10 +++---- client/commands/commits/export.go | 2 +- client/commands/commits/import.go | 2 +- client/commands/commits/show.go | 6 ++--- client/commands/commits/update.go | 4 +-- client/commands/common.go | 14 +++++----- client/commands/init.go | 8 +++--- client/commands/query/tx.go | 4 +-- client/common.go | 22 +++++++-------- client/query.go | 27 ++++++++++--------- client/query_test.go | 8 +++--- client/wrapper.go | 13 ++++----- errors/main.go | 20 +++++++++++--- glide.lock | 38 ++++++++++++++------------ glide.yaml | 2 +- handler.go | 45 +++++++++++-------------------- modules/ibc/commands/tx.go | 4 +-- modules/ibc/ibc_test.go | 18 ++++++------- modules/ibc/noop.go | 26 ++++++++++++++++++ modules/ibc/provider.go | 24 ++++++++--------- modules/ibc/provider_test.go | 16 +++++------ modules/ibc/test_helpers.go | 10 +++---- modules/ibc/tx.go | 6 ++--- server/commands/start.go | 2 +- 26 files changed, 200 insertions(+), 166 deletions(-) create mode 100644 modules/ibc/noop.go diff --git a/app/base.go b/app/base.go index 2ba14fd6469d..e45d3a11d6cc 100644 --- a/app/base.go +++ b/app/base.go @@ -30,10 +30,10 @@ func NewBaseApp(store *StoreApp, handler sdk.Handler, clock sdk.Ticker) *BaseApp } // DeliverTx - ABCI - dispatches to the handler -func (app *BaseApp) DeliverTx(txBytes []byte) abci.Result { +func (app *BaseApp) DeliverTx(txBytes []byte) abci.ResponseDeliverTx { tx, err := sdk.LoadTx(txBytes) if err != nil { - return errors.Result(err) + return errors.DeliverResult(err) } ctx := stack.NewContext( @@ -44,17 +44,17 @@ func (app *BaseApp) DeliverTx(txBytes []byte) abci.Result { res, err := app.handler.DeliverTx(ctx, app.Append(), tx) if err != nil { - return errors.Result(err) + return errors.DeliverResult(err) } app.AddValChange(res.Diff) - return sdk.ToABCI(res) + return res.ToABCI() } // CheckTx - ABCI - dispatches to the handler -func (app *BaseApp) CheckTx(txBytes []byte) abci.Result { +func (app *BaseApp) CheckTx(txBytes []byte) abci.ResponseCheckTx { tx, err := sdk.LoadTx(txBytes) if err != nil { - return errors.Result(err) + return errors.CheckResult(err) } ctx := stack.NewContext( @@ -65,13 +65,13 @@ func (app *BaseApp) CheckTx(txBytes []byte) abci.Result { res, err := app.handler.CheckTx(ctx, app.Check(), tx) if err != nil { - return errors.Result(err) + return errors.CheckResult(err) } - return sdk.ToABCI(res) + return res.ToABCI() } // BeginBlock - ABCI - triggers Tick actions -func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) { +func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { // execute tick if present if app.clock != nil { ctx := stack.NewContext( @@ -86,6 +86,7 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) { } app.AddValChange(diff) } + return res } // InitState - used to setup state (was SetOption) diff --git a/app/store.go b/app/store.go index faa0d77ce83d..05fb43c59048 100644 --- a/app/store.go +++ b/app/store.go @@ -124,8 +124,8 @@ func (app *StoreApp) Info(req abci.RequestInfo) abci.ResponseInfo { } // SetOption - ABCI -func (app *StoreApp) SetOption(key string, value string) string { - return "Not Implemented" +func (app *StoreApp) SetOption(res abci.RequestSetOption) abci.ResponseSetOption { + return abci.ResponseSetOption{Log: "Not Implemented"} } // Query - ABCI @@ -180,7 +180,7 @@ func (app *StoreApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQu } // Commit implements abci.Application -func (app *StoreApp) Commit() (res abci.Result) { +func (app *StoreApp) Commit() (res abci.ResponseCommit) { app.height++ hash, err := app.state.Commit(app.height) @@ -194,20 +194,22 @@ func (app *StoreApp) Commit() (res abci.Result) { ) if app.state.Size() == 0 { - return abci.NewResultOK(nil, "Empty hash for empty tree") + return abci.ResponseCommit{Log: "Empty hash for empty tree"} } - return abci.NewResultOK(hash, "") + return abci.ResponseCommit{Data: hash} } // InitChain - ABCI -func (app *StoreApp) InitChain(req abci.RequestInitChain) {} +func (app *StoreApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) { + return +} // BeginBlock - ABCI func (app *StoreApp) BeginBlock(req abci.RequestBeginBlock) {} // EndBlock - ABCI // Returns a list of all validator changes made in this block -func (app *StoreApp) EndBlock(height uint64) (res abci.ResponseEndBlock) { +func (app *StoreApp) EndBlock(_ abci.RequestEndBlock) (res abci.ResponseEndBlock) { // TODO: cleanup in case a validator exists multiple times in the list res.Diffs = app.pending app.pending = nil diff --git a/client/block.go b/client/block.go index 2bf3f39a8208..178774eb643f 100644 --- a/client/block.go +++ b/client/block.go @@ -5,17 +5,17 @@ import ( "github.com/pkg/errors" - "github.com/tendermint/tendermint/certifiers" - certerr "github.com/tendermint/tendermint/certifiers/errors" + "github.com/tendermint/tendermint/lite" + certerr "github.com/tendermint/tendermint/lite/errors" "github.com/tendermint/tendermint/types" ) -func ValidateBlockMeta(meta *types.BlockMeta, check certifiers.Commit) error { +func ValidateBlockMeta(meta *types.BlockMeta, check lite.Commit) error { // TODO: check the BlockID?? return ValidateHeader(meta.Header, check) } -func ValidateBlock(meta *types.Block, check certifiers.Commit) error { +func ValidateBlock(meta *types.Block, check lite.Commit) error { err := ValidateHeader(meta.Header, check) if err != nil { return err @@ -26,7 +26,7 @@ func ValidateBlock(meta *types.Block, check certifiers.Commit) error { return nil } -func ValidateHeader(head *types.Header, check certifiers.Commit) error { +func ValidateHeader(head *types.Header, check lite.Commit) error { // make sure they are for the same height (obvious fail) if head.Height != check.Height() { return certerr.ErrHeightMismatch(head.Height, check.Height()) diff --git a/client/commands/commits/export.go b/client/commands/commits/export.go index b0b1c2a64cc2..0bcb3f5589cd 100644 --- a/client/commands/commits/export.go +++ b/client/commands/commits/export.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/tendermint/certifiers/files" + "github.com/tendermint/tendermint/lite/files" "github.com/cosmos/cosmos-sdk/client/commands" ) diff --git a/client/commands/commits/import.go b/client/commands/commits/import.go index 3af3d79e6a4d..dedf1deb82f9 100644 --- a/client/commands/commits/import.go +++ b/client/commands/commits/import.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/tendermint/certifiers/files" + "github.com/tendermint/tendermint/lite/files" "github.com/cosmos/cosmos-sdk/client/commands" ) diff --git a/client/commands/commits/show.go b/client/commands/commits/show.go index 67152044c900..f7d5fee58d6d 100644 --- a/client/commands/commits/show.go +++ b/client/commands/commits/show.go @@ -8,8 +8,8 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/tendermint/certifiers" - "github.com/tendermint/tendermint/certifiers/files" + "github.com/tendermint/tendermint/lite" + "github.com/tendermint/tendermint/lite/files" "github.com/cosmos/cosmos-sdk/client/commands" ) @@ -37,7 +37,7 @@ func init() { RootCmd.AddCommand(showCmd) } -func loadCommit(p certifiers.Provider, h int, hash, file string) (fc certifiers.FullCommit, err error) { +func loadCommit(p lite.Provider, h int, hash, file string) (fc lite.FullCommit, err error) { // load the commit from the proper place if h != 0 { fc, err = p.GetByHeight(h) diff --git a/client/commands/commits/update.go b/client/commands/commits/update.go index f522a914a345..3bc0449722c3 100644 --- a/client/commands/commits/update.go +++ b/client/commands/commits/update.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/tendermint/certifiers" + "github.com/tendermint/tendermint/lite" "github.com/cosmos/cosmos-sdk/client/commands" ) @@ -30,7 +30,7 @@ func updateCommit(cmd *cobra.Command, args []string) error { } h := viper.GetInt(heightFlag) - var fc certifiers.FullCommit + var fc lite.FullCommit if h <= 0 { // get the lastest from our source fc, err = cert.Source.LatestCommit() diff --git a/client/commands/common.go b/client/commands/common.go index ff93a05a69c2..019167b9c67e 100644 --- a/client/commands/common.go +++ b/client/commands/common.go @@ -12,7 +12,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/tendermint/certifiers" + "github.com/tendermint/tendermint/lite" "github.com/tendermint/tmlibs/cli" cmn "github.com/tendermint/tmlibs/common" @@ -24,8 +24,8 @@ import ( ) var ( - trustedProv certifiers.Provider - sourceProv certifiers.Provider + trustedProv lite.Provider + sourceProv lite.Provider ) const ( @@ -50,7 +50,7 @@ func GetNode() rpcclient.Client { } // GetSourceProvider returns a provider pointing to an rpc handler -func GetSourceProvider() certifiers.Provider { +func GetSourceProvider() lite.Provider { if sourceProv == nil { node := viper.GetString(NodeFlag) sourceProv = client.GetRPCProvider(node) @@ -59,7 +59,7 @@ func GetSourceProvider() certifiers.Provider { } // GetTrustedProvider returns a reference to a local store with cache -func GetTrustedProvider() certifiers.Provider { +func GetTrustedProvider() lite.Provider { if trustedProv == nil { rootDir := viper.GetString(cli.HomeFlag) trustedProv = client.GetLocalProvider(rootDir) @@ -69,12 +69,12 @@ func GetTrustedProvider() certifiers.Provider { // GetProviders creates a trusted (local) seed provider and a remote // provider based on configuration. -func GetProviders() (trusted certifiers.Provider, source certifiers.Provider) { +func GetProviders() (trusted lite.Provider, source lite.Provider) { return GetTrustedProvider(), GetSourceProvider() } // GetCertifier constructs a dynamic certifier from the config info -func GetCertifier() (*certifiers.Inquiring, error) { +func GetCertifier() (*lite.Inquiring, error) { // load up the latest store.... trust := GetTrustedProvider() source := GetSourceProvider() diff --git a/client/commands/init.go b/client/commands/init.go index c290d1e14a6e..32085fbc0b97 100644 --- a/client/commands/init.go +++ b/client/commands/init.go @@ -15,8 +15,8 @@ import ( "github.com/spf13/pflag" "github.com/spf13/viper" - "github.com/tendermint/tendermint/certifiers" - "github.com/tendermint/tendermint/certifiers/files" + "github.com/tendermint/tendermint/lite" + "github.com/tendermint/tendermint/lite/files" "github.com/tendermint/tmlibs/cli" cmn "github.com/tendermint/tmlibs/common" @@ -280,7 +280,7 @@ func initTrust() (err error) { trust, source := GetProviders() // load a commit file, or get data from the provider - var fc certifiers.FullCommit + var fc lite.FullCommit commitFile := viper.GetString(CommitFlag) if commitFile == "" { fmt.Println("Loading validator set from tendermint rpc...") @@ -321,7 +321,7 @@ func initTrust() (err error) { return nil } -func validateHash(fc certifiers.FullCommit) error { +func validateHash(fc lite.FullCommit) error { // ask the user to verify the validator hash fmt.Println("\nImportant: if this is incorrect, all interaction with the chain will be insecure!") fmt.Printf(" Given validator hash valid: %X\n", fc.ValidatorsHash()) diff --git a/client/commands/query/tx.go b/client/commands/query/tx.go index 8f86c09bb168..f3fed3472fa1 100644 --- a/client/commands/query/tx.go +++ b/client/commands/query/tx.go @@ -67,11 +67,11 @@ func txQueryCmd(cmd *cobra.Command, args []string) error { } // showTx parses anything that was previously registered as sdk.Tx -func showTx(h int, tx types.Tx) error { +func showTx(h uint64, tx types.Tx) error { var info sdk.Tx err := wire.ReadBinaryBytes(tx, &info) if err != nil { return err } - return OutputProof(info, uint64(h)) + return OutputProof(info, h) } diff --git a/client/common.go b/client/common.go index 17ff9a1ba1d3..1705c529b7c4 100644 --- a/client/common.go +++ b/client/common.go @@ -3,10 +3,10 @@ package client import ( "errors" - "github.com/tendermint/tendermint/certifiers" - certclient "github.com/tendermint/tendermint/certifiers/client" - certerr "github.com/tendermint/tendermint/certifiers/errors" - "github.com/tendermint/tendermint/certifiers/files" + "github.com/tendermint/tendermint/lite" + certclient "github.com/tendermint/tendermint/lite/client" + certerr "github.com/tendermint/tendermint/lite/errors" + "github.com/tendermint/tendermint/lite/files" rpcclient "github.com/tendermint/tendermint/rpc/client" ) @@ -18,23 +18,23 @@ func GetNode(url string) rpcclient.Client { // GetRPCProvider retuns a certifier compatible data source using // tendermint RPC -func GetRPCProvider(url string) certifiers.Provider { +func GetRPCProvider(url string) lite.Provider { return certclient.NewHTTPProvider(url) } // GetLocalProvider returns a reference to a file store of headers // wrapped with an in-memory cache -func GetLocalProvider(dir string) certifiers.Provider { - return certifiers.NewCacheProvider( - certifiers.NewMemStoreProvider(), +func GetLocalProvider(dir string) lite.Provider { + return lite.NewCacheProvider( + lite.NewMemStoreProvider(), files.NewProvider(dir), ) } // GetCertifier initializes an inquiring certifier given a fixed chainID // and a local source of trusted data with at least one seed -func GetCertifier(chainID string, trust certifiers.Provider, - source certifiers.Provider) (*certifiers.Inquiring, error) { +func GetCertifier(chainID string, trust lite.Provider, + source lite.Provider) (*lite.Inquiring, error) { // this gets the most recent verified commit fc, err := trust.LatestCommit() @@ -44,6 +44,6 @@ func GetCertifier(chainID string, trust certifiers.Provider, if err != nil { return nil, err } - cert := certifiers.NewInquiring(chainID, fc, trust, source) + cert := lite.NewInquiring(chainID, fc, trust, source) return cert, nil } diff --git a/client/query.go b/client/query.go index 6a0c3469a90a..8be143dd2945 100644 --- a/client/query.go +++ b/client/query.go @@ -6,9 +6,9 @@ import ( "github.com/tendermint/go-wire/data" "github.com/tendermint/iavl" - "github.com/tendermint/tendermint/certifiers" - "github.com/tendermint/tendermint/certifiers/client" - certerr "github.com/tendermint/tendermint/certifiers/errors" + "github.com/tendermint/tendermint/lite" + "github.com/tendermint/tendermint/lite/client" + certerr "github.com/tendermint/tendermint/lite/errors" rpcclient "github.com/tendermint/tendermint/rpc/client" ctypes "github.com/tendermint/tendermint/rpc/core/types" ) @@ -20,7 +20,7 @@ import ( // If val is non-empty, proof should be KeyExistsProof // If val is empty, proof should be KeyMissingProof func GetWithProof(key []byte, reqHeight int, node rpcclient.Client, - cert certifiers.Certifier) ( + cert lite.Certifier) ( val data.Bytes, height uint64, proof iavl.KeyProof, err error) { if reqHeight < 0 { @@ -39,7 +39,7 @@ func GetWithProof(key []byte, reqHeight int, node rpcclient.Client, // GetWithProofOptions is useful if you want full access to the ABCIQueryOptions func GetWithProofOptions(path string, key []byte, opts rpcclient.ABCIQueryOptions, - node rpcclient.Client, cert certifiers.Certifier) ( + node rpcclient.Client, cert lite.Certifier) ( *ctypes.ResultABCIQuery, iavl.KeyProof, error) { resp, err := node.ABCIQueryWithOptions(path, key, opts) @@ -60,7 +60,7 @@ func GetWithProofOptions(path string, key []byte, opts rpcclient.ABCIQueryOption } // AppHash for height H is in header H+1 - commit, err := GetCertifiedCommit(int(resp.Height+1), node, cert) + commit, err := GetCertifiedCommit(resp.Height+1, node, cert) if err != nil { return nil, nil, err } @@ -96,22 +96,25 @@ func GetWithProofOptions(path string, key []byte, opts rpcclient.ABCIQueryOption // GetCertifiedCommit gets the signed header for a given height // and certifies it. Returns error if unable to get a proven header. -func GetCertifiedCommit(h int, node rpcclient.Client, - cert certifiers.Certifier) (empty certifiers.Commit, err error) { +func GetCertifiedCommit(h uint64, node rpcclient.Client, + cert lite.Certifier) (empty lite.Commit, err error) { + + // TODO: please standardize all int types + ih := int(h) // FIXME: cannot use cert.GetByHeight for now, as it also requires // Validators and will fail on querying tendermint for non-current height. // When this is supported, we should use it instead... - rpcclient.WaitForHeight(node, h, nil) - cresp, err := node.Commit(&h) + rpcclient.WaitForHeight(node, ih, nil) + cresp, err := node.Commit(&ih) if err != nil { return } commit := client.CommitFromResult(cresp) // validate downloaded checkpoint with our request and trust store. - if commit.Height() != h { - return empty, certerr.ErrHeightMismatch(h, commit.Height()) + if commit.Height() != ih { + return empty, certerr.ErrHeightMismatch(ih, commit.Height()) } err = cert.Certify(commit) return commit, nil diff --git a/client/query_test.go b/client/query_test.go index 3d4a5a387517..15dbf5fefcd1 100644 --- a/client/query_test.go +++ b/client/query_test.go @@ -9,8 +9,8 @@ import ( "github.com/stretchr/testify/require" "github.com/tendermint/go-wire" - "github.com/tendermint/tendermint/certifiers" - certclient "github.com/tendermint/tendermint/certifiers/client" + "github.com/tendermint/tendermint/lite" + certclient "github.com/tendermint/tendermint/lite/client" "github.com/tendermint/tmlibs/log" nm "github.com/tendermint/tendermint/node" @@ -62,7 +62,7 @@ func TestAppProofs(t *testing.T) { source := certclient.NewProvider(cl) seed, err := source.GetByHeight(br.Height - 2) require.NoError(err, "%+v", err) - cert := certifiers.NewStatic("my-chain", seed.Validators) + cert := lite.NewStatic("my-chain", seed.Validators) client.WaitForHeight(cl, 3, nil) latest, err := source.LatestCommit() @@ -125,7 +125,7 @@ func TestTxProofs(t *testing.T) { source := certclient.NewProvider(cl) seed, err := source.GetByHeight(br.Height - 2) require.NoError(err, "%+v", err) - cert := certifiers.NewStatic("my-chain", seed.Validators) + cert := lite.NewStatic("my-chain", seed.Validators) // First let's make sure a bogus transaction hash returns a valid non-existence proof. key := types.Tx([]byte("bogus")).Hash() diff --git a/client/wrapper.go b/client/wrapper.go index b01235902a9c..ffe6dd4259e7 100644 --- a/client/wrapper.go +++ b/client/wrapper.go @@ -3,8 +3,8 @@ package client import ( "github.com/tendermint/go-wire/data" - "github.com/tendermint/tendermint/certifiers" - certclient "github.com/tendermint/tendermint/certifiers/client" + "github.com/tendermint/tendermint/lite" + certclient "github.com/tendermint/tendermint/lite/client" rpcclient "github.com/tendermint/tendermint/rpc/client" ctypes "github.com/tendermint/tendermint/rpc/core/types" "github.com/tendermint/tendermint/types" @@ -16,14 +16,14 @@ var _ rpcclient.Client = Wrapper{} // provable before passing it along. Allows you to make any rpcclient fully secure. type Wrapper struct { rpcclient.Client - cert *certifiers.Inquiring + cert *lite.Inquiring } // SecureClient uses a given certifier to wrap an connection to an untrusted // host and return a cryptographically secure rpc client. // // If it is wrapping an HTTP rpcclient, it will also wrap the websocket interface -func SecureClient(c rpcclient.Client, cert *certifiers.Inquiring) Wrapper { +func SecureClient(c rpcclient.Client, cert *lite.Inquiring) Wrapper { wrap := Wrapper{c, cert} // TODO: no longer possible as no more such interface exposed.... // if we wrap http client, then we can swap out the event switch to filter @@ -51,7 +51,8 @@ func (w Wrapper) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) { if !prove || err != nil { return res, err } - check, err := GetCertifiedCommit(res.Height, w.Client, w.cert) + h := uint64(res.Height) + check, err := GetCertifiedCommit(h, w.Client, w.cert) if err != nil { return res, err } @@ -111,7 +112,7 @@ func (w Wrapper) Block(height *int) (*ctypes.ResultBlock, error) { return r, nil } -// Commit downloads the Commit and certifies it with the certifiers. +// Commit downloads the Commit and certifies it with the lite. // // This is the foundation for all other verification in this module func (w Wrapper) Commit(height *int) (*ctypes.ResultCommit, error) { diff --git a/errors/main.go b/errors/main.go index a75a523c03ab..073aa944f084 100644 --- a/errors/main.go +++ b/errors/main.go @@ -63,11 +63,23 @@ func (t tmerror) Format(s fmt.State, verb rune) { fmt.Fprintf(s, "(%d) %s\n", t.code, t.msg) } -// Result converts any error into a abci.Result, preserving as much info -// as possible if it was already a TMError -func Result(err error) abci.Result { +// DeliverResult converts any error into a abci.ResponseDeliverTx, +// preserving as much info as possible if it was already +// a TMError +func DeliverResult(err error) abci.ResponseDeliverTx { tm := Wrap(err) - return abci.Result{ + return abci.ResponseDeliverTx{ + Code: tm.ErrorCode(), + Log: tm.Message(), + } +} + +// CheckResult converts any error into a abci.ResponseCheckTx, +// preserving as much info as possible if it was already +// a TMError +func CheckResult(err error) abci.ResponseCheckTx { + tm := Wrap(err) + return abci.ResponseCheckTx{ Code: tm.ErrorCode(), Log: tm.Message(), } diff --git a/glide.lock b/glide.lock index 923e95eaad70..c4c515468506 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 809845bf4c18a4abc85cf5d7b5ee7a17e0f437cd377b22e158787c718272261a -updated: 2017-11-22T12:10:57.995842504+01:00 +hash: b458f1ec5c9386c5c7439fa5ee7a3fe1a812813aef7681ccc18c511fa25073a2 +updated: 2017-11-30T16:15:15.656201018+01:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -11,14 +11,14 @@ imports: version: a368813c5e648fee92e5f6c30e3944ff9d5e8895 - name: github.com/ebuchman/fail-test version: 95f809107225be108efcf10a3509e4ea6ceef3c4 -- name: github.com/ethanfrey/hid - version: dce75af84cf849c60f39bf1b8192fb5cd597b5d9 - name: github.com/ethanfrey/ledger - version: f7f2f056357db77db845a79aa1abdadc3ae66369 + version: 5e432577be582bd18a3b4a9cd75dae7a317ade36 +- name: github.com/flynn/hid + version: ed06a31c6245d4552e8dbba7e32e5b010b875d65 - name: github.com/fsnotify/fsnotify version: 4da3e2cfbabc9f751898f250b49f2439785783a1 - name: github.com/go-kit/kit - version: e2b298466b32c7cd5579a9b9b07e968fc9d9452c + version: d67bb4c202e3b91377d1079b110a6c9ce23ab2f8 subpackages: - log - log/level @@ -26,13 +26,13 @@ imports: - name: github.com/go-logfmt/logfmt version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 - name: github.com/go-playground/locales - version: e4cbcb5d0652150d40ad0646651076b6bd2be4f6 + version: 1e5f1161c6416a5ff48840eb8724a394e48cc534 subpackages: - currency - name: github.com/go-playground/universal-translator version: 71201497bace774495daed26a3874fd339e0b538 - name: github.com/go-stack/stack - version: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf + version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9 subpackages: @@ -89,7 +89,7 @@ imports: - name: github.com/spf13/cast version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 - name: github.com/spf13/cobra - version: 19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f + version: 7b2c5ac9fc04fc5efafb60700713d4fa609b777b - name: github.com/spf13/jwalterweatherman version: 12bd96e66386c1960ab0f74ced1362f66f552f7b - name: github.com/spf13/pflag @@ -97,7 +97,7 @@ imports: - name: github.com/spf13/viper version: 25b30aa063fc18e48662b86996252eabdcf2f0c7 - name: github.com/syndtr/goleveldb - version: b89cc31ef7977104127d34c1bd31ebd1a9db2199 + version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 subpackages: - leveldb - leveldb/cache @@ -112,14 +112,14 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: bee7c5c7aa09443c4d9aa74217a891f8229d9ea3 + version: b89fd815a5e63bd424093aa0ef84d2e146d30c58 subpackages: - client - example/dummy - server - types - name: github.com/tendermint/ed25519 - version: d8387025d2b9d158cf4efb07e7ebf814bcce2057 + version: 1f52c6f8b8a5c7908aff4497c186af344b428925 subpackages: - edwards25519 - extra25519 @@ -137,20 +137,24 @@ imports: subpackages: - data - data/base58 + - nowriter/tmencoding - name: github.com/tendermint/iavl version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653 - name: github.com/tendermint/tendermint - version: e997db7a23d3e51b2b265f892226e980ae4c8300 + version: cb9743e5671776d683cdb9a51de7d12854a2acae subpackages: - blockchain - certifiers - certifiers/client - - certifiers/errors - certifiers/files - cmd/tendermint/commands - config - consensus - consensus/types + - lite + - lite/client + - lite/errors + - lite/files - mempool - node - p2p @@ -173,7 +177,7 @@ imports: - types - version - name: github.com/tendermint/tmlibs - version: 135a1a7cd78215105a55308c167b3331c225e00b + version: 21fb7819891997c96838308b4eba5a50b07ff03f subpackages: - autofile - cli @@ -189,7 +193,7 @@ imports: - pubsub - pubsub/query - name: golang.org/x/crypto - version: edd5e9b0879d13ee6970a50153d85b8fec9f7686 + version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e subpackages: - curve25519 - nacl/box @@ -244,7 +248,7 @@ imports: - tap - transport - name: gopkg.in/go-playground/validator.v9 - version: 1304298bf10d085adec514b076772a79c9cadb6b + version: 6d8c18553ea1ac493d049edd6f102f52e618f085 - name: gopkg.in/yaml.v2 version: eb3733d160e74a9c7e442f435eb3bea458e1d19f testImports: diff --git a/glide.yaml b/glide.yaml index 97630213545a..a23b69f2b183 100644 --- a/glide.yaml +++ b/glide.yaml @@ -22,7 +22,7 @@ import: - package: github.com/tendermint/iavl version: develop - package: github.com/tendermint/tendermint - version: develop + version: feature/indexing subpackages: - certifiers - certifiers/client diff --git a/handler.go b/handler.go index f7d6638029d7..aaea53b6e1cd 100644 --- a/handler.go +++ b/handler.go @@ -99,19 +99,6 @@ func (c InitValidateFunc) InitValidate(l log.Logger, store state.SimpleDB, vals //---------- results and some wrappers -------- -// Result is a common interface of CheckResult and GetResult -type Result interface { - GetData() data.Bytes - GetLog() string -} - -func ToABCI(r Result) abci.Result { - return abci.Result{ - Data: r.GetData(), - Log: r.GetLog(), - } -} - // CheckResult captures any non-error abci result // to make sure people use error for error cases type CheckResult struct { @@ -132,14 +119,13 @@ func NewCheck(gasAllocated uint64, log string) CheckResult { } } -var _ Result = CheckResult{} - -func (r CheckResult) GetData() data.Bytes { - return r.Data -} - -func (r CheckResult) GetLog() string { - return r.Log +func (c CheckResult) ToABCI() abci.ResponseCheckTx { + return abci.ResponseCheckTx{ + Data: c.Data, + Log: c.Log, + Gas: c.GasAllocated, + Fee: c.GasPayment, + } } // DeliverResult captures any non-error abci result @@ -148,17 +134,16 @@ type DeliverResult struct { Data data.Bytes Log string Diff []*abci.Validator - GasUsed uint64 -} - -var _ Result = DeliverResult{} - -func (r DeliverResult) GetData() data.Bytes { - return r.Data + Tags []*abci.KVPair + GasUsed uint64 // unused } -func (r DeliverResult) GetLog() string { - return r.Log +func (d DeliverResult) ToABCI() abci.ResponseDeliverTx { + return abci.ResponseDeliverTx{ + Data: d.Data, + Log: d.Log, + Tags: d.Tags, + } } // placeholders diff --git a/modules/ibc/commands/tx.go b/modules/ibc/commands/tx.go index f5ed752973ac..61fb6ad0eccf 100644 --- a/modules/ibc/commands/tx.go +++ b/modules/ibc/commands/tx.go @@ -11,7 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/commands" txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs" "github.com/cosmos/cosmos-sdk/modules/ibc" - "github.com/tendermint/tendermint/certifiers" + "github.com/tendermint/tendermint/lite" ) // RegisterChainTxCmd is CLI command to register a new chain for ibc @@ -80,7 +80,7 @@ func postPacketTxCmd(cmd *cobra.Command, args []string) error { return txcmd.DoTx(post.Wrap()) } -func readCommit() (fc certifiers.FullCommit, err error) { +func readCommit() (fc lite.FullCommit, err error) { name := viper.GetString(FlagCommit) if name == "" { return fc, errors.New("You must specify a commit file") diff --git a/modules/ibc/ibc_test.go b/modules/ibc/ibc_test.go index e491f94a2a95..70a560f98f45 100644 --- a/modules/ibc/ibc_test.go +++ b/modules/ibc/ibc_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" wire "github.com/tendermint/go-wire" - "github.com/tendermint/tendermint/certifiers" + "github.com/tendermint/tendermint/lite" "github.com/tendermint/tmlibs/log" sdk "github.com/cosmos/cosmos-sdk" @@ -22,8 +22,8 @@ func TestIBCRegister(t *testing.T) { assert := assert.New(t) // the validators we use to make seeds - keys := certifiers.GenValKeys(5) - keys2 := certifiers.GenValKeys(7) + keys := lite.GenValKeys(5) + keys2 := lite.GenValKeys(7) appHash := []byte{0, 4, 7, 23} appHash2 := []byte{12, 34, 56, 78} @@ -32,7 +32,7 @@ func TestIBCRegister(t *testing.T) { badCommit.Header.AppHash = appHash2 cases := []struct { - fc certifiers.FullCommit + fc lite.FullCommit checker errors.CheckErr }{ { @@ -70,7 +70,7 @@ func TestIBCRegisterPermissions(t *testing.T) { require := require.New(t) // the validators we use to make seeds - keys := certifiers.GenValKeys(4) + keys := lite.GenValKeys(4) appHash := []byte{0x17, 0x21, 0x5, 0x1e} foobar := sdk.Actor{App: "foo", Address: []byte("bar")} @@ -78,7 +78,7 @@ func TestIBCRegisterPermissions(t *testing.T) { foobaz := sdk.Actor{App: "foo", Address: []byte("baz")} cases := []struct { - seed certifiers.FullCommit + seed lite.FullCommit registrar sdk.Actor signer sdk.Actor checker errors.CheckErr @@ -148,7 +148,7 @@ func TestIBCUpdate(t *testing.T) { require := require.New(t) // this is the root seed, that others are evaluated against - keys := certifiers.GenValKeys(7) + keys := lite.GenValKeys(7) appHash := []byte{0, 4, 7, 23} start := 100 // initial height root := genEmptyCommit(keys, "chain-1", 100, appHash, len(keys)) @@ -165,7 +165,7 @@ func TestIBCUpdate(t *testing.T) { require.Nil(err, "%+v", err) cases := []struct { - fc certifiers.FullCommit + fc lite.FullCommit checker errors.CheckErr }{ // same validator, higher up @@ -223,7 +223,7 @@ func TestIBCCreatePacket(t *testing.T) { require := require.New(t) // this is the root seed, that others are evaluated against - keys := certifiers.GenValKeys(7) + keys := lite.GenValKeys(7) appHash := []byte{1, 2, 3, 4} start := 100 // initial height chainID := "cosmos-hub" diff --git a/modules/ibc/noop.go b/modules/ibc/noop.go new file mode 100644 index 000000000000..3e111caf9bf1 --- /dev/null +++ b/modules/ibc/noop.go @@ -0,0 +1,26 @@ +package ibc + +import ( + "github.com/tendermint/tendermint/lite" + liteErr "github.com/tendermint/tendermint/lite/errors" +) + +// this really shouldn't be here... removed from upstream lib +// without checking +type missingProvider struct{} + +// NewMissingProvider returns a provider which does not store anything and always misses. +func NewMissingProvider() lite.Provider { + return missingProvider{} +} + +func (missingProvider) StoreCommit(lite.FullCommit) error { return nil } +func (missingProvider) GetByHeight(int) (lite.FullCommit, error) { + return lite.FullCommit{}, liteErr.ErrCommitNotFound() +} +func (missingProvider) GetByHash([]byte) (lite.FullCommit, error) { + return lite.FullCommit{}, liteErr.ErrCommitNotFound() +} +func (missingProvider) LatestCommit() (lite.FullCommit, error) { + return lite.FullCommit{}, liteErr.ErrCommitNotFound() +} diff --git a/modules/ibc/provider.go b/modules/ibc/provider.go index a01b7504fd28..2e9d9584c3d4 100644 --- a/modules/ibc/provider.go +++ b/modules/ibc/provider.go @@ -2,8 +2,8 @@ package ibc import ( wire "github.com/tendermint/go-wire" - "github.com/tendermint/tendermint/certifiers" - certerr "github.com/tendermint/tendermint/certifiers/errors" + "github.com/tendermint/tendermint/lite" + certerr "github.com/tendermint/tendermint/lite/errors" "github.com/cosmos/cosmos-sdk/stack" "github.com/cosmos/cosmos-sdk/state" @@ -18,11 +18,11 @@ const ( // newCertifier loads up the current state of this chain to make a proper certifier // it will load the most recent height before block h if h is positive // if h < 0, it will load the latest height -func newCertifier(store state.SimpleDB, chainID string, h int) (*certifiers.Inquiring, error) { +func newCertifier(store state.SimpleDB, chainID string, h int) (*lite.Inquiring, error) { // each chain has their own prefixed subspace p := newDBProvider(store) - var fc certifiers.FullCommit + var fc lite.FullCommit var err error if h > 0 { // this gets the most recent verified commit below the specified height @@ -36,8 +36,8 @@ func newCertifier(store state.SimpleDB, chainID string, h int) (*certifiers.Inqu } // we have no source for untrusted keys, but use the db to load trusted history - cert := certifiers.NewInquiring(chainID, fc, p, - certifiers.NewMissingProvider()) + cert := lite.NewInquiring(chainID, fc, p, + NewMissingProvider()) return cert, nil } @@ -54,9 +54,9 @@ func newDBProvider(store state.SimpleDB) *dbProvider { } } -var _ certifiers.Provider = &dbProvider{} +var _ lite.Provider = &dbProvider{} -func (d *dbProvider) StoreCommit(fc certifiers.FullCommit) error { +func (d *dbProvider) StoreCommit(fc lite.FullCommit) error { // TODO: don't duplicate data.... b := wire.BinaryBytes(fc) d.byHash.Set(fc.ValidatorsHash(), b) @@ -64,7 +64,7 @@ func (d *dbProvider) StoreCommit(fc certifiers.FullCommit) error { return nil } -func (d *dbProvider) LatestCommit() (fc certifiers.FullCommit, err error) { +func (d *dbProvider) LatestCommit() (fc lite.FullCommit, err error) { b, _ := d.byHeight.Top() if b == nil { return fc, certerr.ErrCommitNotFound() @@ -73,7 +73,7 @@ func (d *dbProvider) LatestCommit() (fc certifiers.FullCommit, err error) { return } -func (d *dbProvider) GetByHeight(h int) (fc certifiers.FullCommit, err error) { +func (d *dbProvider) GetByHeight(h int) (fc lite.FullCommit, err error) { b, _ := d.byHeight.LTE(uint64(h)) if b == nil { return fc, certerr.ErrCommitNotFound() @@ -82,7 +82,7 @@ func (d *dbProvider) GetByHeight(h int) (fc certifiers.FullCommit, err error) { return } -func (d *dbProvider) GetByHash(hash []byte) (fc certifiers.FullCommit, err error) { +func (d *dbProvider) GetByHash(hash []byte) (fc lite.FullCommit, err error) { b := d.byHash.Get(hash) if b == nil { return fc, certerr.ErrCommitNotFound() @@ -93,7 +93,7 @@ func (d *dbProvider) GetByHash(hash []byte) (fc certifiers.FullCommit, err error // GetExactHeight is like GetByHeight, but returns an error instead of // closest match if there is no exact match -func (d *dbProvider) GetExactHeight(h int) (fc certifiers.FullCommit, err error) { +func (d *dbProvider) GetExactHeight(h int) (fc lite.FullCommit, err error) { fc, err = d.GetByHeight(h) if err != nil { return diff --git a/modules/ibc/provider_test.go b/modules/ibc/provider_test.go index abdb93faacd7..120253312a42 100644 --- a/modules/ibc/provider_test.go +++ b/modules/ibc/provider_test.go @@ -7,11 +7,11 @@ import ( "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/state" - "github.com/tendermint/tendermint/certifiers" - certerr "github.com/tendermint/tendermint/certifiers/errors" + "github.com/tendermint/tendermint/lite" + certerr "github.com/tendermint/tendermint/lite/errors" ) -func assertCommitsEqual(t *testing.T, fc, fc2 certifiers.FullCommit) { +func assertCommitsEqual(t *testing.T, fc, fc2 lite.FullCommit) { assert := assert.New(t) assert.Equal(fc.Height(), fc2.Height()) assert.Equal(fc.ValidatorsHash(), fc2.ValidatorsHash()) @@ -22,7 +22,7 @@ func TestProviderStore(t *testing.T) { assert, require := assert.New(t), require.New(t) // make a few commits - keys := certifiers.GenValKeys(2) + keys := lite.GenValKeys(2) commits := makeCommits(keys, 4, "some-chain", "demo-store") // make a provider @@ -76,9 +76,9 @@ func TestDBProvider(t *testing.T) { checkProvider(t, p, "test-db", "bling") } -func makeCommits(keys certifiers.ValKeys, count int, chainID, app string) []certifiers.FullCommit { +func makeCommits(keys lite.ValKeys, count int, chainID, app string) []lite.FullCommit { appHash := []byte(app) - commits := make([]certifiers.FullCommit, count) + commits := make([]lite.FullCommit, count) for i := 0; i < count; i++ { // two commits for each validator, to check how we handle dups // (10, 0), (10, 1), (10, 1), (10, 2), (10, 2), ... @@ -89,9 +89,9 @@ func makeCommits(keys certifiers.ValKeys, count int, chainID, app string) []cert return commits } -func checkProvider(t *testing.T, p certifiers.Provider, chainID, app string) { +func checkProvider(t *testing.T, p lite.Provider, chainID, app string) { assert, require := assert.New(t), require.New(t) - keys := certifiers.GenValKeys(5) + keys := lite.GenValKeys(5) count := 10 // make a bunch of commits... diff --git a/modules/ibc/test_helpers.go b/modules/ibc/test_helpers.go index 456e3076f0ee..6e2baba5c8cc 100644 --- a/modules/ibc/test_helpers.go +++ b/modules/ibc/test_helpers.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/tendermint/iavl" - "github.com/tendermint/tendermint/certifiers" + "github.com/tendermint/tendermint/lite" "github.com/tendermint/tmlibs/log" sdk "github.com/cosmos/cosmos-sdk" @@ -16,7 +16,7 @@ import ( // It is able to produce ibc packets and all verification for // them, but cannot respond to any responses. type MockChain struct { - keys certifiers.ValKeys + keys lite.ValKeys chainID string tree *iavl.Tree } @@ -24,7 +24,7 @@ type MockChain struct { // NewMockChain initializes a teststore and test validators func NewMockChain(chainID string, numKeys int) MockChain { return MockChain{ - keys: certifiers.GenValKeys(numKeys), + keys: lite.GenValKeys(numKeys), chainID: chainID, tree: iavl.NewTree(0, nil), } @@ -48,8 +48,8 @@ func (m MockChain) MakePostPacket(packet Packet, h int) ( return post, update } -func genEmptyCommit(keys certifiers.ValKeys, chain string, h int, - appHash []byte, count int) certifiers.FullCommit { +func genEmptyCommit(keys lite.ValKeys, chain string, h int, + appHash []byte, count int) lite.FullCommit { vals := keys.ToValidators(10, 0) return keys.GenFullCommit(chain, h, nil, vals, appHash, 0, count) diff --git a/modules/ibc/tx.go b/modules/ibc/tx.go index 2686080ce80b..10b69686192b 100644 --- a/modules/ibc/tx.go +++ b/modules/ibc/tx.go @@ -3,7 +3,7 @@ package ibc import ( "github.com/tendermint/go-wire/data" "github.com/tendermint/iavl" - "github.com/tendermint/tendermint/certifiers" + "github.com/tendermint/tendermint/lite" sdk "github.com/cosmos/cosmos-sdk" ) @@ -32,7 +32,7 @@ func init() { // RegisterChainTx allows you to register a new chain on this blockchain type RegisterChainTx struct { - Commit certifiers.FullCommit `json:"seed"` + Commit lite.FullCommit `json:"seed"` } // ChainID helps get the chain this tx refers to @@ -56,7 +56,7 @@ func (r RegisterChainTx) Wrap() sdk.Tx { // UpdateChainTx updates the state of this chain type UpdateChainTx struct { - Commit certifiers.FullCommit `json:"seed"` + Commit lite.FullCommit `json:"seed"` } // ChainID helps get the chain this tx refers to diff --git a/server/commands/start.go b/server/commands/start.go index 5580ce303678..36e2cb712b68 100644 --- a/server/commands/start.go +++ b/server/commands/start.go @@ -175,7 +175,7 @@ func startTendermint(dir string, basecoinApp abci.Application) error { return err } - _, err = n.Start() + err = n.Start() if err != nil { return err } From 1e377c8719c2ef3e5d9dc249c805b1e6dfd88d79 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 30 Nov 2017 17:06:47 +0100 Subject: [PATCH 068/117] Fix unit tests --- app/app_test.go | 57 ++++++++++++------- app/val_test.go | 4 +- client/query_test.go | 11 ++-- errors/main_test.go | 13 +++-- .../counter/plugins/counter/counter_test.go | 6 +- handler.go | 12 ++++ 6 files changed, 67 insertions(+), 36 deletions(-) diff --git a/app/app_test.go b/app/app_test.go index 39f205f0f7e6..1401f4ba8a9a 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -124,7 +124,7 @@ func (at *appTest) reset() { at.initAccount(at.acctOut) resabci := at.app.Commit() - require.True(at.t, resabci.IsOK(), resabci) + require.True(at.t, resabci.Code.IsOK(), resabci) } func getBalance(key sdk.Actor, store state.SimpleDB) (coin.Coins, error) { @@ -139,7 +139,7 @@ func getAddr(addr []byte, state state.SimpleDB) (coin.Coins, error) { } // returns the final balance and expected balance for input and output accounts -func (at *appTest) exec(t *testing.T, tx sdk.Tx, checkTx bool) (res abci.Result, diffIn, diffOut coin.Coins) { +func (at *appTest) execDeliver(t *testing.T, tx sdk.Tx) (res abci.ResponseDeliverTx, diffIn, diffOut coin.Coins) { require := require.New(t) initBalIn, err := getBalance(at.acctIn.Actor(), at.app.Append()) @@ -148,11 +148,26 @@ func (at *appTest) exec(t *testing.T, tx sdk.Tx, checkTx bool) (res abci.Result, require.Nil(err, "%+v", err) txBytes := wire.BinaryBytes(tx) - if checkTx { - res = at.app.CheckTx(txBytes) - } else { - res = at.app.DeliverTx(txBytes) - } + res = at.app.DeliverTx(txBytes) + + endBalIn, err := getBalance(at.acctIn.Actor(), at.app.Append()) + require.Nil(err, "%+v", err) + endBalOut, err := getBalance(at.acctOut.Actor(), at.app.Append()) + require.Nil(err, "%+v", err) + return res, endBalIn.Minus(initBalIn), endBalOut.Minus(initBalOut) +} + +// returns the final balance and expected balance for input and output accounts +func (at *appTest) execCheck(t *testing.T, tx sdk.Tx) (res abci.ResponseCheckTx, diffIn, diffOut coin.Coins) { + require := require.New(t) + + initBalIn, err := getBalance(at.acctIn.Actor(), at.app.Append()) + require.Nil(err, "%+v", err) + initBalOut, err := getBalance(at.acctOut.Actor(), at.app.Append()) + require.Nil(err, "%+v", err) + + txBytes := wire.BinaryBytes(tx) + res = at.app.CheckTx(txBytes) endBalIn, err := getBalance(at.acctIn.Actor(), at.app.Append()) require.Nil(err, "%+v", err) @@ -237,23 +252,23 @@ func TestTx(t *testing.T) { at.initAccount(at.acctIn) at.app.Commit() - res, _, _ := at.exec(t, at.getTx(coin.Coins{{"mycoin", 5}}, 1), true) - assert.True(res.IsErr(), "ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res) - res, diffIn, diffOut := at.exec(t, at.getTx(coin.Coins{{"mycoin", 5}}, 1), false) - assert.True(res.IsErr(), "ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res) + cres, _, _ := at.execCheck(t, at.getTx(coin.Coins{{"mycoin", 5}}, 1)) + assert.True(cres.IsErr(), "ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", cres) + dres, diffIn, diffOut := at.execDeliver(t, at.getTx(coin.Coins{{"mycoin", 5}}, 1)) + assert.True(dres.IsErr(), "ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", dres) assert.True(diffIn.IsZero()) assert.True(diffOut.IsZero()) //Regular CheckTx at.reset() - res, _, _ = at.exec(t, at.getTx(coin.Coins{{"mycoin", 5}}, 1), true) - assert.True(res.IsOK(), "ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", res) + cres, _, _ = at.execCheck(t, at.getTx(coin.Coins{{"mycoin", 5}}, 1)) + assert.True(cres.Code.IsOK(), "ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", cres) //Regular DeliverTx at.reset() amt := coin.Coins{{"mycoin", 3}} - res, diffIn, diffOut = at.exec(t, at.getTx(amt, 1), false) - assert.True(res.IsOK(), "ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res) + dres, diffIn, diffOut = at.execDeliver(t, at.getTx(amt, 1)) + assert.True(dres.Code.IsOK(), "ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", dres) assert.Equal(amt.Negative(), diffIn) assert.Equal(amt, diffOut) @@ -261,8 +276,8 @@ func TestTx(t *testing.T) { at.reset() amt = coin.Coins{{"mycoin", 4}} toll := coin.Coin{"mycoin", 1} - res, diffIn, diffOut = at.exec(t, at.feeTx(amt, toll, 1), false) - assert.True(res.IsOK(), "ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res) + dres, diffIn, diffOut = at.execDeliver(t, at.feeTx(amt, toll, 1)) + assert.True(dres.Code.IsOK(), "ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", dres) payment := amt.Plus(coin.Coins{toll}).Negative() assert.Equal(payment, diffIn) assert.Equal(amt, diffOut) @@ -273,16 +288,16 @@ func TestQuery(t *testing.T) { assert := assert.New(t) at := newAppTest(t) - res, _, _ := at.exec(t, at.getTx(coin.Coins{{"mycoin", 5}}, 1), false) - assert.True(res.IsOK(), "Commit, DeliverTx: Expected OK return from DeliverTx, Error: %v", res) + dres, _, _ := at.execDeliver(t, at.getTx(coin.Coins{{"mycoin", 5}}, 1)) + assert.True(dres.Code.IsOK(), "Commit, DeliverTx: Expected OK return from DeliverTx, Error: %v", dres) resQueryPreCommit := at.app.Query(abci.RequestQuery{ Path: "/account", Data: at.acctIn.Address(), }) - res = at.app.Commit() - assert.True(res.IsOK(), res) + cres := at.app.Commit() + assert.True(cres.Code.IsOK(), cres) key := stack.PrefixedKey(coin.NameCoin, at.acctIn.Address()) resQueryPostCommit := at.app.Query(abci.RequestQuery{ diff --git a/app/val_test.go b/app/val_test.go index c333273f2559..d79d4ee78b85 100644 --- a/app/val_test.go +++ b/app/val_test.go @@ -79,9 +79,9 @@ func TestEndBlock(t *testing.T) { tx := base.ValChangeTx{c}.Wrap() txBytes := wire.BinaryBytes(tx) res := app.DeliverTx(txBytes) - require.True(res.IsOK(), "%#v", res) + require.True(res.Code.IsOK(), "%#v", res) } - diff := app.EndBlock(app.height) + diff := app.EndBlock(abci.RequestEndBlock{app.height}) // TODO: don't care about order here... assert.Equal(tc.expected, diff.Diffs, "%d", i) } diff --git a/client/query_test.go b/client/query_test.go index 15dbf5fefcd1..29bde63bea01 100644 --- a/client/query_test.go +++ b/client/query_test.go @@ -1,7 +1,6 @@ package client import ( - "fmt" "os" "testing" @@ -56,11 +55,11 @@ 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 + brh := int(br.Height) // This sets up our trust on the node based on some past point. source := certclient.NewProvider(cl) - seed, err := source.GetByHeight(br.Height - 2) + seed, err := source.GetByHeight(brh - 2) require.NoError(err, "%+v", err) cert := lite.NewStatic("my-chain", seed.Validators) @@ -120,10 +119,10 @@ func TestTxProofs(t *testing.T) { require.NoError(err, "%+v", err) require.EqualValues(0, br.CheckTx.Code, "%#v", br.CheckTx) require.EqualValues(0, br.DeliverTx.Code) - fmt.Printf("tx height: %d\n", br.Height) + brh := int(br.Height) source := certclient.NewProvider(cl) - seed, err := source.GetByHeight(br.Height - 2) + seed, err := source.GetByHeight(brh - 2) require.NoError(err, "%+v", err) cert := lite.NewStatic("my-chain", seed.Validators) @@ -141,7 +140,7 @@ func TestTxProofs(t *testing.T) { err = res.Proof.Validate(key) assert.NoError(err, "%+v", err) - commit, err := GetCertifiedCommit(int(br.Height), cl, cert) + commit, err := GetCertifiedCommit(br.Height, cl, cert) require.Nil(err, "%+v", err) require.Equal(res.Proof.RootHash, commit.Header.DataHash) diff --git a/errors/main_test.go b/errors/main_test.go index e9a80f8bb02a..f8f60845d25b 100644 --- a/errors/main_test.go +++ b/errors/main_test.go @@ -31,9 +31,14 @@ func TestCreateResult(t *testing.T) { for idx, tc := range cases { i := strconv.Itoa(idx) - res := Result(tc.err) - assert.True(res.IsErr(), i) - assert.Equal(tc.msg, res.Log, i) - assert.Equal(tc.code, res.Code, i) + dres := DeliverResult(tc.err) + assert.True(dres.IsErr(), i) + assert.Equal(tc.msg, dres.Log, i) + assert.Equal(tc.code, dres.Code, i) + + cres := CheckResult(tc.err) + assert.True(cres.IsErr(), i) + assert.Equal(tc.msg, cres.Log, i) + assert.Equal(tc.code, cres.Code, i) } } diff --git a/examples/counter/plugins/counter/counter_test.go b/examples/counter/plugins/counter/counter_test.go index 5c1ef254a2d4..f727bb571577 100644 --- a/examples/counter/plugins/counter/counter_test.go +++ b/examples/counter/plugins/counter/counter_test.go @@ -41,7 +41,7 @@ func TestCounterPlugin(t *testing.T) { require.Nil(err, "%+v", err) // Deliver a CounterTx - DeliverCounterTx := func(valid bool, counterFee coin.Coins, sequence uint32) abci.Result { + DeliverCounterTx := func(valid bool, counterFee coin.Coins, sequence uint32) abci.ResponseDeliverTx { tx := NewTx(valid, counterFee) tx = nonce.NewTx(sequence, []sdk.Actor{acct.Actor()}, tx) tx = base.NewChainTx(chainID, 0, tx) @@ -53,7 +53,7 @@ func TestCounterPlugin(t *testing.T) { // Test a basic send, no fee res := DeliverCounterTx(true, nil, 1) - assert.True(res.IsOK(), res.String()) + assert.True(res.Code.IsOK(), res.String()) // Test an invalid send, no fee res = DeliverCounterTx(false, nil, 2) @@ -65,7 +65,7 @@ func TestCounterPlugin(t *testing.T) { // Test an valid send, with supported fee res = DeliverCounterTx(true, coin.Coins{{"gold", 100}}, 3) - assert.True(res.IsOK(), res.String()) + assert.True(res.Code.IsOK(), res.String()) // Test unsupported fee res = DeliverCounterTx(true, coin.Coins{{"silver", 100}}, 4) diff --git a/handler.go b/handler.go index aaea53b6e1cd..638fe4cc6648 100644 --- a/handler.go +++ b/handler.go @@ -99,6 +99,10 @@ func (c InitValidateFunc) InitValidate(l log.Logger, store state.SimpleDB, vals //---------- results and some wrappers -------- +type Result interface { + GetData() data.Bytes +} + // CheckResult captures any non-error abci result // to make sure people use error for error cases type CheckResult struct { @@ -128,6 +132,10 @@ func (c CheckResult) ToABCI() abci.ResponseCheckTx { } } +func (c CheckResult) GetData() data.Bytes { + return c.Data +} + // DeliverResult captures any non-error abci result // to make sure people use error for error cases type DeliverResult struct { @@ -146,6 +154,10 @@ func (d DeliverResult) ToABCI() abci.ResponseDeliverTx { } } +func (d DeliverResult) GetData() data.Bytes { + return d.Data +} + // placeholders // holders type NopCheck struct{} From 8fe07ea331b2bb025f3ed5ed5e1e9488bfdb304c Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 30 Nov 2017 17:14:54 +0100 Subject: [PATCH 069/117] Fix cli tests --- tests/cli/common.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cli/common.sh b/tests/cli/common.sh index 76d5e9030766..33e8aa647875 100644 --- a/tests/cli/common.sh +++ b/tests/cli/common.sh @@ -173,8 +173,8 @@ checkRole() { txSucceeded() { if (assertTrue "line=${LINENO}, sent tx ($3): $2" $1); then TX=$2 - assertEquals "line=${LINENO}, good check ($3): $TX" "0" $(echo $TX | jq .check_tx.code) - assertEquals "line=${LINENO}, good deliver ($3): $TX" "0" $(echo $TX | jq .deliver_tx.code) + assertEquals "line=${LINENO}, good check ($3): $TX" null $(echo $TX | jq .check_tx.code) + assertEquals "line=${LINENO}, good deliver ($3): $TX" null $(echo $TX | jq .deliver_tx.code) else return 1 fi From 111b80105fb03b2f4253387657d53cb360e27e7b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 30 Nov 2017 17:54:27 +0100 Subject: [PATCH 070/117] Add and test tags to SendTx --- app/app_test.go | 26 +++++++++++++------- modules/coin/handler.go | 53 ++++++++++++++++++++++++++++++++++------- stack/middleware.go | 4 ++-- 3 files changed, 64 insertions(+), 19 deletions(-) diff --git a/app/app_test.go b/app/app_test.go index 1401f4ba8a9a..ac5b1b890990 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -12,7 +12,6 @@ import ( "github.com/cosmos/cosmos-sdk/modules/base" "github.com/cosmos/cosmos-sdk/modules/coin" "github.com/cosmos/cosmos-sdk/modules/fee" - "github.com/cosmos/cosmos-sdk/modules/ibc" "github.com/cosmos/cosmos-sdk/modules/nonce" "github.com/cosmos/cosmos-sdk/modules/roles" "github.com/cosmos/cosmos-sdk/stack" @@ -26,7 +25,6 @@ import ( func DefaultHandler(feeDenom string) sdk.Handler { // use the default stack r := roles.NewHandler() - i := ibc.NewHandler() return stack.New( base.Logger{}, @@ -35,17 +33,13 @@ func DefaultHandler(feeDenom string) sdk.Handler { base.Chain{}, stack.Checkpoint{OnCheck: true}, nonce.ReplayCheck{}, + roles.NewMiddleware(), + fee.NewSimpleFeeMiddleware(coin.Coin{feeDenom, 0}, fee.Bank), + stack.Checkpoint{OnDeliver: true}, ). - IBC(ibc.NewMiddleware()). - Apps( - roles.NewMiddleware(), - fee.NewSimpleFeeMiddleware(coin.Coin{feeDenom, 0}, fee.Bank), - stack.Checkpoint{OnDeliver: true}, - ). Dispatch( coin.NewHandler(), stack.WrapHandler(r), - stack.WrapHandler(i), ) } @@ -150,6 +144,20 @@ func (at *appTest) execDeliver(t *testing.T, tx sdk.Tx) (res abci.ResponseDelive txBytes := wire.BinaryBytes(tx) res = at.app.DeliverTx(txBytes) + // check the tags + if res.Code.IsOK() { + tags := res.Tags + require.NotEmpty(tags) + require.Equal("height", tags[0].Key) + require.True(tags[0].ValueInt > 0) + require.Equal("coin.sender", tags[1].Key) + sender := at.acctIn.Actor().Address.String() + require.Equal(sender, tags[1].ValueString) + require.Equal("coin.receiver", tags[2].Key) + rcpt := at.acctOut.Actor().Address.String() + require.Equal(rcpt, tags[2].ValueString) + } + endBalIn, err := getBalance(at.acctIn.Actor(), at.app.Append()) require.Nil(err, "%+v", err) endBalOut, err := getBalance(at.acctOut.Actor(), at.app.Append()) diff --git a/modules/coin/handler.go b/modules/coin/handler.go index da98d97dc141..fb07fd07ab20 100644 --- a/modules/coin/handler.go +++ b/modules/coin/handler.go @@ -1,6 +1,9 @@ package coin import ( + "strings" + + abci "github.com/tendermint/abci/types" "github.com/tendermint/go-wire/data" "github.com/tendermint/tmlibs/log" @@ -73,7 +76,7 @@ func (h Handler) DeliverTx(ctx sdk.Context, store state.SimpleDB, switch t := tx.Unwrap().(type) { case SendTx: - return res, h.sendTx(ctx, store, t, cb) + return h.sendTx(ctx, store, t, cb) case CreditTx: return res, h.creditTx(ctx, store, t) } @@ -96,11 +99,11 @@ func (h Handler) InitState(l log.Logger, store state.SimpleDB, } func (h Handler) sendTx(ctx sdk.Context, store state.SimpleDB, - send SendTx, cb sdk.Deliver) error { + send SendTx, cb sdk.Deliver) (res sdk.DeliverResult, err error) { - err := checkTx(ctx, send) + err = checkTx(ctx, send) if err != nil { - return err + return res, err } // deduct from all input accounts @@ -108,7 +111,7 @@ func (h Handler) sendTx(ctx sdk.Context, store state.SimpleDB, for _, in := range send.Inputs { _, err = ChangeCoins(store, in.Address, in.Coins.Negative()) if err != nil { - return err + return res, err } senders = append(senders, in.Address) } @@ -123,7 +126,7 @@ func (h Handler) sendTx(ctx sdk.Context, store state.SimpleDB, _, err = ChangeCoins(store, out.Address, out.Coins) if err != nil { - return err + return res, err } // now send ibc packet if needed... if out.Address.ChainID != "" { @@ -144,13 +147,47 @@ func (h Handler) sendTx(ctx sdk.Context, store state.SimpleDB, ibcCtx := ctx.WithPermissions(ibc.AllowIBC(NameCoin)) _, err := cb.DeliverTx(ibcCtx, store, packet.Wrap()) if err != nil { - return err + return res, err } } } + // now we build the tags + tags := make([]*abci.KVPair, 3) + tags[0] = tagInt("height", int64(ctx.BlockHeight())) + + var names []string + for _, in := range send.Inputs { + addr := in.Address.Address.String() + names = append(names, addr) + } + tags[1] = tagStr("coin.sender", strings.Join(names, ",")) + + names = []string{} + for _, out := range send.Outputs { + addr := out.Address.Address.String() + names = append(names, addr) + } + tags[2] = tagStr("coin.receiver", strings.Join(names, ",")) + // a-ok! - return nil + return sdk.DeliverResult{Tags: tags}, nil +} + +func tagInt(key string, val int64) *abci.KVPair { + return &abci.KVPair{ + Key: key, + ValueInt: val, + ValueType: abci.KVPair_INT, + } +} + +func tagStr(key, val string) *abci.KVPair { + return &abci.KVPair{ + Key: key, + ValueString: val, + ValueType: abci.KVPair_STRING, + } } func (h Handler) creditTx(ctx sdk.Context, store state.SimpleDB, diff --git a/stack/middleware.go b/stack/middleware.go index 4c55f7f0af82..0ec80d325466 100644 --- a/stack/middleware.go +++ b/stack/middleware.go @@ -94,8 +94,8 @@ func (b builder) wrap(next sdk.Handler) sdk.Handler { // Stack is the entire application stack type Stack struct { - middles []builder - handler sdk.Handler + middles []builder + handler sdk.Handler sdk.Handler // the compiled version, which we expose } From 7f79c5991b16070e3b67972838630f47662c466b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 30 Nov 2017 18:11:03 +0100 Subject: [PATCH 071/117] CLI test shows search working --- examples/basecoin/tests/cli/basictx.sh | 4 ++++ tests/cli/common.sh | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/examples/basecoin/tests/cli/basictx.sh b/examples/basecoin/tests/cli/basictx.sh index 853aab4b4849..13320e719822 100755 --- a/examples/basecoin/tests/cli/basictx.sh +++ b/examples/basecoin/tests/cli/basictx.sh @@ -47,6 +47,10 @@ test01SendTx() { # Make sure tx is indexed checkSendTx $HASH $TX_HEIGHT $SENDER "992" + + echo "search for tx (demo):" + curl "http://localhost:46657/tx_search?query=\"coin.sender='${SENDER}'\"&prove=true" + echo } test02SendTxWithFee() { diff --git a/tests/cli/common.sh b/tests/cli/common.sh index 33e8aa647875..a1100d469a84 100644 --- a/tests/cli/common.sh +++ b/tests/cli/common.sh @@ -79,6 +79,14 @@ initServer() { sed -ie "s/4665/$3/" $SERVE_DIR/config.toml fi + # add indexing + cat > $SERVE_DIR/config.toml << EOF + +[tx_index] +indexer = "kv" +index_tags = "height,coin.sender,coin.receiver" +EOF + echo "Starting ${SERVER_EXE} server..." startServer $SERVE_DIR $SERVER_LOG return $? From edebf30c879d286dafab8bcbf662ea28e8cd31fa Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 30 Nov 2017 11:25:08 -0600 Subject: [PATCH 072/117] build proper tags --- modules/coin/handler.go | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/modules/coin/handler.go b/modules/coin/handler.go index fb07fd07ab20..9885db2958a5 100644 --- a/modules/coin/handler.go +++ b/modules/coin/handler.go @@ -1,8 +1,6 @@ package coin import ( - "strings" - abci "github.com/tendermint/abci/types" "github.com/tendermint/go-wire/data" "github.com/tendermint/tmlibs/log" @@ -153,22 +151,19 @@ func (h Handler) sendTx(ctx sdk.Context, store state.SimpleDB, } // now we build the tags - tags := make([]*abci.KVPair, 3) - tags[0] = tagInt("height", int64(ctx.BlockHeight())) + tags := make([]*abci.KVPair, 0) + + tags = append(tags, tagInt("height", int64(ctx.BlockHeight()))) - var names []string for _, in := range send.Inputs { addr := in.Address.Address.String() - names = append(names, addr) + tags = append(tags, tagStr("coin.sender", addr)) } - tags[1] = tagStr("coin.sender", strings.Join(names, ",")) - names = []string{} for _, out := range send.Outputs { addr := out.Address.Address.String() - names = append(names, addr) + tags = append(tags, tagStr("coin.receiver", addr)) } - tags[2] = tagStr("coin.receiver", strings.Join(names, ",")) // a-ok! return sdk.DeliverResult{Tags: tags}, nil From 209164b8023a479143d1307722b7c71eb8ddf3ae Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 30 Nov 2017 11:28:38 -0600 Subject: [PATCH 073/117] update Dockerfile.dev --- Dockerfile.dev | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Dockerfile.dev b/Dockerfile.dev index c3b105898775..bfcc28792caf 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -2,13 +2,13 @@ FROM golang:latest RUN apt-get update && apt-get install -y jq -RUN mkdir -p /go/src/github.com/tendermint/basecoin -WORKDIR /go/src/github.com/tendermint/basecoin +RUN mkdir -p /go/src/github.com/cosmos/cosmos-sdk +WORKDIR /go/src/github.com/cosmos/cosmos-sdk -COPY Makefile /go/src/github.com/tendermint/basecoin/ -COPY glide.yaml /go/src/github.com/tendermint/basecoin/ -COPY glide.lock /go/src/github.com/tendermint/basecoin/ +COPY Makefile /go/src/github.com/cosmos/cosmos-sdk/ +COPY glide.yaml /go/src/github.com/cosmos/cosmos-sdk/ +COPY glide.lock /go/src/github.com/cosmos/cosmos-sdk/ RUN make get_vendor_deps -COPY . /go/src/github.com/tendermint/basecoin +COPY . /go/src/github.com/cosmos/cosmos-sdk From 5b8a07fdd641529ee349fe16ce9c0251435d6f98 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 30 Nov 2017 11:56:13 -0600 Subject: [PATCH 074/117] build proper DeliverTx tags --- glide.lock | 6 +++--- modules/coin/handler.go | 22 +++------------------- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/glide.lock b/glide.lock index c4c515468506..3b225c69d214 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: b458f1ec5c9386c5c7439fa5ee7a3fe1a812813aef7681ccc18c511fa25073a2 -updated: 2017-11-30T16:15:15.656201018+01:00 +updated: 2017-11-30T17:49:32.657374318Z imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -112,7 +112,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: b89fd815a5e63bd424093aa0ef84d2e146d30c58 + version: 22b491bb1952125dd2fb0730d6ca8e59e310547c subpackages: - client - example/dummy @@ -141,7 +141,7 @@ imports: - name: github.com/tendermint/iavl version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653 - name: github.com/tendermint/tendermint - version: cb9743e5671776d683cdb9a51de7d12854a2acae + version: 03222d834b8dccde63ed10840a294164caa17f04 subpackages: - blockchain - certifiers diff --git a/modules/coin/handler.go b/modules/coin/handler.go index 9885db2958a5..1c28257b8e2b 100644 --- a/modules/coin/handler.go +++ b/modules/coin/handler.go @@ -153,38 +153,22 @@ func (h Handler) sendTx(ctx sdk.Context, store state.SimpleDB, // now we build the tags tags := make([]*abci.KVPair, 0) - tags = append(tags, tagInt("height", int64(ctx.BlockHeight()))) + tags = append(tags, abci.KVPairInt("height", int64(ctx.BlockHeight()))) for _, in := range send.Inputs { addr := in.Address.Address.String() - tags = append(tags, tagStr("coin.sender", addr)) + tags = append(tags, abci.KVPairString("coin.sender", addr)) } for _, out := range send.Outputs { addr := out.Address.Address.String() - tags = append(tags, tagStr("coin.receiver", addr)) + tags = append(tags, abci.KVPairString("coin.receiver", addr)) } // a-ok! return sdk.DeliverResult{Tags: tags}, nil } -func tagInt(key string, val int64) *abci.KVPair { - return &abci.KVPair{ - Key: key, - ValueInt: val, - ValueType: abci.KVPair_INT, - } -} - -func tagStr(key, val string) *abci.KVPair { - return &abci.KVPair{ - Key: key, - ValueString: val, - ValueType: abci.KVPair_STRING, - } -} - func (h Handler) creditTx(ctx sdk.Context, store state.SimpleDB, credit CreditTx) error { From 599390868fe3d471efeb49318e61cd393f81bca2 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 1 Dec 2017 09:59:57 +0100 Subject: [PATCH 075/117] Fix ibc cli test --- tests/cli/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cli/common.sh b/tests/cli/common.sh index a1100d469a84..3605d81e999b 100644 --- a/tests/cli/common.sh +++ b/tests/cli/common.sh @@ -80,7 +80,7 @@ initServer() { fi # add indexing - cat > $SERVE_DIR/config.toml << EOF + cat >> $SERVE_DIR/config.toml << EOF [tx_index] indexer = "kv" From 385c20612a63a4b2681a285b384fb000fbce71dd Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 1 Dec 2017 10:15:28 +0100 Subject: [PATCH 076/117] Update deps... for hid/ledger fixes --- glide.lock | 16 ++++++++-------- glide.yaml | 9 +++++++-- modules/coin/handler.go | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/glide.lock b/glide.lock index 3b225c69d214..a629377600d7 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: b458f1ec5c9386c5c7439fa5ee7a3fe1a812813aef7681ccc18c511fa25073a2 -updated: 2017-11-30T17:49:32.657374318Z +hash: 791d28ec82d1ea662cc3f192aa7bf1f6dffdc1f2e43e57ce731857d6ea147ee4 +updated: 2017-12-01T10:08:25.699042855+01:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -11,10 +11,10 @@ imports: version: a368813c5e648fee92e5f6c30e3944ff9d5e8895 - name: github.com/ebuchman/fail-test version: 95f809107225be108efcf10a3509e4ea6ceef3c4 +- name: github.com/ethanfrey/hid + version: dce75af84cf849c60f39bf1b8192fb5cd597b5d9 - name: github.com/ethanfrey/ledger - version: 5e432577be582bd18a3b4a9cd75dae7a317ade36 -- name: github.com/flynn/hid - version: ed06a31c6245d4552e8dbba7e32e5b010b875d65 + version: f7f2f056357db77db845a79aa1abdadc3ae66369 - name: github.com/fsnotify/fsnotify version: 4da3e2cfbabc9f751898f250b49f2439785783a1 - name: github.com/go-kit/kit @@ -119,7 +119,7 @@ imports: - server - types - name: github.com/tendermint/ed25519 - version: 1f52c6f8b8a5c7908aff4497c186af344b428925 + version: d8387025d2b9d158cf4efb07e7ebf814bcce2057 subpackages: - edwards25519 - extra25519 @@ -133,7 +133,7 @@ imports: - keys/wordlist - nano - name: github.com/tendermint/go-wire - version: 7d50b38b3815efe313728de77e2995c8813ce13f + version: 217a3c439f6497890d232ff5ed24084b43d9bfb3 subpackages: - data - data/base58 @@ -141,7 +141,7 @@ imports: - name: github.com/tendermint/iavl version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653 - name: github.com/tendermint/tendermint - version: 03222d834b8dccde63ed10840a294164caa17f04 + version: b2489b4318c843a64e2809517f93d906c5f9dc15 subpackages: - blockchain - certifiers diff --git a/glide.yaml b/glide.yaml index a23b69f2b183..718cc1b5d4f0 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,13 +1,18 @@ package: github.com/cosmos/cosmos-sdk import: +- package: github.com/ethanfrey/hid + version: dce75af84cf849c60f39bf1b8192fb5cd597b5d9 +- package: github.com/ethanfrey/ledger + version: f7f2f056357db77db845a79aa1abdadc3ae66369 - package: github.com/gorilla/websocket - package: github.com/pkg/errors version: ^0.8.0 - package: github.com/spf13/cobra - package: github.com/spf13/pflag - package: github.com/spf13/viper +# update this when tendermint/tendermint updates - package: github.com/tendermint/abci - version: develop + version: 22b491bb1952125dd2fb0730d6ca8e59e310547c subpackages: - server - types @@ -22,7 +27,7 @@ import: - package: github.com/tendermint/iavl version: develop - package: github.com/tendermint/tendermint - version: feature/indexing + version: develop subpackages: - certifiers - certifiers/client diff --git a/modules/coin/handler.go b/modules/coin/handler.go index 1c28257b8e2b..c79881219eb9 100644 --- a/modules/coin/handler.go +++ b/modules/coin/handler.go @@ -151,7 +151,7 @@ func (h Handler) sendTx(ctx sdk.Context, store state.SimpleDB, } // now we build the tags - tags := make([]*abci.KVPair, 0) + tags := make([]*abci.KVPair, 0, 1+len(send.Inputs)+len(send.Outputs)) tags = append(tags, abci.KVPairInt("height", int64(ctx.BlockHeight()))) From d647a954a1b388a1b56aa8cbc57e920a89adbac3 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 1 Dec 2017 10:24:53 +0100 Subject: [PATCH 077/117] Fix rpc tests after update --- examples/basecoin/tests/cli/rpc.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/basecoin/tests/cli/rpc.sh b/examples/basecoin/tests/cli/rpc.sh index 5ab6022d9b2b..3a881c8ccd24 100755 --- a/examples/basecoin/tests/cli/rpc.sh +++ b/examples/basecoin/tests/cli/rpc.sh @@ -70,6 +70,11 @@ test01GetInsecure() { } test02GetSecure() { + # checking old headers only works if there is enough info + # before it. Wait until we are at least at height 3, so this + # works properly (querying previous commits) + ${CLIENT_EXE} rpc wait --height=3 > /dev/null + HEIGHT=$(${CLIENT_EXE} rpc status | jq .latest_block_height) assertTrue "line=${LINENO}, get status" "$?" From d14d85d07c304512b3927d2244f5352a474ef8f7 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 1 Dec 2017 11:17:30 +0100 Subject: [PATCH 078/117] Add basecli search sent to find sendtx --- client/commands/search/root.go | 32 ++++++++++++++ client/commands/search/search.go | 14 +++++++ context.go | 10 +++-- examples/basecoin/cmd/basecli/main.go | 7 ++++ examples/basecoin/tests/cli/basictx.sh | 10 ++++- modules/coin/commands/search.go | 58 ++++++++++++++++++++++++++ modules/coin/handler.go | 4 +- 7 files changed, 127 insertions(+), 8 deletions(-) create mode 100644 client/commands/search/root.go create mode 100644 client/commands/search/search.go create mode 100644 modules/coin/commands/search.go diff --git a/client/commands/search/root.go b/client/commands/search/root.go new file mode 100644 index 000000000000..65b22e1ac99a --- /dev/null +++ b/client/commands/search/root.go @@ -0,0 +1,32 @@ +package search + +import ( + "github.com/cosmos/cosmos-sdk/client/commands" + "github.com/spf13/cobra" +) + +// nolint +const ( + FlagMinHeight = "minHeight" + FlagMaxHeight = "maxHeight" +) + +// RootCmd represents the base command when called without any subcommands +var RootCmd = &cobra.Command{ + Use: "search", + Short: "Search for specific transactions based on tags", + Long: `Search has subcommands for each specific tx type. + +Each one has specific flags it allows you to search on and +these are exposed on those subcommands. Returns all historical +transactions that match those tags. +`, +} + +func init() { + RootCmd.PersistentFlags().Int(FlagMinHeight, 0, "Minimum height to include in search (skip for all history)") + RootCmd.PersistentFlags().Int(FlagMaxHeight, 0, "Max height to include in search (skip to include latest)") + RootCmd.PersistentFlags().Bool(commands.FlagTrustNode, false, + "DANGEROUS: blindly trust all results from the server") + RootCmd.PersistentFlags().MarkHidden(commands.FlagTrustNode) +} diff --git a/client/commands/search/search.go b/client/commands/search/search.go new file mode 100644 index 000000000000..414c2cd8b157 --- /dev/null +++ b/client/commands/search/search.go @@ -0,0 +1,14 @@ +package search + +import ( + "github.com/cosmos/cosmos-sdk/client/commands" + + ctypes "github.com/tendermint/tendermint/rpc/core/types" +) + +// FindTx performs the given search +func FindTx(query string, prove bool) ([]*ctypes.ResultTx, error) { + client := commands.GetNode() + // TODO: actually verify these proofs!!! + return client.TxSearch(query, prove) +} diff --git a/context.go b/context.go index 75677f0857e8..fedca0def4f1 100644 --- a/context.go +++ b/context.go @@ -31,6 +31,12 @@ func (a Actor) Bytes() []byte { return wire.BinaryBytes(a) } +// String provides a human-readable representation of an actor +func (a Actor) String() string { + return fmt.Sprintf("%s", a.Address) + // return fmt.Sprintf("%s:%s:%s", a.ChainID, a.App, a.Address) +} + // Equals checks if two actors are the same func (a Actor) Equals(b Actor) bool { return a.ChainID == b.ChainID && @@ -78,10 +84,6 @@ type Context interface { //////////////////////////////// Sort Interface // USAGE sort.Sort(ByAll()) -func (a Actor) String() string { - return fmt.Sprintf("%x", a.Address) -} - // ByAll implements sort.Interface for []Actor. // It sorts be the ChainID, followed by the App, followed by the Address type ByAll []Actor diff --git a/examples/basecoin/cmd/basecli/main.go b/examples/basecoin/cmd/basecli/main.go index 107890a75e22..d0a3dc1b12fe 100644 --- a/examples/basecoin/cmd/basecli/main.go +++ b/examples/basecoin/cmd/basecli/main.go @@ -14,6 +14,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/commands/proxy" "github.com/cosmos/cosmos-sdk/client/commands/query" rpccmd "github.com/cosmos/cosmos-sdk/client/commands/rpc" + "github.com/cosmos/cosmos-sdk/client/commands/search" txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs" authcmd "github.com/cosmos/cosmos-sdk/modules/auth/commands" basecmd "github.com/cosmos/cosmos-sdk/modules/base/commands" @@ -49,6 +50,11 @@ func main() { ibccmd.IBCQueryCmd, ) + // these are queries to search for a tx + search.RootCmd.AddCommand( + coincmd.SentSearchCmd, + ) + // set up the middleware txcmd.Middleware = txcmd.Wrappers{ feecmd.FeeWrapper{}, @@ -80,6 +86,7 @@ func main() { commits.RootCmd, rpccmd.RootCmd, query.RootCmd, + search.RootCmd, txcmd.RootCmd, proxy.RootCmd, commands.VersionCmd, diff --git a/examples/basecoin/tests/cli/basictx.sh b/examples/basecoin/tests/cli/basictx.sh index 13320e719822..0cf24461ac11 100755 --- a/examples/basecoin/tests/cli/basictx.sh +++ b/examples/basecoin/tests/cli/basictx.sh @@ -48,8 +48,14 @@ test01SendTx() { # Make sure tx is indexed checkSendTx $HASH $TX_HEIGHT $SENDER "992" - echo "search for tx (demo):" - curl "http://localhost:46657/tx_search?query=\"coin.sender='${SENDER}'\"&prove=true" + # echo "search for tx (demo):" + # curl "http://localhost:46657/tx_search?query=\"coin.sender='${SENDER}'\"&prove=true" + # echo + + echo "cli search" + ${CLIENT_EXE} search sent ${SENDER} + ${CLIENT_EXE} search sent ${RECV} + ${CLIENT_EXE} search sent 1234567890123456789012345678901234567890 echo } diff --git a/modules/coin/commands/search.go b/modules/coin/commands/search.go new file mode 100644 index 000000000000..928cf26bda35 --- /dev/null +++ b/modules/coin/commands/search.go @@ -0,0 +1,58 @@ +package commands + +import ( + "fmt" + "sort" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/tendermint/go-wire/data" + + "github.com/cosmos/cosmos-sdk/client/commands" + "github.com/cosmos/cosmos-sdk/client/commands/search" +) + +// SentSearchCmd - command to find sendtx +var SentSearchCmd = &cobra.Command{ + Use: "sent [address]", + Short: "Find all tx with this address as sender or receiver", + RunE: commands.RequireInit(sentSearchCmd), +} + +func sentSearchCmd(cmd *cobra.Command, args []string) error { + addr, err := commands.GetOneArg(args, "address") + if err != nil { + return err + } + act, err := commands.ParseActor(addr) + if err != nil { + return err + } + + findSender := fmt.Sprintf("coin.sender='%s'", act) + findReceiver := fmt.Sprintf("coin.receiver='%s'", act) + + prove := !viper.GetBool(commands.FlagTrustNode) + txs, err := search.FindTx(findSender, prove) + if err != nil { + return err + } + txr, err := search.FindTx(findReceiver, prove) + if err != nil { + return err + } + + // combine both lists and sort by height descending + all := append(txs, txr...) + sort.Slice(all, func(i, j int) bool { + return all[i].Height > all[j].Height + }) + + // output as json + blob, err := data.ToJSON(all) + if err != nil { + return err + } + fmt.Println(string(blob)) + return nil +} diff --git a/modules/coin/handler.go b/modules/coin/handler.go index c79881219eb9..90d8642f6b38 100644 --- a/modules/coin/handler.go +++ b/modules/coin/handler.go @@ -156,12 +156,12 @@ func (h Handler) sendTx(ctx sdk.Context, store state.SimpleDB, tags = append(tags, abci.KVPairInt("height", int64(ctx.BlockHeight()))) for _, in := range send.Inputs { - addr := in.Address.Address.String() + addr := in.Address.String() tags = append(tags, abci.KVPairString("coin.sender", addr)) } for _, out := range send.Outputs { - addr := out.Address.Address.String() + addr := out.Address.String() tags = append(tags, abci.KVPairString("coin.receiver", addr)) } From d3e6efb9439f1c049698a6b61106d863fdd7f610 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 1 Dec 2017 12:51:46 +0100 Subject: [PATCH 079/117] basecli search sent formats output properly --- examples/basecoin/tests/cli/basictx.sh | 26 ++++--- modules/base/tx.go | 5 +- modules/coin/commands/search.go | 93 +++++++++++++++++++++++++- modules/nonce/tx.go | 5 +- 4 files changed, 117 insertions(+), 12 deletions(-) diff --git a/examples/basecoin/tests/cli/basictx.sh b/examples/basecoin/tests/cli/basictx.sh index 0cf24461ac11..df95b767d106 100755 --- a/examples/basecoin/tests/cli/basictx.sh +++ b/examples/basecoin/tests/cli/basictx.sh @@ -48,15 +48,23 @@ test01SendTx() { # Make sure tx is indexed checkSendTx $HASH $TX_HEIGHT $SENDER "992" - # echo "search for tx (demo):" - # curl "http://localhost:46657/tx_search?query=\"coin.sender='${SENDER}'\"&prove=true" - # echo - - echo "cli search" - ${CLIENT_EXE} search sent ${SENDER} - ${CLIENT_EXE} search sent ${RECV} - ${CLIENT_EXE} search sent 1234567890123456789012345678901234567890 - echo + CMD="${CLIENT_EXE} search sent ${SENDER}" + echo $CMD + $CMD + + SENT_TX=$(${CLIENT_EXE} search sent ${SENDER}) + assertEquals "line=${LINENO}" 1 $(echo ${SENT_TX} | jq '. | length') + assertEquals "line=${LINENO}" $TX_HEIGHT $(echo ${SENT_TX} | jq '.[0].height') + + IN=$(echo ${SENT_TX} | jq '.[0].tx.inputs') + assertEquals "line=${LINENO}" 1 $(echo ${IN} | jq '. | length') + assertEquals "line=${LINENO}" 992 $(echo ${IN} | jq '.[0].coins[0].amount') + assertEquals "line=${LINENO}" "\"$SENDER\"" $(echo ${IN} | jq '.[0].sender') + + OUT=$(echo ${SENT_TX} | jq '.[0].tx.outputs') + assertEquals "line=${LINENO}" 1 $(echo ${OUT} | jq '. | length') + assertEquals "line=${LINENO}" 992 $(echo ${OUT} | jq '.[0].coins[0].amount') + assertEquals "line=${LINENO}" "\"$RECV\"" $(echo ${OUT} | jq '.[0].receiver') } test02SendTxWithFee() { diff --git a/modules/base/tx.go b/modules/base/tx.go index edd57b672147..8b3a88fb2c0e 100644 --- a/modules/base/tx.go +++ b/modules/base/tx.go @@ -59,7 +59,7 @@ type ChainTx struct { // name of chain, must be [A-Za-z0-9_-]+ ChainID string `json:"chain_id"` // block height at which it is no longer valid, 0 means no expiration - ExpiresAt uint64 `json:"expires_at"` + ExpiresAt uint64 `json:"expires_at"` Tx sdk.Tx `json:"tx"` } @@ -97,3 +97,6 @@ func (c ChainTx) ValidateBasic() error { // TODO: more checks? chainID? return c.Tx.ValidateBasic() } +func (c ChainTx) Next() sdk.Tx { + return c.Tx +} diff --git a/modules/coin/commands/search.go b/modules/coin/commands/search.go index 928cf26bda35..28d60882f074 100644 --- a/modules/coin/commands/search.go +++ b/modules/coin/commands/search.go @@ -6,10 +6,15 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + "github.com/tendermint/go-wire/data" + ctypes "github.com/tendermint/tendermint/rpc/core/types" + sdk "github.com/cosmos/cosmos-sdk" "github.com/cosmos/cosmos-sdk/client/commands" "github.com/cosmos/cosmos-sdk/client/commands/search" + "github.com/cosmos/cosmos-sdk/errors" + "github.com/cosmos/cosmos-sdk/modules/coin" ) // SentSearchCmd - command to find sendtx @@ -48,11 +53,97 @@ func sentSearchCmd(cmd *cobra.Command, args []string) error { return all[i].Height > all[j].Height }) + // format.... + output, err := formatResults(all) + if err != nil { + return err + } + // output as json - blob, err := data.ToJSON(all) + blob, err := data.ToJSON(output) if err != nil { return err } fmt.Println(string(blob)) return nil } + +type ResultOutput struct { + Tx *CoinTx `json:"tx"` + Height int64 `json:"height"` +} + +type CoinTx struct { + Inputs []CoinInput `json:"inputs"` + Outputs []CoinOutput `json:"outputs"` +} + +type CoinInput struct { + Sender string `json:"sender"` + Coins coin.Coins `json:"coins"` +} + +type CoinOutput struct { + Receiver string `json:"receiver"` + Coins coin.Coins `json:"coins"` +} + +func formatResults(res []*ctypes.ResultTx) ([]ResultOutput, error) { + out := make([]ResultOutput, 0, len(res)) + for _, r := range res { + ctx, err := extractCoinTx(r.Tx) + if err != nil { + return nil, err + } + ro := ResultOutput{ + Height: int64(r.Height), + Tx: ctx, + } + + out = append(out, ro) + } + return out, nil +} + +func extractCoinTx(data []byte) (*CoinTx, error) { + tx, err := sdk.LoadTx(data) + if err != nil { + return nil, err + } + txl, ok := tx.Unwrap().(sdk.TxLayer) + for ok { + tx = txl.Next() + txl, ok = tx.Unwrap().(sdk.TxLayer) + } + ctx, ok := tx.Unwrap().(coin.SendTx) + if !ok { + return nil, errors.ErrUnknownTxType(tx) + } + // now reformat this.... + return &CoinTx{ + Inputs: transformInputs(ctx.Inputs), + Outputs: transformOutputs(ctx.Outputs), + }, nil +} + +func transformInputs(input []coin.TxInput) []CoinInput { + out := make([]CoinInput, 0, len(input)) + for _, in := range input { + out = append(out, CoinInput{ + Sender: in.Address.String(), + Coins: in.Coins, + }) + } + return out +} + +func transformOutputs(output []coin.TxOutput) []CoinOutput { + out := make([]CoinOutput, 0, len(output)) + for _, val := range output { + out = append(out, CoinOutput{ + Receiver: val.Address.String(), + Coins: val.Coins, + }) + } + return out +} diff --git a/modules/nonce/tx.go b/modules/nonce/tx.go index ba5b21c31ffd..256849e6be2a 100644 --- a/modules/nonce/tx.go +++ b/modules/nonce/tx.go @@ -26,7 +26,7 @@ func init() { // Tx - Nonce transaction structure, contains list of signers and current sequence number type Tx struct { - Sequence uint32 `json:"sequence"` + Sequence uint32 `json:"sequence"` Signers []sdk.Actor `json:"signers"` Tx sdk.Tx `json:"tx"` } @@ -57,6 +57,9 @@ func (n Tx) ValidateBasic() error { } return n.Tx.ValidateBasic() } +func (n Tx) Next() sdk.Tx { + return n.Tx +} // CheckIncrementSeq - Check that the sequence number is one more than the state sequence number // and further increment the sequence number From d5c91d1f5fd5ddf817eedf487551e8c0e0e1ee9b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 1 Dec 2017 13:58:42 +0100 Subject: [PATCH 080/117] Expose senttx search in LCD --- client/commands/search/search.go | 71 +++++++++++++++ examples/basecoin/cmd/baseserver/main.go | 4 +- examples/basecoin/tests/cli/basictx.sh | 7 +- examples/basecoin/tests/cli/rest.sh | 7 ++ modules/coin/commands/search.go | 108 +---------------------- modules/coin/rest/handlers.go | 54 ++++++++++++ modules/coin/transform.go | 65 ++++++++++++++ 7 files changed, 205 insertions(+), 111 deletions(-) create mode 100644 modules/coin/transform.go diff --git a/client/commands/search/search.go b/client/commands/search/search.go index 414c2cd8b157..0a71a5464dbc 100644 --- a/client/commands/search/search.go +++ b/client/commands/search/search.go @@ -1,8 +1,14 @@ package search import ( + "fmt" + "io" + "os" + "sort" + "github.com/cosmos/cosmos-sdk/client/commands" + "github.com/tendermint/go-wire/data" ctypes "github.com/tendermint/tendermint/rpc/core/types" ) @@ -12,3 +18,68 @@ func FindTx(query string, prove bool) ([]*ctypes.ResultTx, error) { // TODO: actually verify these proofs!!! return client.TxSearch(query, prove) } + +// FindAnyTx search all of the strings sequentionally and +// returns combined result +func FindAnyTx(prove bool, queries ...string) ([]*ctypes.ResultTx, error) { + var all []*ctypes.ResultTx + // combine all requests + for _, q := range queries { + txs, err := FindTx(q, prove) + if err != nil { + return nil, err + } + all = append(all, txs...) + } + sort.Slice(all, func(i, j int) bool { + return all[i].Height > all[j].Height + }) + return all, nil +} + +// TxExtractor take an encoded tx and converts it to +// a usable format +type TxExtractor func([]byte) (interface{}, error) + +// TxOutput is like the query output, but stores Tx data +type TxOutput struct { + Tx interface{} `json:"tx"` + Height int64 `json:"height"` +} + +// FormatSearch takes the FindTx results and converts them +// to a format to display with help of a TxExtractor that +// knows how to present the tx +func FormatSearch(res []*ctypes.ResultTx, fn TxExtractor) ([]TxOutput, error) { + out := make([]TxOutput, 0, len(res)) + for _, r := range res { + ctx, err := fn(r.Tx) + if err != nil { + return nil, err + } + ro := TxOutput{ + Height: int64(r.Height), + Tx: ctx, + } + out = append(out, ro) + } + return out, nil +} + +// Foutput writes the output of wrapping height and info +// in the form {"data": , "height": } +// to the provider io.Writer +func Foutput(w io.Writer, v interface{}) error { + blob, err := data.ToJSON(v) + if err != nil { + return err + } + _, err = fmt.Fprintf(w, "%s\n", string(blob)) + return err +} + +// Output prints the search results from FormatSearch +// to stdout +func Output(data interface{}) error { + return Foutput(os.Stdout, data) +} diff --git a/examples/basecoin/cmd/baseserver/main.go b/examples/basecoin/cmd/baseserver/main.go index a92e8edd0190..c4b4c2a8692a 100644 --- a/examples/basecoin/cmd/baseserver/main.go +++ b/examples/basecoin/cmd/baseserver/main.go @@ -48,9 +48,7 @@ func serve(cmd *cobra.Command, args []string) error { rest.NewDefaultKeysManager(defaultAlgo).RegisterAllCRUD, // Coin send handler - coinrest.RegisterCoinSend, - // Coin query account handler - coinrest.RegisterQueryAccount, + coinrest.RegisterAll, // Roles createRole handler rolerest.RegisterCreateRole, diff --git a/examples/basecoin/tests/cli/basictx.sh b/examples/basecoin/tests/cli/basictx.sh index df95b767d106..70c9c980d716 100755 --- a/examples/basecoin/tests/cli/basictx.sh +++ b/examples/basecoin/tests/cli/basictx.sh @@ -48,9 +48,10 @@ test01SendTx() { # Make sure tx is indexed checkSendTx $HASH $TX_HEIGHT $SENDER "992" - CMD="${CLIENT_EXE} search sent ${SENDER}" - echo $CMD - $CMD + # For demoing output + # CMD="${CLIENT_EXE} search sent ${SENDER}" + # echo $CMD + # $CMD SENT_TX=$(${CLIENT_EXE} search sent ${SENDER}) assertEquals "line=${LINENO}" 1 $(echo ${SENT_TX} | jq '. | length') diff --git a/examples/basecoin/tests/cli/rest.sh b/examples/basecoin/tests/cli/rest.sh index 076e08e3e4af..f02878cdf3d7 100755 --- a/examples/basecoin/tests/cli/rest.sh +++ b/examples/basecoin/tests/cli/rest.sh @@ -87,6 +87,13 @@ test01SendTx() { checkSendTx $HASH $TX_HEIGHT $SENDER "992" } +test02FindTx() { + SENDER=$(restAddr $RICH) + QUERY=${URL}/tx/coin/$SENDER + echo "search" + curl ${QUERY} 2>/dev/null +} + # XXX Ex Usage: restCreateRole $PAYLOAD $EXPECTED # Desc: Tests that the first returned signer.addr matches the expected diff --git a/modules/coin/commands/search.go b/modules/coin/commands/search.go index 28d60882f074..ff8069a5f08c 100644 --- a/modules/coin/commands/search.go +++ b/modules/coin/commands/search.go @@ -2,18 +2,12 @@ package commands import ( "fmt" - "sort" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/go-wire/data" - ctypes "github.com/tendermint/tendermint/rpc/core/types" - - sdk "github.com/cosmos/cosmos-sdk" "github.com/cosmos/cosmos-sdk/client/commands" "github.com/cosmos/cosmos-sdk/client/commands/search" - "github.com/cosmos/cosmos-sdk/errors" "github.com/cosmos/cosmos-sdk/modules/coin" ) @@ -38,112 +32,16 @@ func sentSearchCmd(cmd *cobra.Command, args []string) error { findReceiver := fmt.Sprintf("coin.receiver='%s'", act) prove := !viper.GetBool(commands.FlagTrustNode) - txs, err := search.FindTx(findSender, prove) - if err != nil { - return err - } - txr, err := search.FindTx(findReceiver, prove) + all, err := search.FindAnyTx(prove, findSender, findReceiver) if err != nil { return err } - // combine both lists and sort by height descending - all := append(txs, txr...) - sort.Slice(all, func(i, j int) bool { - return all[i].Height > all[j].Height - }) - // format.... - output, err := formatResults(all) - if err != nil { - return err - } - - // output as json - blob, err := data.ToJSON(output) + output, err := search.FormatSearch(all, coin.ExtractCoinTx) if err != nil { return err } - fmt.Println(string(blob)) - return nil -} - -type ResultOutput struct { - Tx *CoinTx `json:"tx"` - Height int64 `json:"height"` -} - -type CoinTx struct { - Inputs []CoinInput `json:"inputs"` - Outputs []CoinOutput `json:"outputs"` -} - -type CoinInput struct { - Sender string `json:"sender"` - Coins coin.Coins `json:"coins"` -} - -type CoinOutput struct { - Receiver string `json:"receiver"` - Coins coin.Coins `json:"coins"` -} - -func formatResults(res []*ctypes.ResultTx) ([]ResultOutput, error) { - out := make([]ResultOutput, 0, len(res)) - for _, r := range res { - ctx, err := extractCoinTx(r.Tx) - if err != nil { - return nil, err - } - ro := ResultOutput{ - Height: int64(r.Height), - Tx: ctx, - } - - out = append(out, ro) - } - return out, nil -} - -func extractCoinTx(data []byte) (*CoinTx, error) { - tx, err := sdk.LoadTx(data) - if err != nil { - return nil, err - } - txl, ok := tx.Unwrap().(sdk.TxLayer) - for ok { - tx = txl.Next() - txl, ok = tx.Unwrap().(sdk.TxLayer) - } - ctx, ok := tx.Unwrap().(coin.SendTx) - if !ok { - return nil, errors.ErrUnknownTxType(tx) - } - // now reformat this.... - return &CoinTx{ - Inputs: transformInputs(ctx.Inputs), - Outputs: transformOutputs(ctx.Outputs), - }, nil -} - -func transformInputs(input []coin.TxInput) []CoinInput { - out := make([]CoinInput, 0, len(input)) - for _, in := range input { - out = append(out, CoinInput{ - Sender: in.Address.String(), - Coins: in.Coins, - }) - } - return out -} -func transformOutputs(output []coin.TxOutput) []CoinOutput { - out := make([]CoinOutput, 0, len(output)) - for _, val := range output { - out = append(out, CoinOutput{ - Receiver: val.Address.String(), - Coins: val.Coins, - }) - } - return out + return search.Output(output) } diff --git a/modules/coin/rest/handlers.go b/modules/coin/rest/handlers.go index a7362c706dcc..2e1841f8ae30 100644 --- a/modules/coin/rest/handlers.go +++ b/modules/coin/rest/handlers.go @@ -13,6 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/commands" "github.com/cosmos/cosmos-sdk/client/commands/query" + "github.com/cosmos/cosmos-sdk/client/commands/search" "github.com/cosmos/cosmos-sdk/modules/auth" "github.com/cosmos/cosmos-sdk/modules/base" "github.com/cosmos/cosmos-sdk/modules/coin" @@ -76,6 +77,51 @@ func doQueryAccount(w http.ResponseWriter, r *http.Request) { } } +// doQueryAccount is the HTTP handlerfunc to search for +// all SendTx transactions with this account as sender +// or receiver +func doSearchSent(w http.ResponseWriter, r *http.Request) { + args := mux.Vars(r) + account := args["account"] + actor, err := commands.ParseActor(account) + if err != nil { + common.WriteError(w, err) + return + } + + // TODO: handle minHeight... + // var h int + // qHeight := r.URL.Query().Get("height") + // if qHeight != "" { + // h, err = strconv.Atoi(qHeight) + // if err != nil { + // common.WriteError(w, err) + // return + // } + // } + + findSender := fmt.Sprintf("coin.sender='%s'", actor) + findReceiver := fmt.Sprintf("coin.receiver='%s'", actor) + prove := !viper.GetBool(commands.FlagTrustNode) + all, err := search.FindAnyTx(prove, findSender, findReceiver) + if err != nil { + common.WriteError(w, err) + return + } + + // format.... + output, err := search.FormatSearch(all, coin.ExtractCoinTx) + if err != nil { + common.WriteError(w, err) + return + } + + // display + if err := search.Foutput(w, output); err != nil { + common.WriteError(w, err) + } +} + func PrepareSendTx(si *SendInput) sdk.Tx { tx := coin.NewSendOneTx(*si.From, *si.To, si.Amount) // fees are optional @@ -147,12 +193,20 @@ func RegisterQueryAccount(r *mux.Router) error { return nil } +// RegisterSearchSent is a mux.Router handler that exposes GET +// method access on route /tx/coin/{account} to historical sendtx transactions +func RegisterSearchSent(r *mux.Router) error { + r.HandleFunc("/tx/coin/{account}", doSearchSent).Methods("GET") + return nil +} + // RegisterAll is a convenience function to // register all the handlers in this package. func RegisterAll(r *mux.Router) error { funcs := []func(*mux.Router) error{ RegisterCoinSend, RegisterQueryAccount, + RegisterSearchSent, } for _, fn := range funcs { diff --git a/modules/coin/transform.go b/modules/coin/transform.go new file mode 100644 index 000000000000..25ff2c06424e --- /dev/null +++ b/modules/coin/transform.go @@ -0,0 +1,65 @@ +package coin + +import ( + sdk "github.com/cosmos/cosmos-sdk" + "github.com/cosmos/cosmos-sdk/errors" +) + +type coinTx struct { + Inputs []coinInput `json:"inputs"` + Outputs []coinOutput `json:"outputs"` +} + +type coinInput struct { + Sender string `json:"sender"` + Coins Coins `json:"coins"` +} + +type coinOutput struct { + Receiver string `json:"receiver"` + Coins Coins `json:"coins"` +} + +// ExtractCoinTx makes nice json from raw tx bytes +func ExtractCoinTx(data []byte) (interface{}, error) { + tx, err := sdk.LoadTx(data) + if err != nil { + return nil, err + } + txl, ok := tx.Unwrap().(sdk.TxLayer) + for ok { + tx = txl.Next() + txl, ok = tx.Unwrap().(sdk.TxLayer) + } + ctx, ok := tx.Unwrap().(SendTx) + if !ok { + return nil, errors.ErrUnknownTxType(tx) + } + // now reformat this.... + return &coinTx{ + Inputs: transformInputs(ctx.Inputs), + Outputs: transformOutputs(ctx.Outputs), + }, nil +} + +func transformInputs(input []TxInput) []coinInput { + out := make([]coinInput, 0, len(input)) + for _, in := range input { + out = append(out, coinInput{ + Sender: in.Address.String(), + Coins: in.Coins, + }) + } + return out +} + +func transformOutputs(output []TxOutput) []coinOutput { + out := make([]coinOutput, 0, len(output)) + for _, val := range output { + out = append(out, coinOutput{ + Receiver: val.Address.String(), + Coins: val.Coins, + }) + } + return out +} From d87d6521121d970dd78fd3cab7dcd17fa6e5a82a Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 1 Dec 2017 17:48:15 +0100 Subject: [PATCH 081/117] Update hid for osx... again --- glide.lock | 2 +- glide.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/glide.lock b/glide.lock index a629377600d7..e65ce91197ef 100644 --- a/glide.lock +++ b/glide.lock @@ -12,7 +12,7 @@ imports: - name: github.com/ebuchman/fail-test version: 95f809107225be108efcf10a3509e4ea6ceef3c4 - name: github.com/ethanfrey/hid - version: dce75af84cf849c60f39bf1b8192fb5cd597b5d9 + version: f76da0b80567e8b6f676e1757b549a93494fe4b5 - name: github.com/ethanfrey/ledger version: f7f2f056357db77db845a79aa1abdadc3ae66369 - name: github.com/fsnotify/fsnotify diff --git a/glide.yaml b/glide.yaml index 718cc1b5d4f0..84086d33b194 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,7 +1,7 @@ package: github.com/cosmos/cosmos-sdk import: - package: github.com/ethanfrey/hid - version: dce75af84cf849c60f39bf1b8192fb5cd597b5d9 + version: f76da0b80567e8b6f676e1757b549a93494fe4b5 - package: github.com/ethanfrey/ledger version: f7f2f056357db77db845a79aa1abdadc3ae66369 - package: github.com/gorilla/websocket From 38fdd7ad1fd7732e536b7e3311467620b70f1669 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 1 Dec 2017 17:52:51 +0100 Subject: [PATCH 082/117] Update rest search test --- examples/basecoin/tests/cli/rest.sh | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/examples/basecoin/tests/cli/rest.sh b/examples/basecoin/tests/cli/rest.sh index f02878cdf3d7..e0ae959c3c20 100755 --- a/examples/basecoin/tests/cli/rest.sh +++ b/examples/basecoin/tests/cli/rest.sh @@ -89,9 +89,27 @@ test01SendTx() { test02FindTx() { SENDER=$(restAddr $RICH) + RECV=$(restAddr $POOR) + QUERY=${URL}/tx/coin/$SENDER - echo "search" - curl ${QUERY} 2>/dev/null + + # For demoing rest + # echo "search" + # curl ${QUERY} 2>/dev/null + + SENT_TX=$(curl ${QUERY} 2>/dev/null) + assertEquals "line=${LINENO}" 1 $(echo ${SENT_TX} | jq '. | length') + assertEquals "line=${LINENO}" $TX_HEIGHT $(echo ${SENT_TX} | jq '.[0].height') + + IN=$(echo ${SENT_TX} | jq '.[0].tx.inputs') + assertEquals "line=${LINENO}" 1 $(echo ${IN} | jq '. | length') + assertEquals "line=${LINENO}" 992 $(echo ${IN} | jq '.[0].coins[0].amount') + assertEquals "line=${LINENO}" "\"$SENDER\"" $(echo ${IN} | jq '.[0].sender') + + OUT=$(echo ${SENT_TX} | jq '.[0].tx.outputs') + assertEquals "line=${LINENO}" 1 $(echo ${OUT} | jq '. | length') + assertEquals "line=${LINENO}" 992 $(echo ${OUT} | jq '.[0].coins[0].amount') + assertEquals "line=${LINENO}" "\"$RECV\"" $(echo ${OUT} | jq '.[0].receiver') } From d29a6ca7fd4edac38398d5b009393af4438f591e Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 5 Dec 2017 15:37:03 +0100 Subject: [PATCH 083/117] Adding links to API in readme --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 3e759ebc337f..a801805dd9d2 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,10 @@ go get -u github.com/cosmos/cosmos-sdk/cmd/basecoin See the [install guide](/docs/guide/install.md) for more details. +## API +* [Baseserver](/examples/basecoin/cmd/baseserver/README.md) +* [Basecli](/examples/basecoin/cmd/basecli/README.md) + ## Guides * Getting started with the [Basecoin basics](/docs/guide/basecoin-basics.md) From 40d78a1874547dca4f3998c4e8ec54e81f9ac8c4 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sun, 26 Nov 2017 04:16:22 +0000 Subject: [PATCH 084/117] bash test fix for binary merge --- tests/cli/common.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/cli/common.sh b/tests/cli/common.sh index 3605d81e999b..8675cb7802d7 100644 --- a/tests/cli/common.sh +++ b/tests/cli/common.sh @@ -15,10 +15,10 @@ quickSetup() { BASE_DIR=$HOME/$1 CHAIN_ID=$2 - # TODO Make this more robust + # TODO Make this more robust if [ "$BASE_DIR" == "$HOME/" ]; then - echo "quickSetup() must be called with argument, or it will wipe your home directory" - exit 1 + echo "quickSetup() must be called with argument, or it will wipe your home directory" + exit 1 fi rm -rf $BASE_DIR 2>/dev/null @@ -68,7 +68,7 @@ initServer() { SERVE_DIR=$1/server assertNotNull "line=${LINENO}, no chain" $2 CHAIN=$2 - SERVER_LOG=$1/${SERVER_EXE}.log + SERVER_LOG=$1/node.log GENKEY=$(${CLIENT_EXE} keys get ${RICH} | awk '{print $2}') ${SERVER_EXE} init --static --chain-id $CHAIN $GENKEY --home=$SERVE_DIR >>$SERVER_LOG From 703a95b4e47d89a7beb50057a12df8e6b094055f Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 5 Dec 2017 20:57:04 +0000 Subject: [PATCH 085/117] tick endblock tick to endblock --- app/base.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/base.go b/app/base.go index e45d3a11d6cc..4f872b4e4def 100644 --- a/app/base.go +++ b/app/base.go @@ -70,8 +70,13 @@ func (app *BaseApp) CheckTx(txBytes []byte) abci.ResponseCheckTx { return res.ToABCI() } -// BeginBlock - ABCI - triggers Tick actions -func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { +// BeginBlock - ABCI +func (app *BaseApp) BeginBlock(_ abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { + return +} + +// EndBlock - ABCI - triggers Tick actions +func (app *BaseApp) EndBlock(_ abci.RequestEndBlock) (res abci.ResponseEndBlock) { // execute tick if present if app.clock != nil { ctx := stack.NewContext( From bd8207976d1fb6ea28565543e08efdee5ebc315b Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 6 Dec 2017 00:23:24 +0000 Subject: [PATCH 086/117] hid update --- glide.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glide.lock b/glide.lock index e65ce91197ef..a629377600d7 100644 --- a/glide.lock +++ b/glide.lock @@ -12,7 +12,7 @@ imports: - name: github.com/ebuchman/fail-test version: 95f809107225be108efcf10a3509e4ea6ceef3c4 - name: github.com/ethanfrey/hid - version: f76da0b80567e8b6f676e1757b549a93494fe4b5 + version: dce75af84cf849c60f39bf1b8192fb5cd597b5d9 - name: github.com/ethanfrey/ledger version: f7f2f056357db77db845a79aa1abdadc3ae66369 - name: github.com/fsnotify/fsnotify From 9120ad8ea48c0f3a3e3cd7f43e2f87fdd5cf22cc Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 6 Dec 2017 00:41:58 +0000 Subject: [PATCH 087/117] fix val_test --- app/base.go | 8 +++----- app/store.go | 5 ++++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/base.go b/app/base.go index 4f872b4e4def..05a13e9ea6fb 100644 --- a/app/base.go +++ b/app/base.go @@ -71,12 +71,10 @@ func (app *BaseApp) CheckTx(txBytes []byte) abci.ResponseCheckTx { } // BeginBlock - ABCI -func (app *BaseApp) BeginBlock(_ abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { - return -} +func (app *BaseApp) BeginBlock(_ abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { return } // EndBlock - ABCI - triggers Tick actions -func (app *BaseApp) EndBlock(_ abci.RequestEndBlock) (res abci.ResponseEndBlock) { +func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) { // execute tick if present if app.clock != nil { ctx := stack.NewContext( @@ -91,7 +89,7 @@ func (app *BaseApp) EndBlock(_ abci.RequestEndBlock) (res abci.ResponseEndBlock) } app.AddValChange(diff) } - return res + return app.StoreApp.EndBlock(req) } // InitState - used to setup state (was SetOption) diff --git a/app/store.go b/app/store.go index 05fb43c59048..ed4af7a9fa76 100644 --- a/app/store.go +++ b/app/store.go @@ -42,6 +42,9 @@ type StoreApp struct { logger log.Logger } +// TODO should satisfy? +//var _ abci.Application = &StoreApp{} + // 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, DefaultHistorySize) @@ -205,7 +208,7 @@ func (app *StoreApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInit } // BeginBlock - ABCI -func (app *StoreApp) BeginBlock(req abci.RequestBeginBlock) {} +func (app *StoreApp) BeginBlock(_ abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { return } // EndBlock - ABCI // Returns a list of all validator changes made in this block From 23e464d3c8cf0e563b0da2062682a41ff58aa183 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 6 Dec 2017 18:34:31 +0100 Subject: [PATCH 088/117] add recover and persist endpoint to --- client/rest/handlers.go | 21 +++++++++++++++++++++ client/rest/types.go | 1 + 2 files changed, 22 insertions(+) diff --git a/client/rest/handlers.go b/client/rest/handlers.go index 330e82e2c93a..0b847165a6ef 100644 --- a/client/rest/handlers.go +++ b/client/rest/handlers.go @@ -126,6 +126,25 @@ func (k *Keys) DeleteKey(w http.ResponseWriter, r *http.Request) { common.WriteSuccess(w, resp) } +func (k *Keys) RecoverKey(w http.ResponseWriter, r *http.Request) { + ckReq := &RecoverKeyRequest{ + Algo: k.algo, + } + if err := common.ParseRequestAndValidateJSON(r, ckReq); err != nil { + common.WriteError(w, err) + return + } + + key, err := k.manager.Recover(ckReq.Name, ckReq.Passphrase, ckReq.Seed) + if err != nil { + common.WriteError(w, err) + return + } + + res := &CreateKeyResponse{Key: key, Seed: ckReq.Seed} + common.WriteSuccess(w, res) +} + func doPostTx(w http.ResponseWriter, r *http.Request) { tx := new(sdk.Tx) if err := common.ParseRequestAndValidateJSON(r, tx); err != nil { @@ -168,12 +187,14 @@ func RegisterPostTx(r *mux.Router) error { // RegisterAllCRUD is a convenience method to register all // CRUD for keys to allow access by methods and routes: // POST: /keys +// POST: /keys/recover // GET: /keys // GET: /keys/{name} // POST, PUT: /keys/{name} // DELETE: /keys/{name} func (k *Keys) RegisterAllCRUD(r *mux.Router) error { r.HandleFunc("/keys", k.GenerateKey).Methods("POST") + r.HandleFunc("/keys/recover", k.RecoverKey).Methods("POST") r.HandleFunc("/keys", k.ListKeys).Methods("GET") r.HandleFunc("/keys/{name}", k.GetKey).Methods("GET") r.HandleFunc("/keys/{name}", k.UpdateKey).Methods("POST", "PUT") diff --git a/client/rest/types.go b/client/rest/types.go index 3ae0252ca6d5..91ffe52b3ebc 100644 --- a/client/rest/types.go +++ b/client/rest/types.go @@ -9,6 +9,7 @@ import ( type CreateKeyRequest struct { Name string `json:"name,omitempty" validate:"required,min=3,printascii"` Passphrase string `json:"password,omitempty" validate:"required,min=10"` + Seed string `json:"seed_phrase,omitempty" validate:"min=23"` // Algo is the requested algorithm to create the key Algo string `json:"algo,omitempty"` From 3986e186e1dda1244cffbf5ba24726c07de24263 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 6 Dec 2017 19:06:12 +0100 Subject: [PATCH 089/117] fixed bug and implemented feedback --- client/rest/handlers.go | 10 +++++----- client/rest/types.go | 10 +++++++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/client/rest/handlers.go b/client/rest/handlers.go index 0b847165a6ef..99127f1c96b6 100644 --- a/client/rest/handlers.go +++ b/client/rest/handlers.go @@ -127,21 +127,21 @@ func (k *Keys) DeleteKey(w http.ResponseWriter, r *http.Request) { } func (k *Keys) RecoverKey(w http.ResponseWriter, r *http.Request) { - ckReq := &RecoverKeyRequest{ + rkReq := &RecoverKeyRequest{ Algo: k.algo, } - if err := common.ParseRequestAndValidateJSON(r, ckReq); err != nil { + if err := common.ParseRequestAndValidateJSON(r, rkReq); err != nil { common.WriteError(w, err) return } - key, err := k.manager.Recover(ckReq.Name, ckReq.Passphrase, ckReq.Seed) + key, err := k.manager.Recover(rkReq.Name, rkReq.Passphrase, rkReq.Seed) if err != nil { common.WriteError(w, err) return } - res := &CreateKeyResponse{Key: key, Seed: ckReq.Seed} + res := &CreateKeyResponse{Key: key, Seed: rkReq.Seed} common.WriteSuccess(w, res) } @@ -187,7 +187,7 @@ func RegisterPostTx(r *mux.Router) error { // RegisterAllCRUD is a convenience method to register all // CRUD for keys to allow access by methods and routes: // POST: /keys -// POST: /keys/recover +// POST: /keys/recover // GET: /keys // GET: /keys/{name} // POST, PUT: /keys/{name} diff --git a/client/rest/types.go b/client/rest/types.go index 91ffe52b3ebc..529fcbe20962 100644 --- a/client/rest/types.go +++ b/client/rest/types.go @@ -9,7 +9,6 @@ import ( type CreateKeyRequest struct { Name string `json:"name,omitempty" validate:"required,min=3,printascii"` Passphrase string `json:"password,omitempty" validate:"required,min=10"` - Seed string `json:"seed_phrase,omitempty" validate:"min=23"` // Algo is the requested algorithm to create the key Algo string `json:"algo,omitempty"` @@ -26,6 +25,15 @@ type UpdateKeyRequest struct { NewPass string `json:"new_passphrase,omitempty" validate:"required,min=10"` } +type RecoverKeyRequest struct { + Name string `json:"name,omitempty" validate:"required,min=3,printascii"` + Passphrase string `json:"password,omitempty" validate:"required,min=10"` + Seed string `json:"seed_phrase,omitempty" validate:"required,min=23"` + + // Algo is the requested algorithm to create the key + Algo string `json:"algo,omitempty"` +} + type SignRequest struct { Name string `json:"name,omitempty" validate:"required,min=3,printascii"` Password string `json:"password,omitempty" validate:"required,min=10"` From 26eab9951a4744ab1e21111437f8a93381bcf56b Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 6 Dec 2017 23:35:04 -0500 Subject: [PATCH 090/117] refactor client/rest --- client/commands/keys/new.go | 2 +- client/rest/handlers.go | 213 ----------------------- client/rest/helpers.go | 29 --- client/rest/keys.go | 190 ++++++++++++++++++++ client/rest/txs.go | 54 ++++++ client/rest/types.go | 64 +++---- examples/basecoin/cmd/baseserver/main.go | 12 +- 7 files changed, 287 insertions(+), 277 deletions(-) delete mode 100644 client/rest/handlers.go delete mode 100644 client/rest/helpers.go create mode 100644 client/rest/keys.go create mode 100644 client/rest/txs.go diff --git a/client/commands/keys/new.go b/client/commands/keys/new.go index f1f422a20aaf..46f967a5692a 100644 --- a/client/commands/keys/new.go +++ b/client/commands/keys/new.go @@ -36,7 +36,7 @@ var newCmd = &cobra.Command{ Use: "new [name]", Short: "Create a new public/private key pair", Long: `Add a public/private key pair to the key store. -The password muts be entered in the terminal and not +The password must be entered in the terminal and not passed as a command line argument for security.`, RunE: runNewCmd, } diff --git a/client/rest/handlers.go b/client/rest/handlers.go deleted file mode 100644 index 99127f1c96b6..000000000000 --- a/client/rest/handlers.go +++ /dev/null @@ -1,213 +0,0 @@ -package rest - -import ( - "net/http" - - "github.com/gorilla/mux" - "github.com/pkg/errors" - - keys "github.com/tendermint/go-crypto/keys" - "github.com/tendermint/tmlibs/common" - - sdk "github.com/cosmos/cosmos-sdk" - keycmd "github.com/cosmos/cosmos-sdk/client/commands/keys" -) - -type Keys struct { - algo string - manager keys.Manager -} - -func DefaultKeysManager() keys.Manager { - return keycmd.GetKeyManager() -} - -func NewDefaultKeysManager(algo string) *Keys { - return New(DefaultKeysManager(), algo) -} - -func New(manager keys.Manager, algo string) *Keys { - return &Keys{ - algo: algo, - manager: manager, - } -} - -func (k *Keys) GenerateKey(w http.ResponseWriter, r *http.Request) { - ckReq := &CreateKeyRequest{ - Algo: k.algo, - } - if err := common.ParseRequestAndValidateJSON(r, ckReq); err != nil { - common.WriteError(w, err) - return - } - - key, seed, err := k.manager.Create(ckReq.Name, ckReq.Passphrase, ckReq.Algo) - if err != nil { - common.WriteError(w, err) - return - } - - res := &CreateKeyResponse{Key: key, Seed: seed} - common.WriteSuccess(w, res) -} - -func (k *Keys) GetKey(w http.ResponseWriter, r *http.Request) { - query := mux.Vars(r) - name := query["name"] - key, err := k.manager.Get(name) - if err != nil { - common.WriteError(w, err) - return - } - common.WriteSuccess(w, &key) -} - -func (k *Keys) ListKeys(w http.ResponseWriter, r *http.Request) { - keys, err := k.manager.List() - if err != nil { - common.WriteError(w, err) - return - } - common.WriteSuccess(w, keys) -} - -var ( - errNonMatchingPathAndJSONKeyNames = errors.New("path and json key names don't match") -) - -func (k *Keys) UpdateKey(w http.ResponseWriter, r *http.Request) { - uReq := new(UpdateKeyRequest) - if err := common.ParseRequestAndValidateJSON(r, uReq); err != nil { - common.WriteError(w, err) - return - } - - query := mux.Vars(r) - name := query["name"] - if name != uReq.Name { - common.WriteError(w, errNonMatchingPathAndJSONKeyNames) - return - } - - if err := k.manager.Update(uReq.Name, uReq.OldPass, uReq.NewPass); err != nil { - common.WriteError(w, err) - return - } - - key, err := k.manager.Get(uReq.Name) - if err != nil { - common.WriteError(w, err) - return - } - common.WriteSuccess(w, &key) -} - -func (k *Keys) DeleteKey(w http.ResponseWriter, r *http.Request) { - dReq := new(DeleteKeyRequest) - if err := common.ParseRequestAndValidateJSON(r, dReq); err != nil { - common.WriteError(w, err) - return - } - - query := mux.Vars(r) - name := query["name"] - if name != dReq.Name { - common.WriteError(w, errNonMatchingPathAndJSONKeyNames) - return - } - - if err := k.manager.Delete(dReq.Name, dReq.Passphrase); err != nil { - common.WriteError(w, err) - return - } - - resp := &common.ErrorResponse{Success: true} - common.WriteSuccess(w, resp) -} - -func (k *Keys) RecoverKey(w http.ResponseWriter, r *http.Request) { - rkReq := &RecoverKeyRequest{ - Algo: k.algo, - } - if err := common.ParseRequestAndValidateJSON(r, rkReq); err != nil { - common.WriteError(w, err) - return - } - - key, err := k.manager.Recover(rkReq.Name, rkReq.Passphrase, rkReq.Seed) - if err != nil { - common.WriteError(w, err) - return - } - - res := &CreateKeyResponse{Key: key, Seed: rkReq.Seed} - common.WriteSuccess(w, res) -} - -func doPostTx(w http.ResponseWriter, r *http.Request) { - tx := new(sdk.Tx) - if err := common.ParseRequestAndValidateJSON(r, tx); err != nil { - common.WriteError(w, err) - return - } - commit, err := PostTx(*tx) - if err != nil { - common.WriteError(w, err) - return - } - - common.WriteSuccess(w, commit) -} - -func doSign(w http.ResponseWriter, r *http.Request) { - sr := new(SignRequest) - if err := common.ParseRequestAndValidateJSON(r, sr); err != nil { - common.WriteError(w, err) - return - } - - tx := sr.Tx - if err := SignTx(sr.Name, sr.Password, tx); err != nil { - common.WriteError(w, err) - return - } - common.WriteSuccess(w, tx) -} - -// mux.Router registrars - -// RegisterPostTx is a mux.Router handler that exposes POST -// method access to post a transaction to the blockchain. -func RegisterPostTx(r *mux.Router) error { - r.HandleFunc("/tx", doPostTx).Methods("POST") - return nil -} - -// RegisterAllCRUD is a convenience method to register all -// CRUD for keys to allow access by methods and routes: -// POST: /keys -// POST: /keys/recover -// GET: /keys -// GET: /keys/{name} -// POST, PUT: /keys/{name} -// DELETE: /keys/{name} -func (k *Keys) RegisterAllCRUD(r *mux.Router) error { - r.HandleFunc("/keys", k.GenerateKey).Methods("POST") - r.HandleFunc("/keys/recover", k.RecoverKey).Methods("POST") - r.HandleFunc("/keys", k.ListKeys).Methods("GET") - r.HandleFunc("/keys/{name}", k.GetKey).Methods("GET") - r.HandleFunc("/keys/{name}", k.UpdateKey).Methods("POST", "PUT") - r.HandleFunc("/keys/{name}", k.DeleteKey).Methods("DELETE") - - return nil -} - -// RegisterSignTx is a mux.Router handler that -// exposes POST method access to sign a transaction. -func RegisterSignTx(r *mux.Router) error { - r.HandleFunc("/sign", doSign).Methods("POST") - return nil -} - -// End of mux.Router registrars diff --git a/client/rest/helpers.go b/client/rest/helpers.go deleted file mode 100644 index 5085135e848a..000000000000 --- a/client/rest/helpers.go +++ /dev/null @@ -1,29 +0,0 @@ -package rest - -import ( - "github.com/tendermint/go-crypto/keys" - wire "github.com/tendermint/go-wire" - - ctypes "github.com/tendermint/tendermint/rpc/core/types" - - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/client/commands" - keycmd "github.com/cosmos/cosmos-sdk/client/commands/keys" -) - -// PostTx is same as a tx -func PostTx(tx sdk.Tx) (*ctypes.ResultBroadcastTxCommit, error) { - packet := wire.BinaryBytes(tx) - // post the bytes - node := commands.GetNode() - return node.BroadcastTxCommit(packet) -} - -// SignTx will modify the tx in-place, adding a signature if possible -func SignTx(name, pass string, tx sdk.Tx) error { - if sign, ok := tx.Unwrap().(keys.Signable); ok { - manager := keycmd.GetKeyManager() - return manager.Sign(name, pass, sign) - } - return nil -} diff --git a/client/rest/keys.go b/client/rest/keys.go new file mode 100644 index 000000000000..4457b44c430c --- /dev/null +++ b/client/rest/keys.go @@ -0,0 +1,190 @@ +package rest + +import ( + "net/http" + + "github.com/gorilla/mux" + "github.com/pkg/errors" + + keys "github.com/tendermint/go-crypto/keys" + "github.com/tendermint/tmlibs/common" +) + +const ( + defaultAlgo = "ed25519" // TODO: allow this to come in via requests +) + +var ( + errNonMatchingPathAndJSONKeyNames = errors.New("path and json key names don't match") +) + +// ServiceKeys exposes a REST API service for +// managing keys and signing transactions +type ServiceKeys struct { + manager keys.Manager +} + +// New returns a new instance of the keys service +func NewServiceKeys(manager keys.Manager) *ServiceKeys { + return &ServiceKeys{ + manager: manager, // XXX keycmd.GetKeyManager() + } +} + +func (s *ServiceKeys) Create(w http.ResponseWriter, r *http.Request) { + req := &RequestCreate{ + Algo: defaultAlgo, + } + if err := common.ParseRequestAndValidateJSON(r, req); err != nil { + common.WriteError(w, err) + return + } + + key, seed, err := s.manager.Create(req.Name, req.Passphrase, req.Algo) + if err != nil { + common.WriteError(w, err) + return + } + + res := &ResponseCreate{Key: key, Seed: seed} + common.WriteSuccess(w, res) +} + +func (s *ServiceKeys) Get(w http.ResponseWriter, r *http.Request) { + query := mux.Vars(r) + name := query["name"] + key, err := s.manager.Get(name) + if err != nil { + common.WriteError(w, err) + return + } + common.WriteSuccess(w, &key) +} + +func (s *ServiceKeys) List(w http.ResponseWriter, r *http.Request) { + keys, err := s.manager.List() + if err != nil { + common.WriteError(w, err) + return + } + common.WriteSuccess(w, keys) +} + +func (s *ServiceKeys) Update(w http.ResponseWriter, r *http.Request) { + req := new(RequestUpdate) + if err := common.ParseRequestAndValidateJSON(r, req); err != nil { + common.WriteError(w, err) + return + } + + query := mux.Vars(r) + name := query["name"] + if name != req.Name { + common.WriteError(w, errNonMatchingPathAndJSONKeyNames) + return + } + + if err := s.manager.Update(req.Name, req.OldPass, req.NewPass); err != nil { + common.WriteError(w, err) + return + } + + key, err := s.manager.Get(req.Name) + if err != nil { + common.WriteError(w, err) + return + } + common.WriteSuccess(w, &key) +} + +func (s *ServiceKeys) Delete(w http.ResponseWriter, r *http.Request) { + req := new(RequestDelete) + if err := common.ParseRequestAndValidateJSON(r, req); err != nil { + common.WriteError(w, err) + return + } + + query := mux.Vars(r) + name := query["name"] + if name != req.Name { + common.WriteError(w, errNonMatchingPathAndJSONKeyNames) + return + } + + if err := s.manager.Delete(req.Name, req.Passphrase); err != nil { + common.WriteError(w, err) + return + } + + resp := &common.ErrorResponse{Success: true} + common.WriteSuccess(w, resp) +} + +func (s *ServiceKeys) Recover(w http.ResponseWriter, r *http.Request) { + req := &RequestRecover{ + Algo: defaultAlgo, + } + if err := common.ParseRequestAndValidateJSON(r, req); err != nil { + common.WriteError(w, err) + return + } + + key, err := s.manager.Recover(req.Name, req.Passphrase, req.Seed) + if err != nil { + common.WriteError(w, err) + return + } + + res := &ResponseRecover{Key: key} + common.WriteSuccess(w, res) +} + +func (s *ServiceKeys) SignTx(w http.ResponseWriter, r *http.Request) { + req := new(RequestSign) + if err := common.ParseRequestAndValidateJSON(r, req); err != nil { + common.WriteError(w, err) + return + } + + tx := req.Tx + + var err error + if sign, ok := tx.Unwrap().(keys.Signable); ok { + err = s.manager.Sign(req.Name, req.Password, sign) + } + if err != nil { + common.WriteError(w, err) + return + } + common.WriteSuccess(w, tx) +} + +// mux.Router registrars + +// RegisterCRUD is a convenience method to register all +// CRUD for keys to allow access by methods and routes: +// POST: /keys +// POST: /keys/recover +// GET: /keys +// GET: /keys/{name} +// POST, PUT: /keys/{name} +// DELETE: /keys/{name} +func (s *ServiceKeys) RegisterCRUD(r *mux.Router) error { + r.HandleFunc("/keys", s.Create).Methods("POST") + r.HandleFunc("/keys/recover", s.Recover).Methods("POST") + r.HandleFunc("/keys", s.List).Methods("GET") + r.HandleFunc("/keys/{name}", s.Get).Methods("GET") + r.HandleFunc("/keys/{name}", s.Update).Methods("POST", "PUT") + r.HandleFunc("/keys/{name}", s.Delete).Methods("DELETE") + + return nil +} + +// RegisterSignTx is a mux.Router handler that +// exposes POST method access to sign a transaction. +func (s *ServiceKeys) RegisterSignTx(r *mux.Router) error { + r.HandleFunc("/sign", s.SignTx).Methods("POST") + return nil +} + +// End of mux.Router registrars diff --git a/client/rest/txs.go b/client/rest/txs.go new file mode 100644 index 000000000000..65da4da4b29b --- /dev/null +++ b/client/rest/txs.go @@ -0,0 +1,54 @@ +package rest + +import ( + "net/http" + + "github.com/gorilla/mux" + + wire "github.com/tendermint/go-wire" + "github.com/tendermint/tmlibs/common" + + sdk "github.com/cosmos/cosmos-sdk" + + rpcclient "github.com/tendermint/tendermint/rpc/client" +) + +// ServiceTxs exposes a REST API service for sendings txs. +// It wraps a Tendermint RPC client. +type ServiceTxs struct { + node rpcclient.Client +} + +func NewServiceTxs(c rpcclient.Client) *ServiceTxs { + return &ServiceTxs{ + node: c, + } +} + +func (s *ServiceTxs) PostTx(w http.ResponseWriter, r *http.Request) { + tx := new(sdk.Tx) + if err := common.ParseRequestAndValidateJSON(r, tx); err != nil { + common.WriteError(w, err) + return + } + + packet := wire.BinaryBytes(*tx) + commit, err := s.node.BroadcastTxCommit(packet) + if err != nil { + common.WriteError(w, err) + return + } + + common.WriteSuccess(w, commit) +} + +// mux.Router registrars + +// RegisterPostTx is a mux.Router handler that exposes POST +// method access to post a transaction to the blockchain. +func (s *ServiceTxs) RegisterPostTx(r *mux.Router) error { + r.HandleFunc("/tx", s.PostTx).Methods("POST") + return nil +} + +// End of mux.Router registrars diff --git a/client/rest/types.go b/client/rest/types.go index 529fcbe20962..a43097bbf8cc 100644 --- a/client/rest/types.go +++ b/client/rest/types.go @@ -1,12 +1,14 @@ package rest import ( - sdk "github.com/cosmos/cosmos-sdk" - "github.com/cosmos/cosmos-sdk/modules/coin" "github.com/tendermint/go-crypto/keys" + + sdk "github.com/cosmos/cosmos-sdk" ) -type CreateKeyRequest struct { +// TODO: consistency between Passphrase and Password !!! + +type RequestCreate struct { Name string `json:"name,omitempty" validate:"required,min=3,printascii"` Passphrase string `json:"password,omitempty" validate:"required,min=10"` @@ -14,48 +16,48 @@ type CreateKeyRequest struct { Algo string `json:"algo,omitempty"` } -type DeleteKeyRequest struct { +type ResponseCreate struct { + Key keys.Info `json:"key,omitempty"` + Seed string `json:"seed_phrase,omitempty"` +} + +//----------------------------------------------------------------------- + +type RequestRecover struct { Name string `json:"name,omitempty" validate:"required,min=3,printascii"` Passphrase string `json:"password,omitempty" validate:"required,min=10"` + Seed string `json:"seed_phrase,omitempty" validate:"required,min=23"` + + // Algo is the requested algorithm to create the key + Algo string `json:"algo,omitempty"` } -type UpdateKeyRequest struct { - Name string `json:"name,omitempty" validate:"required,min=3,printascii"` - OldPass string `json:"password,omitempty" validate:"required,min=10"` - NewPass string `json:"new_passphrase,omitempty" validate:"required,min=10"` +type ResponseRecover struct { + Key keys.Info `json:"key,omitempty"` } -type RecoverKeyRequest struct { +//----------------------------------------------------------------------- + +type RequestDelete struct { Name string `json:"name,omitempty" validate:"required,min=3,printascii"` Passphrase string `json:"password,omitempty" validate:"required,min=10"` - Seed string `json:"seed_phrase,omitempty" validate:"required,min=23"` +} - // Algo is the requested algorithm to create the key - Algo string `json:"algo,omitempty"` +//----------------------------------------------------------------------- + +type RequestUpdate struct { + Name string `json:"name,omitempty" validate:"required,min=3,printascii"` + OldPass string `json:"password,omitempty" validate:"required,min=10"` + NewPass string `json:"new_passphrase,omitempty" validate:"required,min=10"` } -type SignRequest struct { +//----------------------------------------------------------------------- + +type RequestSign struct { Name string `json:"name,omitempty" validate:"required,min=3,printascii"` Password string `json:"password,omitempty" validate:"required,min=10"` Tx sdk.Tx `json:"tx" validate:"required"` } -type CreateKeyResponse struct { - Key keys.Info `json:"key,omitempty"` - Seed string `json:"seed_phrase,omitempty"` -} - -// SendInput is the request to send an amount from one actor to another. -// Note: Not using the `validator:""` tags here because SendInput has -// many fields so it would be nice to figure out all the invalid -// inputs and report them back to the caller, in one shot. -type SendInput struct { - Fees *coin.Coin `json:"fees"` - Multi bool `json:"multi,omitempty"` - Sequence uint32 `json:"sequence"` - - To *sdk.Actor `json:"to"` - From *sdk.Actor `json:"from"` - Amount coin.Coins `json:"amount"` -} +//----------------------------------------------------------------------- diff --git a/examples/basecoin/cmd/baseserver/main.go b/examples/basecoin/cmd/baseserver/main.go index c4b4c2a8692a..70dc7f992873 100644 --- a/examples/basecoin/cmd/baseserver/main.go +++ b/examples/basecoin/cmd/baseserver/main.go @@ -10,6 +10,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/commands" rest "github.com/cosmos/cosmos-sdk/client/rest" coinrest "github.com/cosmos/cosmos-sdk/modules/coin/rest" @@ -43,9 +44,14 @@ func init() { func serve(cmd *cobra.Command, args []string) error { router := mux.NewRouter() + rootDir := viper.GetString(cli.HomeFlag) + keyMan := client.GetKeyManager(rootDir) + serviceKeys := rest.NewServiceKeys(keyMan) + serviceTxs := rest.NewServiceTxs(commands.GetNode()) + routeRegistrars := []func(*mux.Router) error{ // rest.Keys handlers - rest.NewDefaultKeysManager(defaultAlgo).RegisterAllCRUD, + serviceKeys.RegisterCRUD, // Coin send handler coinrest.RegisterAll, @@ -54,9 +60,9 @@ func serve(cmd *cobra.Command, args []string) error { rolerest.RegisterCreateRole, // Basecoin sign transactions handler - rest.RegisterSignTx, + serviceKeys.RegisterSignTx, // Basecoin post transaction handler - rest.RegisterPostTx, + serviceTxs.RegisterPostTx, // Nonce query handler noncerest.RegisterQueryNonce, From bbcb838bfef0dfb110d460f0df5a2b63144bb9b2 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 7 Dec 2017 01:13:53 -0500 Subject: [PATCH 091/117] client/rest: add a test --- client/rest/keys_test.go | 114 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 client/rest/keys_test.go diff --git a/client/rest/keys_test.go b/client/rest/keys_test.go new file mode 100644 index 000000000000..eeb5f99f9410 --- /dev/null +++ b/client/rest/keys_test.go @@ -0,0 +1,114 @@ +package rest + +import ( + "bytes" + "encoding/json" + "io/ioutil" + "net/http" + "net/http/httptest" + "testing" + + "github.com/gorilla/mux" + "github.com/stretchr/testify/assert" + "github.com/tendermint/go-crypto/keys" + "github.com/tendermint/go-crypto/keys/cryptostore" + "github.com/tendermint/go-crypto/keys/storage/memstorage" +) + +func getKeyManager() keys.Manager { + return cryptostore.New( + cryptostore.SecretBox, + memstorage.New(), + keys.MustLoadCodec("english"), + ) +} + +func equalKeys(t *testing.T, k1, k2 keys.Info, name bool) { + assert.Equal(t, k1.Address, k2.Address) + assert.Equal(t, k1.PubKey, k2.PubKey) +} + +func TestKeysCreateGetRecover(t *testing.T) { + keyMan := getKeyManager() + serviceKeys := NewServiceKeys(keyMan) + + r := mux.NewRouter() + err := serviceKeys.RegisterCRUD(r) + assert.Nil(t, err) + + ts := httptest.NewServer(r) + defer ts.Close() + + var ( + keyInfo keys.Info + + passPhrase string = "abcdefghijklmno" + seedPhrase string + ) + keyInfo.Name = "mykey" + + // create the key + { + reqCreate := RequestCreate{ + Name: keyInfo.Name, + Passphrase: passPhrase, + Algo: defaultAlgo, + } + b, err := json.Marshal(reqCreate) + assert.Nil(t, err) + + resp, err := http.Post(ts.URL+"/keys", "json", bytes.NewBuffer(b)) + assert.Nil(t, err) + assert.Equal(t, resp.StatusCode, 200) + + var resCreate ResponseCreate + body, err := ioutil.ReadAll(resp.Body) + assert.Nil(t, err) + err = json.Unmarshal(body, &resCreate) + assert.Nil(t, err) + + assert.Equal(t, keyInfo.Name, resCreate.Key.Name) + keyInfo = resCreate.Key + seedPhrase = resCreate.Seed + } + + // get the key and confirm it matches + { + resp, err := http.Get(ts.URL + "/keys/" + keyInfo.Name) + assert.Nil(t, err) + assert.Equal(t, resp.StatusCode, 200) + + var resKeyInfo keys.Info + body, err := ioutil.ReadAll(resp.Body) + assert.Nil(t, err) + err = json.Unmarshal(body, &resKeyInfo) + assert.Nil(t, err) + + equalKeys(t, keyInfo, resKeyInfo, true) + } + + // recover the key and confirm it matches + { + + reqRecover := RequestRecover{ + Name: "newName", + Passphrase: passPhrase, + Seed: seedPhrase, + Algo: defaultAlgo, + } + b, err := json.Marshal(reqRecover) + assert.Nil(t, err) + + resp, err := http.Post(ts.URL+"/keys/recover", "json", bytes.NewBuffer(b)) + assert.Nil(t, err) + assert.Equal(t, resp.StatusCode, 200) + + var resRecover ResponseRecover + body, err := ioutil.ReadAll(resp.Body) + assert.Nil(t, err) + err = json.Unmarshal(body, &resRecover) + assert.Nil(t, err) + + equalKeys(t, keyInfo, resRecover.Key, false) + } +} From 408842461e2cfa900a0fd32f054f6a72de0615aa Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 8 Dec 2017 18:49:32 -0500 Subject: [PATCH 092/117] wip --- client/query.go | 16 ++++++++------- errors/common.go | 8 -------- errors/main.go | 16 +++++++-------- examples/basecoin/cmd/baseserver/main.go | 14 ++++++++++++- glide.lock | 26 ++++++++++++++++-------- glide.yaml | 4 ++-- 6 files changed, 49 insertions(+), 35 deletions(-) diff --git a/client/query.go b/client/query.go index 8be143dd2945..62ea8635bc83 100644 --- a/client/query.go +++ b/client/query.go @@ -28,11 +28,12 @@ func GetWithProof(key []byte, reqHeight int, node rpcclient.Client, return } - resp, proof, err := GetWithProofOptions("/key", key, - rpcclient.ABCIQueryOptions{Height: uint64(reqHeight)}, + _resp, proof, err := GetWithProofOptions("/key", key, + rpcclient.ABCIQueryOptions{Height: int64(reqHeight)}, node, cert) - if resp != nil { - val, height = resp.Value, resp.Height + if _resp != nil { + resp := _resp.Response + val, height = resp.Value, uint64(resp.Height) } return val, height, proof, err } @@ -42,14 +43,15 @@ func GetWithProofOptions(path string, key []byte, opts rpcclient.ABCIQueryOption node rpcclient.Client, cert lite.Certifier) ( *ctypes.ResultABCIQuery, iavl.KeyProof, error) { - resp, err := node.ABCIQueryWithOptions(path, key, opts) + _resp, err := node.ABCIQueryWithOptions(path, key, opts) if err != nil { return nil, nil, err } + resp := _resp.Response // make sure the proof is the proper height - if !resp.Code.IsOK() { - err = errors.Errorf("Query error %d: %s", resp.Code, resp.Code.String()) + if resp.IsErr() { + err = errors.Errorf("Query error %d: %d", resp.Code) return nil, nil, err } if len(resp.Key) == 0 || len(resp.Proof) == 0 { diff --git a/errors/common.go b/errors/common.go index 64d45c082079..c8854f12207f 100644 --- a/errors/common.go +++ b/errors/common.go @@ -4,8 +4,6 @@ package errors import ( "fmt" "reflect" - - abci "github.com/tendermint/abci/types" ) var ( @@ -17,12 +15,6 @@ var ( errInvalidFormat = fmt.Errorf("Invalid format") errUnknownModule = fmt.Errorf("Unknown module") errUnknownKey = fmt.Errorf("Unknown key") - - internalErr = abci.CodeType_InternalError - encodingErr = abci.CodeType_EncodingError - unauthorized = abci.CodeType_Unauthorized - unknownRequest = abci.CodeType_UnknownRequest - unknownAddress = abci.CodeType_BaseUnknownAddress ) // some crazy reflection to unwrap any generated struct. diff --git a/errors/main.go b/errors/main.go index 073aa944f084..9cfbe61978dc 100644 --- a/errors/main.go +++ b/errors/main.go @@ -8,8 +8,6 @@ import ( abci "github.com/tendermint/abci/types" ) -const defaultErrCode = abci.CodeType_InternalError - type stackTracer interface { error StackTrace() errors.StackTrace @@ -22,13 +20,13 @@ type causer interface { // TMError is the tendermint abci return type with stack trace type TMError interface { stackTracer - ErrorCode() abci.CodeType + ErrorCode() uint32 Message() string } type tmerror struct { stackTracer - code abci.CodeType + code uint32 msg string } @@ -37,7 +35,7 @@ var ( _ error = tmerror{} ) -func (t tmerror) ErrorCode() abci.CodeType { +func (t tmerror) ErrorCode() uint32 { return t.code } @@ -102,7 +100,7 @@ func Wrap(err error) TMError { // WithCode adds a stacktrace if necessary and sets the code and msg, // overriding the state if err was already TMError -func WithCode(err error, code abci.CodeType) TMError { +func WithCode(err error, code uint32) TMError { // add a stack only if not present st, ok := err.(stackTracer) if !ok { @@ -118,14 +116,14 @@ func WithCode(err error, code abci.CodeType) TMError { // WithMessage prepends some text to the error, then calls WithCode // It wraps the original error, so IsSameError will still match on err -func WithMessage(prefix string, err error, code abci.CodeType) TMError { +func WithMessage(prefix string, err error, code uint32) TMError { e2 := errors.WithMessage(err, prefix) return WithCode(e2, code) } // New adds a stacktrace if necessary and sets the code and msg, // overriding the state if err was already TMError -func New(msg string, code abci.CodeType) TMError { +func New(msg string, code uint32) TMError { // create a new error with stack trace and attach a code st := errors.New(msg).(stackTracer) return tmerror{ @@ -143,7 +141,7 @@ func IsSameError(pattern error, err error) bool { } // HasErrorCode checks if this error would return the named error code -func HasErrorCode(err error, code abci.CodeType) bool { +func HasErrorCode(err error, code uint32) bool { if tm, ok := err.(TMError); ok { return tm.ErrorCode() == code } diff --git a/examples/basecoin/cmd/baseserver/main.go b/examples/basecoin/cmd/baseserver/main.go index 70dc7f992873..d41ac45a6de6 100644 --- a/examples/basecoin/cmd/baseserver/main.go +++ b/examples/basecoin/cmd/baseserver/main.go @@ -47,7 +47,9 @@ func serve(cmd *cobra.Command, args []string) error { rootDir := viper.GetString(cli.HomeFlag) keyMan := client.GetKeyManager(rootDir) serviceKeys := rest.NewServiceKeys(keyMan) - serviceTxs := rest.NewServiceTxs(commands.GetNode()) + + rpcClient := commands.GetNode() + serviceTxs := rest.NewServiceTxs(rpcClient) routeRegistrars := []func(*mux.Router) error{ // rest.Keys handlers @@ -77,6 +79,16 @@ func serve(cmd *cobra.Command, args []string) error { port := viper.GetInt(envPortFlag) addr := fmt.Sprintf(":%d", port) + onDisconnect := rpc.OnDisconnect(func(remoteAddr string) { + // FIXME: TODO + // n.eventBus.UnsubscribeAll(context.Background(), remoteAddr) + }) + routes := client.RPCRoutes(rpcClient) + wm := rpcserver.NewWebsocketManager(routes, onDisconnect) + wsLogger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "ws") + wm.SetLogger(wsLogger) + router.HandleFunc("/websocket", wm.WebsocketHandler) + log.Printf("Serving on %q", addr) return http.ListenAndServe(addr, router) } diff --git a/glide.lock b/glide.lock index a629377600d7..2793a6242ff3 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 791d28ec82d1ea662cc3f192aa7bf1f6dffdc1f2e43e57ce731857d6ea147ee4 -updated: 2017-12-01T10:08:25.699042855+01:00 +hash: da24779c9db3af6dc6427b7d1ae84a725bf454f7785c09d3dfc1a160442aca9f +updated: 2017-12-08T18:41:01.918184161-05:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -33,6 +33,15 @@ imports: version: 71201497bace774495daed26a3874fd339e0b538 - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 +- name: github.com/gogo/protobuf + version: 342cbe0a04158f6dcb03ca0079991a51a4248c02 + subpackages: + - gogoproto + - jsonpb + - proto + - protoc-gen-gogo/descriptor + - sortkeys + - types - name: github.com/golang/protobuf version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9 subpackages: @@ -112,9 +121,10 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: 22b491bb1952125dd2fb0730d6ca8e59e310547c + version: fca2b508c185b855af1446ec4afc19bdfc7b315d subpackages: - client + - example/code - example/dummy - server - types @@ -133,15 +143,15 @@ imports: - keys/wordlist - nano - name: github.com/tendermint/go-wire - version: 217a3c439f6497890d232ff5ed24084b43d9bfb3 + version: 51453fda64ba68061b42e17b17e68469993e0a02 subpackages: - data - data/base58 - - nowriter/tmencoding + - nowriter/tmlegacy - name: github.com/tendermint/iavl version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653 - name: github.com/tendermint/tendermint - version: b2489b4318c843a64e2809517f93d906c5f9dc15 + version: 7e3a5b7ce8e8a92b81eb99e3a6c1451e6d271d36 subpackages: - blockchain - certifiers @@ -177,7 +187,7 @@ imports: - types - version - name: github.com/tendermint/tmlibs - version: 21fb7819891997c96838308b4eba5a50b07ff03f + version: b49bce2bc3fb8fa25f676b9b49cce5e10f89b0c6 subpackages: - autofile - cli @@ -229,7 +239,7 @@ imports: subpackages: - googleapis/rpc/status - name: google.golang.org/grpc - version: f7bf885db0b7479a537ec317c6e48ce53145f3db + version: 401e0e00e4bb830a10496d64cd95e068c5bf50de subpackages: - balancer - codes diff --git a/glide.yaml b/glide.yaml index 84086d33b194..d309c51601b9 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,7 +1,7 @@ package: github.com/cosmos/cosmos-sdk import: - package: github.com/ethanfrey/hid - version: f76da0b80567e8b6f676e1757b549a93494fe4b5 + version: dce75af84cf849c60f39bf1b8192fb5cd597b5d9 - package: github.com/ethanfrey/ledger version: f7f2f056357db77db845a79aa1abdadc3ae66369 - package: github.com/gorilla/websocket @@ -12,7 +12,7 @@ import: - package: github.com/spf13/viper # update this when tendermint/tendermint updates - package: github.com/tendermint/abci - version: 22b491bb1952125dd2fb0730d6ca8e59e310547c + version: develop subpackages: - server - types From 65229108b9f3ca8bb2fb5b38e1e317000f6663ac Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 8 Dec 2017 19:15:05 -0500 Subject: [PATCH 093/117] updated to latest everything. booyeh --- app/store.go | 8 ++++---- app/val_test.go | 4 ++-- client/commands/commits/export.go | 2 +- client/commands/commits/show.go | 4 ++-- client/commands/commits/update.go | 2 +- client/commands/query/get.go | 23 +++++++++++++---------- client/commands/query/tx.go | 2 +- client/commands/rpc/helpers.go | 4 ++-- client/commands/rpc/secure.go | 8 ++++---- client/query.go | 23 ++++++++++------------- client/query_test.go | 2 +- client/wrapper.go | 8 ++++---- context.go | 2 +- errors/code.go | 15 +++++++++++++++ errors/common.go | 22 +++++++++++----------- handler.go | 8 ++++---- modules/auth/errors.go | 4 +--- modules/base/chain.go | 2 +- modules/base/chain_test.go | 4 ++-- modules/base/commands/wrap.go | 2 +- modules/base/errors.go | 4 +--- modules/base/helpers.go | 6 +++--- modules/base/multiplexer.go | 4 ++-- modules/base/multiplexer_test.go | 6 +++--- modules/base/tx.go | 4 ++-- modules/coin/errors.go | 10 ++++------ modules/coin/handler.go | 6 +++--- modules/coin/handler_test.go | 4 ++-- modules/eyes/errors.go | 2 +- modules/eyes/handler.go | 2 +- modules/eyes/handler_test.go | 2 +- modules/eyes/store.go | 4 ++-- modules/fee/errors.go | 4 +--- modules/fee/handler.go | 4 ++-- modules/fee/handler_test.go | 2 +- modules/ibc/commands/query.go | 8 ++++---- modules/ibc/errors.go | 21 ++++++++++----------- modules/ibc/ibc_test.go | 2 +- modules/ibc/keys.go | 4 ++-- modules/ibc/middleware.go | 2 +- modules/ibc/noop.go | 2 +- modules/ibc/provider.go | 10 +++++----- modules/ibc/store.go | 14 +++++++------- modules/ibc/test_helpers.go | 16 ++++++++-------- modules/ibc/tx.go | 2 +- modules/nonce/commands/query.go | 2 +- modules/nonce/errors.go | 8 +++----- modules/nonce/tx_test.go | 2 +- modules/roles/commands/wrap.go | 3 +-- modules/roles/error.go | 4 +--- modules/roles/handler.go | 4 ++-- modules/roles/handler_test.go | 2 +- modules/roles/middleware_test.go | 4 ++-- modules/roles/rest/handlers.go | 2 +- stack/context.go | 2 +- stack/mock.go | 6 +++--- state/bonsai.go | 4 ++-- state/errors.go | 3 +-- state/merkle.go | 10 +++++----- state/merkle_test.go | 2 +- state/queue.go | 27 ++++++++++++++------------- state/queue_test.go | 2 +- state/span.go | 18 +++++++++--------- state/span_test.go | 4 ++-- 64 files changed, 202 insertions(+), 201 deletions(-) create mode 100644 errors/code.go diff --git a/app/store.go b/app/store.go index ed4af7a9fa76..3b523f3e5cc0 100644 --- a/app/store.go +++ b/app/store.go @@ -37,7 +37,7 @@ type StoreApp struct { pending []*abci.Validator // height is last committed block, DeliverTx is the next one - height uint64 + height int64 logger log.Logger } @@ -99,12 +99,12 @@ func (app *StoreApp) Check() sm.SimpleDB { // CommittedHeight gets the last block height committed // to the db -func (app *StoreApp) CommittedHeight() uint64 { +func (app *StoreApp) CommittedHeight() int64 { return app.height } // WorkingHeight gets the current block we are writing -func (app *StoreApp) WorkingHeight() uint64 { +func (app *StoreApp) WorkingHeight() int64 { return app.height + 1 } @@ -243,7 +243,7 @@ func pubKeyIndex(val *abci.Validator, list []*abci.Validator) int { return -1 } -func loadState(dbName string, cacheSize int, historySize uint64) (*sm.State, error) { +func loadState(dbName string, cacheSize int, historySize int64) (*sm.State, error) { // memory backed case, just for testing if dbName == "" { tree := iavl.NewVersionedTree(0, dbm.NewMemDB()) diff --git a/app/val_test.go b/app/val_test.go index d79d4ee78b85..677a903ea9d6 100644 --- a/app/val_test.go +++ b/app/val_test.go @@ -17,8 +17,8 @@ import ( //----------------------------------- // Test cases start here -func randPower() uint64 { - return uint64(cmn.RandInt()%50 + 60) +func randPower() int64 { + return int64(cmn.RandInt()%50 + 60) } func makeVal() *abci.Validator { diff --git a/client/commands/commits/export.go b/client/commands/commits/export.go index 0bcb3f5589cd..c9789258f737 100644 --- a/client/commands/commits/export.go +++ b/client/commands/commits/export.go @@ -34,7 +34,7 @@ func exportCommit(cmd *cobra.Command, args []string) error { // load the seed as specified trust, _ := commands.GetProviders() - h := viper.GetInt(heightFlag) + h := int64(viper.GetInt(heightFlag)) hash := viper.GetString(hashFlag) fc, err := loadCommit(trust, h, hash, "") if err != nil { diff --git a/client/commands/commits/show.go b/client/commands/commits/show.go index f7d5fee58d6d..f107c5899f87 100644 --- a/client/commands/commits/show.go +++ b/client/commands/commits/show.go @@ -37,7 +37,7 @@ func init() { RootCmd.AddCommand(showCmd) } -func loadCommit(p lite.Provider, h int, hash, file string) (fc lite.FullCommit, err error) { +func loadCommit(p lite.Provider, h int64, hash, file string) (fc lite.FullCommit, err error) { // load the commit from the proper place if h != 0 { fc, err = p.GetByHeight(h) @@ -59,7 +59,7 @@ func loadCommit(p lite.Provider, h int, hash, file string) (fc lite.FullCommit, func showCommit(cmd *cobra.Command, args []string) error { trust, _ := commands.GetProviders() - h := viper.GetInt(heightFlag) + h := int64(viper.GetInt(heightFlag)) hash := viper.GetString(hashFlag) file := viper.GetString(fileFlag) fc, err := loadCommit(trust, h, hash, file) diff --git a/client/commands/commits/update.go b/client/commands/commits/update.go index 3bc0449722c3..d3d6d4a66274 100644 --- a/client/commands/commits/update.go +++ b/client/commands/commits/update.go @@ -29,7 +29,7 @@ func updateCommit(cmd *cobra.Command, args []string) error { return err } - h := viper.GetInt(heightFlag) + h := int64(viper.GetInt(heightFlag)) var fc lite.FullCommit if h <= 0 { // get the lastest from our source diff --git a/client/commands/query/get.go b/client/commands/query/get.go index 59c44c05f8c5..35f1bfad86dc 100644 --- a/client/commands/query/get.go +++ b/client/commands/query/get.go @@ -27,7 +27,7 @@ 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{}, height int, prove bool) (uint64, error) { +func GetParsed(key []byte, data interface{}, height int64, prove bool) (int64, error) { bs, h, err := Get(key, height, prove) if err != nil { return 0, err @@ -47,7 +47,7 @@ func GetParsed(key []byte, data interface{}, height int, prove bool) (uint64, er // 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, height int, prove bool) (data.Bytes, uint64, error) { +func Get(key []byte, height int64, prove bool) (data.Bytes, int64, error) { if height < 0 { return nil, 0, fmt.Errorf("Height cannot be negative") } @@ -55,8 +55,11 @@ func Get(key []byte, height int, prove bool) (data.Bytes, uint64, error) { if !prove { node := commands.GetNode() resp, err := node.ABCIQueryWithOptions("/key", key, - rpcclient.ABCIQueryOptions{Trusted: true, Height: uint64(height)}) - return data.Bytes(resp.Value), resp.Height, err + rpcclient.ABCIQueryOptions{Trusted: true, Height: int64(height)}) + if resp == nil { + return nil, height, err + } + return data.Bytes(resp.Response.Value), resp.Response.Height, err } val, h, _, err := GetWithProof(key, height) return val, h, err @@ -65,7 +68,7 @@ func Get(key []byte, height int, prove bool) (data.Bytes, uint64, error) { // 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, height int) (data.Bytes, uint64, iavl.KeyProof, error) { +func GetWithProof(key []byte, height int64) (data.Bytes, int64, iavl.KeyProof, error) { node := commands.GetNode() cert, err := commands.GetCertifier() if err != nil { @@ -93,19 +96,19 @@ func ParseHexKey(args []string, argname string) ([]byte, error) { } // GetHeight reads the viper config for the query height -func GetHeight() int { - return viper.GetInt(FlagHeight) +func GetHeight() int64 { + return int64(viper.GetInt(FlagHeight)) } type proof struct { - Height uint64 `json:"height"` + Height int64 `json:"height"` Data interface{} `json:"data"` } // FoutputProof writes the output of wrapping height and info // in the form {"data": , "height": } // to the provider io.Writer -func FoutputProof(w io.Writer, v interface{}, height uint64) error { +func FoutputProof(w io.Writer, v interface{}, height int64) error { wrap := &proof{height, v} blob, err := data.ToJSON(wrap) if err != nil { @@ -118,6 +121,6 @@ func FoutputProof(w io.Writer, v interface{}, height uint64) error { // OutputProof prints the proof to stdout // reuse this for printing proofs and we should enhance this for text/json, // better presentation of height -func OutputProof(data interface{}, height uint64) error { +func OutputProof(data interface{}, height int64) error { return FoutputProof(os.Stdout, data, height) } diff --git a/client/commands/query/tx.go b/client/commands/query/tx.go index f3fed3472fa1..9db6a727c15e 100644 --- a/client/commands/query/tx.go +++ b/client/commands/query/tx.go @@ -67,7 +67,7 @@ func txQueryCmd(cmd *cobra.Command, args []string) error { } // showTx parses anything that was previously registered as sdk.Tx -func showTx(h uint64, tx types.Tx) error { +func showTx(h int64, tx types.Tx) error { var info sdk.Tx err := wire.ReadBinaryBytes(tx, &info) if err != nil { diff --git a/client/commands/rpc/helpers.go b/client/commands/rpc/helpers.go index 7bcd074a0fa8..82ff88686ce2 100644 --- a/client/commands/rpc/helpers.go +++ b/client/commands/rpc/helpers.go @@ -25,10 +25,10 @@ func init() { func runWait(cmd *cobra.Command, args []string) error { c := commands.GetNode() - h := viper.GetInt(FlagHeight) + h := int64(viper.GetInt(FlagHeight)) if h == -1 { // read from delta - d := viper.GetInt(FlagDelta) + d := int64(viper.GetInt(FlagDelta)) if d == -1 { return errors.New("Must set --height or --delta") } diff --git a/client/commands/rpc/secure.go b/client/commands/rpc/secure.go index 86cf64f0c254..4ea350881375 100644 --- a/client/commands/rpc/secure.go +++ b/client/commands/rpc/secure.go @@ -26,7 +26,7 @@ func runBlock(cmd *cobra.Command, args []string) error { return err } - h := viper.GetInt(FlagHeight) + h := int64(viper.GetInt(FlagHeight)) block, err := c.Block(&h) if err != nil { return err @@ -46,7 +46,7 @@ func runCommit(cmd *cobra.Command, args []string) error { return err } - h := viper.GetInt(FlagHeight) + h := int64(viper.GetInt(FlagHeight)) commit, err := c.Commit(&h) if err != nil { return err @@ -66,8 +66,8 @@ func runHeaders(cmd *cobra.Command, args []string) error { return err } - min := viper.GetInt(FlagMin) - max := viper.GetInt(FlagMax) + min := int64(viper.GetInt(FlagMin)) + max := int64(viper.GetInt(FlagMax)) headers, err := c.BlockchainInfo(min, max) if err != nil { return err diff --git a/client/query.go b/client/query.go index 62ea8635bc83..f6e488bed062 100644 --- a/client/query.go +++ b/client/query.go @@ -19,9 +19,9 @@ 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, reqHeight int, node rpcclient.Client, +func GetWithProof(key []byte, reqHeight int64, node rpcclient.Client, cert lite.Certifier) ( - val data.Bytes, height uint64, proof iavl.KeyProof, err error) { + val data.Bytes, height int64, proof iavl.KeyProof, err error) { if reqHeight < 0 { err = errors.Errorf("Height cannot be negative") @@ -33,7 +33,7 @@ func GetWithProof(key []byte, reqHeight int, node rpcclient.Client, node, cert) if _resp != nil { resp := _resp.Response - val, height = resp.Value, uint64(resp.Height) + val, height = resp.Value, resp.Height } return val, height, proof, err } @@ -79,7 +79,7 @@ func GetWithProofOptions(path string, key []byte, opts rpcclient.ABCIQueryOption if err != nil { return nil, nil, errors.Wrap(err, "Couldn't verify proof") } - return resp, eproof, nil + return &ctypes.ResultABCIQuery{resp}, eproof, nil } // The key wasn't found, construct a proof of non-existence. @@ -93,30 +93,27 @@ func GetWithProofOptions(path string, key []byte, opts rpcclient.ABCIQueryOption if err != nil { return nil, nil, errors.Wrap(err, "Couldn't verify proof") } - return resp, aproof, ErrNoData() + return &ctypes.ResultABCIQuery{resp}, aproof, ErrNoData() } // GetCertifiedCommit gets the signed header for a given height // and certifies it. Returns error if unable to get a proven header. -func GetCertifiedCommit(h uint64, node rpcclient.Client, +func GetCertifiedCommit(h int64, node rpcclient.Client, cert lite.Certifier) (empty lite.Commit, err error) { - // TODO: please standardize all int types - ih := int(h) - // FIXME: cannot use cert.GetByHeight for now, as it also requires // Validators and will fail on querying tendermint for non-current height. // When this is supported, we should use it instead... - rpcclient.WaitForHeight(node, ih, nil) - cresp, err := node.Commit(&ih) + rpcclient.WaitForHeight(node, h, nil) + cresp, err := node.Commit(&h) if err != nil { return } commit := client.CommitFromResult(cresp) // validate downloaded checkpoint with our request and trust store. - if commit.Height() != ih { - return empty, certerr.ErrHeightMismatch(ih, commit.Height()) + if commit.Height() != h { + return empty, certerr.ErrHeightMismatch(h, commit.Height()) } err = cert.Certify(commit) return commit, nil diff --git a/client/query_test.go b/client/query_test.go index 29bde63bea01..8f93ff40044d 100644 --- a/client/query_test.go +++ b/client/query_test.go @@ -81,7 +81,7 @@ func TestAppProofs(t *testing.T) { bs, height, proof, err = GetWithProof(k, brh, cl, cert) require.NoError(err, "%+v", err) require.NotNil(proof) - require.True(height >= uint64(latest.Header.Height)) + require.True(height >= int64(latest.Header.Height)) // Alexis there is a bug here, somehow the above code gives us rootHash = nil // and proof.Verify doesn't care, while proofNotExists.Verify fails. diff --git a/client/wrapper.go b/client/wrapper.go index ffe6dd4259e7..e901881042a2 100644 --- a/client/wrapper.go +++ b/client/wrapper.go @@ -51,7 +51,7 @@ func (w Wrapper) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) { if !prove || err != nil { return res, err } - h := uint64(res.Height) + h := int64(res.Height) check, err := GetCertifiedCommit(h, w.Client, w.cert) if err != nil { return res, err @@ -64,7 +64,7 @@ func (w Wrapper) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) { // Rather expensive. // // TODO: optimize this if used for anything needing performance -func (w Wrapper) BlockchainInfo(minHeight, maxHeight int) (*ctypes.ResultBlockchainInfo, error) { +func (w Wrapper) BlockchainInfo(minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) { r, err := w.Client.BlockchainInfo(minHeight, maxHeight) if err != nil { return nil, err @@ -88,7 +88,7 @@ func (w Wrapper) BlockchainInfo(minHeight, maxHeight int) (*ctypes.ResultBlockch } // Block returns an entire block and verifies all signatures -func (w Wrapper) Block(height *int) (*ctypes.ResultBlock, error) { +func (w Wrapper) Block(height *int64) (*ctypes.ResultBlock, error) { r, err := w.Client.Block(height) if err != nil { return nil, err @@ -115,7 +115,7 @@ func (w Wrapper) Block(height *int) (*ctypes.ResultBlock, error) { // Commit downloads the Commit and certifies it with the lite. // // This is the foundation for all other verification in this module -func (w Wrapper) Commit(height *int) (*ctypes.ResultCommit, error) { +func (w Wrapper) Commit(height *int64) (*ctypes.ResultCommit, error) { rpcclient.WaitForHeight(w.Client, *height, nil) r, err := w.Client.Commit(height) // if we got it, then certify it diff --git a/context.go b/context.go index fedca0def4f1..9444d9963e76 100644 --- a/context.go +++ b/context.go @@ -78,7 +78,7 @@ type Context interface { IsParent(ctx Context) bool Reset() Context ChainID() string - BlockHeight() uint64 + BlockHeight() int64 } //////////////////////////////// Sort Interface diff --git a/errors/code.go b/errors/code.go new file mode 100644 index 000000000000..ec9a24cf35d7 --- /dev/null +++ b/errors/code.go @@ -0,0 +1,15 @@ +package errors + +const ( + defaultErrCode uint32 = 0x1 + + CodeTypeInternalErr uint32 = 0 + CodeTypeEncodingErr uint32 = 1 + CodeTypeUnauthorized uint32 = 2 + CodeTypeUnknownRequest uint32 = 3 + CodeTypeUnknownAddress uint32 = 4 + CodeTypeBaseUnknownAddress uint32 = 4 // lol fuck it + CodeTypeBadNonce uint32 = 5 + CodeTypeBaseInvalidInput uint32 = 20 + CodeTypeBaseInvalidOutput uint32 = 21 +) diff --git a/errors/common.go b/errors/common.go index c8854f12207f..535a3469c683 100644 --- a/errors/common.go +++ b/errors/common.go @@ -32,7 +32,7 @@ func unwrap(i interface{}) interface{} { func ErrUnknownTxType(tx interface{}) TMError { msg := fmt.Sprintf("%T", unwrap(tx)) - return WithMessage(msg, errUnknownTxType, unknownRequest) + return WithMessage(msg, errUnknownTxType, CodeTypeUnknownRequest) } func IsUnknownTxTypeErr(err error) bool { return IsSameError(errUnknownTxType, err) @@ -40,61 +40,61 @@ func IsUnknownTxTypeErr(err error) bool { func ErrInvalidFormat(expected string, tx interface{}) TMError { msg := fmt.Sprintf("%T not %s", unwrap(tx), expected) - return WithMessage(msg, errInvalidFormat, unknownRequest) + return WithMessage(msg, errInvalidFormat, CodeTypeUnknownRequest) } func IsInvalidFormatErr(err error) bool { return IsSameError(errInvalidFormat, err) } func ErrUnknownModule(mod string) TMError { - return WithMessage(mod, errUnknownModule, unknownRequest) + return WithMessage(mod, errUnknownModule, CodeTypeUnknownRequest) } func IsUnknownModuleErr(err error) bool { return IsSameError(errUnknownModule, err) } func ErrUnknownKey(mod string) TMError { - return WithMessage(mod, errUnknownKey, unknownRequest) + return WithMessage(mod, errUnknownKey, CodeTypeUnknownRequest) } func IsUnknownKeyErr(err error) bool { return IsSameError(errUnknownKey, err) } func ErrInternal(msg string) TMError { - return New(msg, internalErr) + return New(msg, CodeTypeInternalErr) } // IsInternalErr matches any error that is not classified func IsInternalErr(err error) bool { - return HasErrorCode(err, internalErr) + return HasErrorCode(err, CodeTypeInternalErr) } func ErrDecoding() TMError { - return WithCode(errDecoding, encodingErr) + return WithCode(errDecoding, CodeTypeEncodingErr) } func IsDecodingErr(err error) bool { return IsSameError(errDecoding, err) } func ErrUnauthorized() TMError { - return WithCode(errUnauthorized, unauthorized) + return WithCode(errUnauthorized, CodeTypeUnauthorized) } // IsUnauthorizedErr is generic helper for any unauthorized errors, // also specific sub-types func IsUnauthorizedErr(err error) bool { - return HasErrorCode(err, unauthorized) + return HasErrorCode(err, CodeTypeUnauthorized) } func ErrMissingSignature() TMError { - return WithCode(errMissingSignature, unauthorized) + return WithCode(errMissingSignature, CodeTypeUnauthorized) } func IsMissingSignatureErr(err error) bool { return IsSameError(errMissingSignature, err) } func ErrTooLarge() TMError { - return WithCode(errTooLarge, encodingErr) + return WithCode(errTooLarge, CodeTypeEncodingErr) } func IsTooLargeErr(err error) bool { return IsSameError(errTooLarge, err) diff --git a/handler.go b/handler.go index 638fe4cc6648..5bfc24194e0a 100644 --- a/handler.go +++ b/handler.go @@ -109,14 +109,14 @@ type CheckResult struct { Data data.Bytes Log string // GasAllocated is the maximum units of work we allow this tx to perform - GasAllocated uint64 + GasAllocated int64 // GasPayment is the total fees for this tx (or other source of payment) - GasPayment uint64 + GasPayment int64 } // NewCheck sets the gas used and the response data but no more info // these are the most common info needed to be set by the Handler -func NewCheck(gasAllocated uint64, log string) CheckResult { +func NewCheck(gasAllocated int64, log string) CheckResult { return CheckResult{ GasAllocated: gasAllocated, Log: log, @@ -143,7 +143,7 @@ type DeliverResult struct { Log string Diff []*abci.Validator Tags []*abci.KVPair - GasUsed uint64 // unused + GasUsed int64 // unused } func (d DeliverResult) ToABCI() abci.ResponseDeliverTx { diff --git a/modules/auth/errors.go b/modules/auth/errors.go index 46b562cf4e49..7db2d27698d8 100644 --- a/modules/auth/errors.go +++ b/modules/auth/errors.go @@ -4,8 +4,6 @@ package auth import ( "fmt" - abci "github.com/tendermint/abci/types" - "github.com/cosmos/cosmos-sdk/errors" ) @@ -13,7 +11,7 @@ var ( errInvalidSignature = fmt.Errorf("Invalid Signature") //move auth errTooManySignatures = fmt.Errorf("Too many signatures") //move auth - unauthorized = abci.CodeType_Unauthorized + unauthorized = errors.CodeTypeUnauthorized ) func ErrTooManySignatures() errors.TMError { diff --git a/modules/base/chain.go b/modules/base/chain.go index 61f919c0efe0..1fa32ce6cc21 100644 --- a/modules/base/chain.go +++ b/modules/base/chain.go @@ -44,7 +44,7 @@ func (c Chain) DeliverTx(ctx sdk.Context, store state.SimpleDB, tx sdk.Tx, next // checkChainTx makes sure the tx is a Chain Tx, it is on the proper chain, // and it has not expired. -func (c Chain) checkChainTx(chainID string, height uint64, tx sdk.Tx) (sdk.Tx, error) { +func (c Chain) checkChainTx(chainID string, height int64, tx sdk.Tx) (sdk.Tx, error) { // make sure it is a chaintx ctx, ok := tx.Unwrap().(ChainTx) if !ok { diff --git a/modules/base/chain_test.go b/modules/base/chain_test.go index 4ce1a53a72a2..a8d58bff92d7 100644 --- a/modules/base/chain_test.go +++ b/modules/base/chain_test.go @@ -19,7 +19,7 @@ func TestChainValidate(t *testing.T) { cases := []struct { name string - expires uint64 + expires int64 valid bool }{ {"hello", 0, true}, @@ -48,7 +48,7 @@ func TestChain(t *testing.T) { assert := assert.New(t) msg := "got it" chainID := "my-chain" - height := uint64(100) + height := int64(100) raw := stack.NewRawTx([]byte{1, 2, 3, 4}) cases := []struct { diff --git a/modules/base/commands/wrap.go b/modules/base/commands/wrap.go index b9be03779f94..caca2904fdb6 100644 --- a/modules/base/commands/wrap.go +++ b/modules/base/commands/wrap.go @@ -29,7 +29,7 @@ func (ChainWrapper) Wrap(tx sdk.Tx) (res sdk.Tx, err error) { if chain == "" { return res, errors.New("No chain-id provided") } - res = base.NewChainTx(chain, uint64(expires), tx) + res = base.NewChainTx(chain, int64(expires), tx) return } diff --git a/modules/base/errors.go b/modules/base/errors.go index 4ebf626b8f9c..7da6b985b3a2 100644 --- a/modules/base/errors.go +++ b/modules/base/errors.go @@ -4,8 +4,6 @@ package base import ( "fmt" - abci "github.com/tendermint/abci/types" - "github.com/cosmos/cosmos-sdk/errors" ) @@ -14,7 +12,7 @@ var ( errWrongChain = fmt.Errorf("Wrong chain for tx") //move base errExpired = fmt.Errorf("Tx expired") //move base - unauthorized = abci.CodeType_Unauthorized + unauthorized = errors.CodeTypeUnauthorized ) func ErrNoChain() errors.TMError { diff --git a/modules/base/helpers.go b/modules/base/helpers.go index 4958a8bfbbe4..1e6d5bffdbc8 100644 --- a/modules/base/helpers.go +++ b/modules/base/helpers.go @@ -103,11 +103,11 @@ func (PriceHandler) DeliverTx(ctx sdk.Context, store state.SimpleDB, // PriceShowTx lets us bounce back a given fee/gas on CheckTx type PriceShowTx struct { - GasAllocated uint64 - GasPayment uint64 + GasAllocated int64 + GasPayment int64 } -func NewPriceShowTx(gasAllocated, gasPayment uint64) sdk.Tx { +func NewPriceShowTx(gasAllocated, gasPayment int64) sdk.Tx { return PriceShowTx{GasAllocated: gasAllocated, GasPayment: gasPayment}.Wrap() } diff --git a/modules/base/multiplexer.go b/modules/base/multiplexer.go index d899a76ebe06..a949c542ba69 100644 --- a/modules/base/multiplexer.go +++ b/modules/base/multiplexer.go @@ -77,7 +77,7 @@ func runAllDelivers(ctx sdk.Context, store state.SimpleDB, txs []sdk.Tx, next sd func combineChecks(all []sdk.CheckResult) sdk.CheckResult { datas := make([]data.Bytes, len(all)) logs := make([]string, len(all)) - var allocated, payments uint64 + var allocated, payments int64 for i, r := range all { datas[i] = r.Data logs[i] = r.Log @@ -97,7 +97,7 @@ func combineChecks(all []sdk.CheckResult) sdk.CheckResult { func combineDelivers(all []sdk.DeliverResult) sdk.DeliverResult { datas := make([]data.Bytes, len(all)) logs := make([]string, len(all)) - var used uint64 + var used int64 var diffs []*abci.Validator for i, r := range all { datas[i] = r.Data diff --git a/modules/base/multiplexer_test.go b/modules/base/multiplexer_test.go index 97d5324ee64d..1b3a447c9afb 100644 --- a/modules/base/multiplexer_test.go +++ b/modules/base/multiplexer_test.go @@ -16,7 +16,7 @@ func TestMultiplexer(t *testing.T) { assert := assert.New(t) msg := "diddly" chainID := "multi-verse" - height := uint64(100) + height := int64(100) // Generic args here... store := state.NewMemKVStore() @@ -43,8 +43,8 @@ func TestMultiplexer(t *testing.T) { cases := [...]struct { tx sdk.Tx valid bool - gasAllocated uint64 - gasPayment uint64 + gasAllocated int64 + gasPayment int64 log string data data.Bytes }{ diff --git a/modules/base/tx.go b/modules/base/tx.go index 8b3a88fb2c0e..f7379ce8975b 100644 --- a/modules/base/tx.go +++ b/modules/base/tx.go @@ -59,7 +59,7 @@ type ChainTx struct { // name of chain, must be [A-Za-z0-9_-]+ ChainID string `json:"chain_id"` // block height at which it is no longer valid, 0 means no expiration - ExpiresAt uint64 `json:"expires_at"` + ExpiresAt int64 `json:"expires_at"` Tx sdk.Tx `json:"tx"` } @@ -71,7 +71,7 @@ var ( // NewChainTx wraps a particular tx with the ChainTx wrapper, // to enforce chain and height -func NewChainTx(chainID string, expires uint64, tx sdk.Tx) sdk.Tx { +func NewChainTx(chainID string, expires int64, tx sdk.Tx) sdk.Tx { c := ChainTx{ ChainID: chainID, ExpiresAt: expires, diff --git a/modules/coin/errors.go b/modules/coin/errors.go index caf7d4c9b975..ce37da3fb71d 100644 --- a/modules/coin/errors.go +++ b/modules/coin/errors.go @@ -4,8 +4,6 @@ package coin import ( "fmt" - abci "github.com/tendermint/abci/types" - "github.com/cosmos/cosmos-sdk/errors" ) @@ -18,10 +16,10 @@ var ( errInvalidAddress = fmt.Errorf("Invalid address") errInvalidCoins = fmt.Errorf("Invalid coins") - invalidInput = abci.CodeType_BaseInvalidInput - invalidOutput = abci.CodeType_BaseInvalidOutput - unknownAddress = abci.CodeType_BaseUnknownAddress - unknownRequest = abci.CodeType_UnknownRequest + invalidInput = errors.CodeTypeBaseInvalidInput + invalidOutput = errors.CodeTypeBaseInvalidOutput + unknownAddress = errors.CodeTypeBaseUnknownAddress + unknownRequest = errors.CodeTypeUnknownRequest ) // here are some generic handlers to grab classes of errors based on code diff --git a/modules/coin/handler.go b/modules/coin/handler.go index 90d8642f6b38..6f3d6ee45770 100644 --- a/modules/coin/handler.go +++ b/modules/coin/handler.go @@ -17,9 +17,9 @@ const ( //NameCoin - name space of the coin module NameCoin = "coin" // CostSend is GasAllocation per input/output - CostSend = uint64(10) + CostSend = int64(10) // CostCredit is GasAllocation of a credit allocation - CostCredit = uint64(20) + CostCredit = int64(20) ) // Handler includes an accountant @@ -54,7 +54,7 @@ func (h Handler) CheckTx(ctx sdk.Context, store state.SimpleDB, switch t := tx.Unwrap().(type) { case SendTx: // price based on inputs and outputs - used := uint64(len(t.Inputs) + len(t.Outputs)) + used := int64(len(t.Inputs) + len(t.Outputs)) return sdk.NewCheck(used*CostSend, ""), h.checkSendTx(ctx, store, t) case CreditTx: // default price of 20, constant work diff --git a/modules/coin/handler_test.go b/modules/coin/handler_test.go index 3df51d8e56b0..81e18c521fc3 100644 --- a/modules/coin/handler_test.go +++ b/modules/coin/handler_test.go @@ -110,7 +110,7 @@ func TestCheckDeliverSendTx(t *testing.T) { tx sdk.Tx perms []sdk.Actor final []money // nil for error - cost uint64 // gas allocated (if not error) + cost int64 // gas allocated (if not error) }{ { []money{{addr1, moreCoins}}, @@ -175,7 +175,7 @@ func TestCheckDeliverSendTx(t *testing.T) { assert.Nil(err, "%d: %+v", i, err) assert.Nil(err2, "%d: %+v", i, err2) // make sure proper gas is set - assert.Equal(uint64(0), cres.GasPayment, "%d", i) + assert.Equal(int64(0), cres.GasPayment, "%d", i) assert.Equal(tc.cost, cres.GasAllocated, "%d", i) // make sure the final balances are correct for _, f := range tc.final { diff --git a/modules/eyes/errors.go b/modules/eyes/errors.go index ae7babc6ca07..286e24776e6c 100644 --- a/modules/eyes/errors.go +++ b/modules/eyes/errors.go @@ -11,7 +11,7 @@ import ( var ( errMissingData = fmt.Errorf("All tx fields must be filled") - malformed = abci.CodeType_EncodingError + malformed = errors.CodeTypeEncodingError ) //nolint diff --git a/modules/eyes/handler.go b/modules/eyes/handler.go index 34a54877e4b9..0e3946730d7c 100644 --- a/modules/eyes/handler.go +++ b/modules/eyes/handler.go @@ -14,7 +14,7 @@ const ( Name = "eyes" // CostSet is the gas needed for the set operation - CostSet uint64 = 10 + CostSet int64 = 10 // CostRemove is the gas needed for the remove operation CostRemove = 10 ) diff --git a/modules/eyes/handler_test.go b/modules/eyes/handler_test.go index 1e44ae438114..fd70b29fddfe 100644 --- a/modules/eyes/handler_test.go +++ b/modules/eyes/handler_test.go @@ -15,7 +15,7 @@ func TestHandler(t *testing.T) { key := []byte("one") val := []byte("foo") - var height uint64 = 123 + var height int64 = 123 h := NewHandler() ctx := stack.MockContext("role-chain", height) diff --git a/modules/eyes/store.go b/modules/eyes/store.go index 38d892064f03..b103ea4fabbd 100644 --- a/modules/eyes/store.go +++ b/modules/eyes/store.go @@ -5,14 +5,14 @@ import "github.com/tendermint/go-wire/data" // Data is the struct we use to store in the merkle tree type Data struct { // SetAt is the block height this was set at - SetAt uint64 `json:"set_at"` + SetAt int64 `json:"set_at"` // Value is the data that was stored. // data.Bytes is like []byte but json encodes as hex not base64 Value data.Bytes `json:"value"` } // NewData creates a new Data item -func NewData(value []byte, setAt uint64) Data { +func NewData(value []byte, setAt int64) Data { return Data{ SetAt: setAt, Value: value, diff --git a/modules/fee/errors.go b/modules/fee/errors.go index 80cc9818aa30..dcbbf58e13c8 100644 --- a/modules/fee/errors.go +++ b/modules/fee/errors.go @@ -4,8 +4,6 @@ package fee import ( "fmt" - abci "github.com/tendermint/abci/types" - "github.com/cosmos/cosmos-sdk/errors" ) @@ -14,7 +12,7 @@ var ( errWrongFeeDenom = fmt.Errorf("Required fee denomination") errSkipFees = fmt.Errorf("Skip fees") - invalidInput = abci.CodeType_BaseInvalidInput + invalidInput = errors.CodeTypeBaseInvalidInput ) func ErrInsufficientFees() errors.TMError { diff --git a/modules/fee/handler.go b/modules/fee/handler.go index 0a1df3f49d91..2e9392dcae81 100644 --- a/modules/fee/handler.go +++ b/modules/fee/handler.go @@ -55,14 +55,14 @@ func (h SimpleFeeMiddleware) CheckTx(ctx sdk.Context, store state.SimpleDB, tx s return res, err } - var paid, used uint64 + var paid, used int64 if !fee.Fee.IsZero() { // now, try to make a IPC call to coins... send := coin.NewSendOneTx(fee.Payer, h.Collector, coin.Coins{fee.Fee}) sendRes, err := next.CheckTx(ctx, store, send) if err != nil { return res, err } - paid = uint64(fee.Fee.Amount) + paid = int64(fee.Fee.Amount) used = sendRes.GasAllocated } diff --git a/modules/fee/handler_test.go b/modules/fee/handler_test.go index a4fc0cc9baf6..bbb07e2d80a0 100644 --- a/modules/fee/handler_test.go +++ b/modules/fee/handler_test.go @@ -71,7 +71,7 @@ func TestFeeChecks(t *testing.T) { left coin.Coins collected coin.Coins // expected gas allocated - expectedCost uint64 + expectedCost int64 }{ // make sure it works with no fee (control group) {true, app1, act1, false, act1, zero, mixed, nil, 0}, diff --git a/modules/ibc/commands/query.go b/modules/ibc/commands/query.go index fb1da6506764..cd37ebae9e79 100644 --- a/modules/ibc/commands/query.go +++ b/modules/ibc/commands/query.go @@ -47,7 +47,7 @@ var PacketsQueryCmd = &cobra.Command{ Use: "packets", Short: "Get latest packet in a queue", RunE: commands.RequireInit(packetsQueryCmd), - // uint64 + // int64 } // PacketQueryCmd - get the names packet (by queue and sequence) @@ -156,7 +156,7 @@ func packetsQueryCmd(cmd *cobra.Command, args []string) error { key = stack.PrefixedKey(ibc.NameIBC, ibc.QueueOutKey(to)) } - var res uint64 + var res int64 prove := !viper.GetBool(commands.FlagTrustNode) h, err := query.GetParsed(key, &res, query.GetHeight(), prove) if err != nil { @@ -182,9 +182,9 @@ func packetQueryCmd(cmd *cobra.Command, args []string) error { var key []byte if from != "" { - key = stack.PrefixedKey(ibc.NameIBC, ibc.QueueInPacketKey(from, uint64(seq))) + key = stack.PrefixedKey(ibc.NameIBC, ibc.QueueInPacketKey(from, int64(seq))) } else { - key = stack.PrefixedKey(ibc.NameIBC, ibc.QueueOutPacketKey(to, uint64(seq))) + key = stack.PrefixedKey(ibc.NameIBC, ibc.QueueOutPacketKey(to, int64(seq))) } // Input queue just display the results diff --git a/modules/ibc/errors.go b/modules/ibc/errors.go index 8c3c99a611bb..04b52adb0818 100644 --- a/modules/ibc/errors.go +++ b/modules/ibc/errors.go @@ -3,7 +3,6 @@ package ibc import ( "fmt" - abci "github.com/tendermint/abci/types" "github.com/cosmos/cosmos-sdk/errors" ) @@ -20,14 +19,14 @@ var ( errInvalidProof = fmt.Errorf("Invalid merkle proof") msgInvalidCommit = "Invalid header and commit" - IBCCodeChainNotRegistered = abci.CodeType(1001) - IBCCodeChainAlreadyExists = abci.CodeType(1002) - IBCCodeUnknownChain = abci.CodeType(1003) - IBCCodeInvalidPacketSequence = abci.CodeType(1004) - IBCCodeUnknownHeight = abci.CodeType(1005) - IBCCodeInvalidCommit = abci.CodeType(1006) - IBCCodeInvalidProof = abci.CodeType(1007) - IBCCodeInvalidCall = abci.CodeType(1008) + IBCCodeChainNotRegistered = uint32(1001) + IBCCodeChainAlreadyExists = uint32(1002) + IBCCodeUnknownChain = uint32(1003) + IBCCodeInvalidPacketSequence = uint32(1004) + IBCCodeUnknownHeight = uint32(1005) + IBCCodeInvalidCommit = uint32(1006) + IBCCodeInvalidProof = uint32(1007) + IBCCodeInvalidCall = uint32(1008) ) func ErrNotRegistered(chainID string) error { @@ -65,7 +64,7 @@ func IsCannotSetPermissionErr(err error) bool { return errors.IsSameError(errCannotSetPermission, err) } -func ErrHeaderNotFound(h int) error { +func ErrHeaderNotFound(h int64) error { msg := fmt.Sprintf("height %d", h) return errors.WithMessage(msg, errHeaderNotFound, IBCCodeUnknownHeight) } @@ -80,7 +79,7 @@ func IsPacketAlreadyExistsErr(err error) bool { return errors.IsSameError(errPacketAlreadyExists, err) } -func ErrPacketOutOfOrder(seq uint64) error { +func ErrPacketOutOfOrder(seq int64) error { msg := fmt.Sprintf("expected %d", seq) return errors.WithMessage(msg, errPacketOutOfOrder, IBCCodeInvalidPacketSequence) } diff --git a/modules/ibc/ibc_test.go b/modules/ibc/ibc_test.go index 70a560f98f45..659d28456cae 100644 --- a/modules/ibc/ibc_test.go +++ b/modules/ibc/ibc_test.go @@ -302,7 +302,7 @@ func TestIBCCreatePacket(t *testing.T) { q := OutputQueue(p, chainID) if assert.Equal(2, q.Size()) { expected := []struct { - seq uint64 + seq int64 perm sdk.Actors }{ {0, nil}, diff --git a/modules/ibc/keys.go b/modules/ibc/keys.go index 4b5a53f980f0..90c098a38f74 100644 --- a/modules/ibc/keys.go +++ b/modules/ibc/keys.go @@ -46,14 +46,14 @@ func QueueOutKey(chainID string) []byte { } // QueueInPacketKey is the key to get given packet from this chain's input queue -func QueueInPacketKey(chainID string, seq uint64) []byte { +func QueueInPacketKey(chainID string, seq int64) []byte { return stack.PrefixedKey(chainID, stack.PrefixedKey(prefixInput, state.QueueItemKey(seq))) } // QueueOutPacketKey is the key to get given packet from this chain's output queue -func QueueOutPacketKey(chainID string, seq uint64) []byte { +func QueueOutPacketKey(chainID string, seq int64) []byte { return stack.PrefixedKey(chainID, stack.PrefixedKey(prefixOutput, state.QueueItemKey(seq))) diff --git a/modules/ibc/middleware.go b/modules/ibc/middleware.go index 09ffabb14241..83866f8fe959 100644 --- a/modules/ibc/middleware.go +++ b/modules/ibc/middleware.go @@ -96,7 +96,7 @@ func (m Middleware) verifyPost(ctx sdk.Context, store state.SimpleDB, provider := newDBProvider(space) // if the query was on height H, the proof is in header H+1 - proofHeight := int(tx.FromChainHeight + 1) + proofHeight := tx.FromChainHeight + 1 seed, err := provider.GetExactHeight(proofHeight) if err != nil { return ictx, itx, err diff --git a/modules/ibc/noop.go b/modules/ibc/noop.go index 3e111caf9bf1..9c6825694eff 100644 --- a/modules/ibc/noop.go +++ b/modules/ibc/noop.go @@ -15,7 +15,7 @@ func NewMissingProvider() lite.Provider { } func (missingProvider) StoreCommit(lite.FullCommit) error { return nil } -func (missingProvider) GetByHeight(int) (lite.FullCommit, error) { +func (missingProvider) GetByHeight(int64) (lite.FullCommit, error) { return lite.FullCommit{}, liteErr.ErrCommitNotFound() } func (missingProvider) GetByHash([]byte) (lite.FullCommit, error) { diff --git a/modules/ibc/provider.go b/modules/ibc/provider.go index 2e9d9584c3d4..6314840c104c 100644 --- a/modules/ibc/provider.go +++ b/modules/ibc/provider.go @@ -18,7 +18,7 @@ const ( // newCertifier loads up the current state of this chain to make a proper certifier // it will load the most recent height before block h if h is positive // if h < 0, it will load the latest height -func newCertifier(store state.SimpleDB, chainID string, h int) (*lite.Inquiring, error) { +func newCertifier(store state.SimpleDB, chainID string, h int64) (*lite.Inquiring, error) { // each chain has their own prefixed subspace p := newDBProvider(store) @@ -60,7 +60,7 @@ func (d *dbProvider) StoreCommit(fc lite.FullCommit) error { // TODO: don't duplicate data.... b := wire.BinaryBytes(fc) d.byHash.Set(fc.ValidatorsHash(), b) - d.byHeight.Set(uint64(fc.Height()), b) + d.byHeight.Set(int64(fc.Height()), b) return nil } @@ -73,8 +73,8 @@ func (d *dbProvider) LatestCommit() (fc lite.FullCommit, err error) { return } -func (d *dbProvider) GetByHeight(h int) (fc lite.FullCommit, err error) { - b, _ := d.byHeight.LTE(uint64(h)) +func (d *dbProvider) GetByHeight(h int64) (fc lite.FullCommit, err error) { + b, _ := d.byHeight.LTE(int64(h)) if b == nil { return fc, certerr.ErrCommitNotFound() } @@ -93,7 +93,7 @@ func (d *dbProvider) GetByHash(hash []byte) (fc lite.FullCommit, err error) { // GetExactHeight is like GetByHeight, but returns an error instead of // closest match if there is no exact match -func (d *dbProvider) GetExactHeight(h int) (fc lite.FullCommit, err error) { +func (d *dbProvider) GetExactHeight(h int64) (fc lite.FullCommit, err error) { fc, err = d.GetByHeight(h) if err != nil { return diff --git a/modules/ibc/store.go b/modules/ibc/store.go index 6da04f004b9f..13e798e2d602 100644 --- a/modules/ibc/store.go +++ b/modules/ibc/store.go @@ -30,8 +30,8 @@ func LoadInfo(store state.SimpleDB) (h HandlerInfo) { // ChainInfo is the global info we store for each registered chain, // besides the headers, proofs, and packets type ChainInfo struct { - RegisteredAt uint64 `json:"registered_at"` - RemoteBlock int `json:"remote_block"` + RegisteredAt int64 `json:"registered_at"` + RemoteBlock int64 `json:"remote_block"` } // ChainSet is the set of all registered chains @@ -49,7 +49,7 @@ func NewChainSet(store state.SimpleDB) ChainSet { // Register adds the named chain with some info // returns error if already present -func (c ChainSet) Register(chainID string, ourHeight uint64, theirHeight int) error { +func (c ChainSet) Register(chainID string, ourHeight int64, theirHeight int64) error { if c.Exists([]byte(chainID)) { return ErrAlreadyRegistered(chainID) } @@ -64,7 +64,7 @@ func (c ChainSet) Register(chainID string, ourHeight uint64, theirHeight int) er // Update sets the new tracked height on this chain // returns error if not present -func (c ChainSet) Update(chainID string, theirHeight int) error { +func (c ChainSet) Update(chainID string, theirHeight int64) error { d := c.Set.Get([]byte(chainID)) if len(d) == 0 { return ErrNotRegistered(chainID) @@ -86,14 +86,14 @@ func (c ChainSet) Update(chainID string, theirHeight int) error { // Packet is a wrapped transaction and permission that we want to // send off to another chain. type Packet struct { - DestChain string `json:"dest_chain"` - Sequence uint64 `json:"sequence"` + DestChain string `json:"dest_chain"` + Sequence int64 `json:"sequence"` Permissions sdk.Actors `json:"permissions"` Tx sdk.Tx `json:"tx"` } // NewPacket creates a new outgoing packet -func NewPacket(tx sdk.Tx, dest string, seq uint64, perm ...sdk.Actor) Packet { +func NewPacket(tx sdk.Tx, dest string, seq int64, perm ...sdk.Actor) Packet { return Packet{ DestChain: dest, Sequence: seq, diff --git a/modules/ibc/test_helpers.go b/modules/ibc/test_helpers.go index 6e2baba5c8cc..480a9254aca2 100644 --- a/modules/ibc/test_helpers.go +++ b/modules/ibc/test_helpers.go @@ -31,14 +31,14 @@ func NewMockChain(chainID string, numKeys int) MockChain { } // GetRegistrationTx returns a valid tx to register this chain -func (m MockChain) GetRegistrationTx(h int) RegisterChainTx { +func (m MockChain) GetRegistrationTx(h int64) RegisterChainTx { fc := genEmptyCommit(m.keys, m.chainID, h, m.tree.Hash(), len(m.keys)) return RegisterChainTx{fc} } // MakePostPacket commits the packet locally and returns the proof, // in the form of two packets to update the header and prove this packet. -func (m MockChain) MakePostPacket(packet Packet, h int) ( +func (m MockChain) MakePostPacket(packet Packet, h int64) ( PostPacketTx, UpdateChainTx) { post := makePostPacket(m.tree, packet, m.chainID, h) @@ -48,14 +48,14 @@ func (m MockChain) MakePostPacket(packet Packet, h int) ( return post, update } -func genEmptyCommit(keys lite.ValKeys, chain string, h int, +func genEmptyCommit(keys lite.ValKeys, chain string, h int64, appHash []byte, count int) lite.FullCommit { vals := keys.ToValidators(10, 0) return keys.GenFullCommit(chain, h, nil, vals, appHash, 0, count) } -func makePostPacket(tree *iavl.Tree, packet Packet, fromID string, fromHeight int) PostPacketTx { +func makePostPacket(tree *iavl.Tree, packet Packet, fromID string, fromHeight int64) PostPacketTx { key := []byte(fmt.Sprintf("some-long-prefix-%06d", packet.Sequence)) tree.Set(key, packet.Bytes()) _, proof, err := tree.GetWithProof(key) @@ -68,7 +68,7 @@ func makePostPacket(tree *iavl.Tree, packet Packet, fromID string, fromHeight in return PostPacketTx{ FromChainID: fromID, - FromChainHeight: uint64(fromHeight), + FromChainHeight: int64(fromHeight), Proof: proof.(*iavl.KeyExistsProof), Key: key, Packet: packet, @@ -80,7 +80,7 @@ type AppChain struct { chainID string app sdk.Handler store state.SimpleDB - height int + height int64 } // NewAppChain returns a chain that is ready to respond to tx @@ -95,7 +95,7 @@ func NewAppChain(app sdk.Handler, chainID string) *AppChain { // IncrementHeight allows us to jump heights, more than the auto-step // of 1. It returns the new height we are at. -func (a *AppChain) IncrementHeight(delta int) int { +func (a *AppChain) IncrementHeight(delta int64) int64 { a.height += delta return a.height } @@ -103,7 +103,7 @@ func (a *AppChain) IncrementHeight(delta int) int { // DeliverTx runs the tx and commits the new tree, incrementing height // by one. func (a *AppChain) DeliverTx(tx sdk.Tx, perms ...sdk.Actor) (sdk.DeliverResult, error) { - ctx := stack.MockContext(a.chainID, uint64(a.height)).WithPermissions(perms...) + ctx := stack.MockContext(a.chainID, int64(a.height)).WithPermissions(perms...) store := a.store.Checkpoint() res, err := a.app.DeliverTx(ctx, store, tx) if err == nil { diff --git a/modules/ibc/tx.go b/modules/ibc/tx.go index 10b69686192b..be9dbefefc7c 100644 --- a/modules/ibc/tx.go +++ b/modules/ibc/tx.go @@ -114,7 +114,7 @@ type PostPacketTx struct { 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"` + FromChainHeight int64 `json:"src_height"` // this proof must match the header and the packet.Bytes() Proof *iavl.KeyExistsProof `json:"proof"` Key data.Bytes `json:"key"` diff --git a/modules/nonce/commands/query.go b/modules/nonce/commands/query.go index 7021c8ca5a2c..9d3bb0a16b81 100644 --- a/modules/nonce/commands/query.go +++ b/modules/nonce/commands/query.go @@ -41,7 +41,7 @@ func nonceQueryCmd(cmd *cobra.Command, args []string) error { return query.OutputProof(seq, height) } -func doNonceQuery(signers []sdk.Actor) (sequence uint32, height uint64, err error) { +func doNonceQuery(signers []sdk.Actor) (sequence uint32, height int64, err error) { key := stack.PrefixedKey(nonce.NameNonce, nonce.GetSeqKey(signers)) prove := !viper.GetBool(commands.FlagTrustNode) height, err = query.GetParsed(key, &sequence, query.GetHeight(), prove) diff --git a/modules/nonce/errors.go b/modules/nonce/errors.go index 0d77b798427c..9d456dd650ec 100644 --- a/modules/nonce/errors.go +++ b/modules/nonce/errors.go @@ -4,8 +4,6 @@ package nonce import ( "fmt" - abci "github.com/tendermint/abci/types" - "github.com/cosmos/cosmos-sdk/errors" ) @@ -16,9 +14,9 @@ var ( errNoSigners = fmt.Errorf("There are no signers") errTxEmpty = fmt.Errorf("The provided Tx is empty") - unauthorized = abci.CodeType_Unauthorized - badNonce = abci.CodeType_BadNonce - invalidInput = abci.CodeType_BaseInvalidInput + unauthorized = errors.CodeTypeUnauthorized + badNonce = errors.CodeTypeBadNonce + invalidInput = errors.CodeTypeBaseInvalidInput ) func ErrBadNonce(got, expected uint32) errors.TMError { diff --git a/modules/nonce/tx_test.go b/modules/nonce/tx_test.go index e47a7711645c..84d62d4e887d 100644 --- a/modules/nonce/tx_test.go +++ b/modules/nonce/tx_test.go @@ -19,7 +19,7 @@ func TestNonce(t *testing.T) { chainID := "my-chain" chain2ID := "woohoo" - height := uint64(100) + height := int64(100) ctx := stack.MockContext(chainID, height) store := state.NewMemKVStore() diff --git a/modules/roles/commands/wrap.go b/modules/roles/commands/wrap.go index 9ea855e9e4c8..174113d20ff5 100644 --- a/modules/roles/commands/wrap.go +++ b/modules/roles/commands/wrap.go @@ -6,7 +6,6 @@ import ( "github.com/spf13/pflag" "github.com/spf13/viper" - abci "github.com/tendermint/abci/types" cmn "github.com/tendermint/tmlibs/common" sdk "github.com/cosmos/cosmos-sdk" @@ -53,7 +52,7 @@ func parseRole(role string) ([]byte, error) { res, err := hex.DecodeString(cmn.StripHex(role)) if err != nil { err = errors.WithMessage("Address is invalid hex", err, - abci.CodeType_EncodingError) + errors.CodeTypeEncodingErr) } return res, err } diff --git a/modules/roles/error.go b/modules/roles/error.go index 4abdbf895671..57e8914a463f 100644 --- a/modules/roles/error.go +++ b/modules/roles/error.go @@ -4,8 +4,6 @@ package roles import ( "fmt" - abci "github.com/tendermint/abci/types" - "github.com/cosmos/cosmos-sdk/errors" ) @@ -18,7 +16,7 @@ var ( errTooManyMembers = fmt.Errorf("Too many members specified") errNotEnoughMembers = fmt.Errorf("Not enough members specified") - unauthorized = abci.CodeType_Unauthorized + unauthorized = errors.CodeTypeUnauthorized ) // TODO: codegen? diff --git a/modules/roles/handler.go b/modules/roles/handler.go index f70091e89cdf..34d64391f23f 100644 --- a/modules/roles/handler.go +++ b/modules/roles/handler.go @@ -10,9 +10,9 @@ const ( //NameRole - name space of the roles module NameRole = "role" // CostCreate is the cost to create a new role - CostCreate = uint64(40) + CostCreate = int64(40) // CostAssume is the cost to assume a role as part of a tx - CostAssume = uint64(5) + CostAssume = int64(5) ) // Handler allows us to create new roles diff --git a/modules/roles/handler_test.go b/modules/roles/handler_test.go index f654f5acee05..7658ccdb7d72 100644 --- a/modules/roles/handler_test.go +++ b/modules/roles/handler_test.go @@ -44,7 +44,7 @@ func TestCreateRole(t *testing.T) { assert.Nil(err, "%d/%s: %+v", i, tc.role, err) assert.Nil(err2, "%d/%s: %+v", i, tc.role, err2) assert.Equal(roles.CostCreate, cres.GasAllocated) - assert.Equal(uint64(0), cres.GasPayment) + assert.Equal(int64(0), cres.GasPayment) } else { assert.NotNil(err, "%d/%s", i, tc.role) assert.NotNil(err2, "%d/%s", i, tc.role) diff --git a/modules/roles/middleware_test.go b/modules/roles/middleware_test.go index 459405cf9c66..7886e5ab6c48 100644 --- a/modules/roles/middleware_test.go +++ b/modules/roles/middleware_test.go @@ -99,8 +99,8 @@ func TestAssumeRole(t *testing.T) { assert.Nil(err, "%d: %+v", i, err) assert.Nil(err2, "%d: %+v", i, err2) // make sure we charge for each role - assert.Equal(roles.CostAssume*uint64(len(tc.roles)), cres.GasAllocated) - assert.Equal(uint64(0), cres.GasPayment) + assert.Equal(roles.CostAssume*int64(len(tc.roles)), cres.GasAllocated) + assert.Equal(int64(0), cres.GasPayment) } else { assert.NotNil(err, "%d", i) assert.NotNil(err2, "%d", i) diff --git a/modules/roles/rest/handlers.go b/modules/roles/rest/handlers.go index 1943634a34e4..315ddcb13dd0 100644 --- a/modules/roles/rest/handlers.go +++ b/modules/roles/rest/handlers.go @@ -37,7 +37,7 @@ type RoleInput struct { func decodeRoleHex(roleInHex string) ([]byte, error) { parsedRole, err := hex.DecodeString(common.StripHex(roleInHex)) if err != nil { - err = errors.WithMessage("invalid hex", err, abci.CodeType_EncodingError) + err = errors.WithMessage("invalid hex", err, errors.CodeTypeEncodingError) return nil, err } return parsedRole, nil diff --git a/stack/context.go b/stack/context.go index f923e89ad96d..fe01ec7059ec 100644 --- a/stack/context.go +++ b/stack/context.go @@ -20,7 +20,7 @@ type secureContext struct { } // NewContext - create a new secureContext -func NewContext(chain string, height uint64, logger log.Logger) sdk.Context { +func NewContext(chain string, height int64, logger log.Logger) sdk.Context { mock := MockContext(chain, height).(naiveContext) mock.Logger = logger return secureContext{ diff --git a/stack/mock.go b/stack/mock.go index 7327875f6a3e..67a2fa84cbae 100644 --- a/stack/mock.go +++ b/stack/mock.go @@ -11,7 +11,7 @@ import ( type naiveContext struct { id nonce chain string - height uint64 + height int64 perms []sdk.Actor log.Logger } @@ -19,7 +19,7 @@ type naiveContext struct { // MockContext returns a simple, non-checking context for test cases. // // Always use NewContext() for production code to sandbox malicious code better -func MockContext(chain string, height uint64) sdk.Context { +func MockContext(chain string, height int64) sdk.Context { return naiveContext{ id: nonce(rand.Int63()), chain: chain, @@ -34,7 +34,7 @@ func (c naiveContext) ChainID() string { return c.chain } -func (c naiveContext) BlockHeight() uint64 { +func (c naiveContext) BlockHeight() int64 { return c.height } diff --git a/state/bonsai.go b/state/bonsai.go index 2ab75b2df830..dfa3d3a9a886 100644 --- a/state/bonsai.go +++ b/state/bonsai.go @@ -54,8 +54,8 @@ func (b *Bonsai) GetWithProof(key []byte) ([]byte, iavl.KeyProof, error) { return b.Tree.GetWithProof(key) } -func (b *Bonsai) GetVersionedWithProof(key []byte, version uint64) ([]byte, iavl.KeyProof, error) { - return b.Tree.GetVersionedWithProof(key, version) +func (b *Bonsai) GetVersionedWithProof(key []byte, version int64) ([]byte, iavl.KeyProof, error) { + return b.Tree.GetVersionedWithProof(key, uint64(version)) } func (b *Bonsai) List(start, end []byte, limit int) []Model { diff --git a/state/errors.go b/state/errors.go index 54b5badd3d5d..2693e5a08b1a 100644 --- a/state/errors.go +++ b/state/errors.go @@ -4,7 +4,6 @@ package state import ( "fmt" - abci "github.com/tendermint/abci/types" "github.com/cosmos/cosmos-sdk/errors" ) @@ -13,7 +12,7 @@ var ( ) func ErrNotASubTransaction() errors.TMError { - return errors.WithCode(errNotASubTransaction, abci.CodeType_InternalError) + return errors.WithCode(errNotASubTransaction, errors.CodeTypeInternalErr) } func IsNotASubTransactionErr(err error) bool { return errors.IsSameError(errNotASubTransaction, err) diff --git a/state/merkle.go b/state/merkle.go index 7bfabc43752c..7d11aa8ddb58 100644 --- a/state/merkle.go +++ b/state/merkle.go @@ -8,12 +8,12 @@ type State struct { committed *Bonsai deliverTx SimpleDB checkTx SimpleDB - historySize uint64 + historySize int64 } // NewState wraps a versioned tree and maintains all needed // states for the abci app -func NewState(tree *iavl.VersionedTree, historySize uint64) *State { +func NewState(tree *iavl.VersionedTree, historySize int64) *State { base := NewBonsai(tree) return &State{ committed: base, @@ -64,7 +64,7 @@ func (s State) LatestHash() []byte { } // Commit saves persistent nodes to the database and re-copies the trees -func (s *State) Commit(version uint64) ([]byte, error) { +func (s *State) Commit(version int64) ([]byte, error) { // commit (if we didn't do hash earlier) err := s.committed.Commit(s.deliverTx) if err != nil { @@ -74,7 +74,7 @@ func (s *State) Commit(version uint64) ([]byte, error) { // store a new version var hash []byte if !s.IsEmpty() { - hash, err = s.committed.Tree.SaveVersion(version) + hash, err = s.committed.Tree.SaveVersion(uint64(version)) if err != nil { return nil, err } @@ -82,7 +82,7 @@ func (s *State) Commit(version uint64) ([]byte, error) { // release an old version if version > s.historySize { - s.committed.Tree.DeleteVersion(version - s.historySize) + s.committed.Tree.DeleteVersion(uint64(version - s.historySize)) } s.deliverTx = s.committed.Checkpoint() diff --git a/state/merkle_test.go b/state/merkle_test.go index 5fc7e9e56a91..1bb5ee53cc3f 100644 --- a/state/merkle_test.go +++ b/state/merkle_test.go @@ -77,7 +77,7 @@ func TestStateCommitHash(t *testing.T) { deliver.Set(k, v) } // commit and add hash to result - hash, err := store.Commit(uint64(n + 1)) + hash, err := store.Commit(int64(n + 1)) require.Nil(err, "tc:%d / rnd:%d - %+v", i, n, err) result[n] = hash } diff --git a/state/queue.go b/state/queue.go index 756f90bb644e..e4629414d7d6 100644 --- a/state/queue.go +++ b/state/queue.go @@ -19,15 +19,15 @@ func QueueTailKey() []byte { } // QueueItemKey gives us the key to look up one item by sequence -func QueueItemKey(i uint64) []byte { +func QueueItemKey(i int64) []byte { return makeKey(i) } // Queue allows us to fill up a range of the db, and grab from either end type Queue struct { store KVStore - head uint64 // if Size() > 0, the first element is here - tail uint64 // this is the first empty slot to Push() to + head int64 // if Size() > 0, the first element is here + tail int64 // this is the first empty slot to Push() to } // NewQueue will load or initialize a queue in this state-space @@ -41,7 +41,7 @@ func NewQueue(store KVStore) *Queue { } // Tail returns the next slot that Push() will use -func (q *Queue) Tail() uint64 { +func (q *Queue) Tail() int64 { return q.tail } @@ -51,7 +51,7 @@ func (q *Queue) Size() int { } // Push adds an element to the tail of the queue and returns it's location -func (q *Queue) Push(value []byte) uint64 { +func (q *Queue) Push(value []byte) int64 { key := makeKey(q.tail) q.store.Set(key, value) q.tail++ @@ -72,31 +72,32 @@ func (q *Queue) Pop() []byte { } // Item looks at any element in the queue, without modifying anything -func (q *Queue) Item(seq uint64) []byte { +func (q *Queue) Item(seq int64) []byte { if seq >= q.tail || seq < q.head { return nil } return q.store.Get(makeKey(seq)) } -func (q *Queue) setCount(key []byte, val uint64) { +func (q *Queue) setCount(key []byte, val int64) { b := make([]byte, 8) - binary.BigEndian.PutUint64(b, val) + binary.BigEndian.PutUint64(b, uint64(val)) q.store.Set(key, b) } -func (q *Queue) getCount(key []byte) (val uint64) { +func (q *Queue) getCount(key []byte) (val int64) { b := q.store.Get(key) + var v uint64 if b != nil { - val = binary.BigEndian.Uint64(b) + v = binary.BigEndian.Uint64(b) } - return val + return int64(v) } // makeKey returns the key for a data point -func makeKey(val uint64) []byte { +func makeKey(val int64) []byte { b := make([]byte, 8+len(dataKey)) copy(b, dataKey) - binary.BigEndian.PutUint64(b[len(dataKey):], val) + binary.BigEndian.PutUint64(b[len(dataKey):], uint64(val)) return b } diff --git a/state/queue_test.go b/state/queue_test.go index d6212be90e4c..21d466debad5 100644 --- a/state/queue_test.go +++ b/state/queue_test.go @@ -44,7 +44,7 @@ func TestQueue(t *testing.T) { q := NewQueue(store) for j, in := range tc.pushes { cnt := q.Push(in) - assert.Equal(uint64(j), cnt, "%d", i) + assert.Equal(int64(j), cnt, "%d", i) } assert.EqualValues(len(tc.pushes), q.Size()) diff --git a/state/span.go b/state/span.go index 5b97084179fc..a3a65d8b7f3b 100644 --- a/state/span.go +++ b/state/span.go @@ -18,7 +18,7 @@ var ( type Span struct { store KVStore // keys is sorted ascending and cannot contain duplicates - keys []uint64 + keys []int64 } // NewSpan loads or initializes a span of keys @@ -29,7 +29,7 @@ func NewSpan(store KVStore) *Span { } // Set puts a value at a given height -func (s *Span) Set(h uint64, value []byte) { +func (s *Span) Set(h int64, value []byte) { key := makeKey(h) s.store.Set(key, value) s.addKey(h) @@ -37,13 +37,13 @@ func (s *Span) Set(h uint64, value []byte) { } // Get returns the element at h if it exists -func (s *Span) Get(h uint64) []byte { +func (s *Span) Get(h int64) []byte { key := makeKey(h) return s.store.Get(key) } // Bottom returns the lowest element in the Span, along with its index -func (s *Span) Bottom() ([]byte, uint64) { +func (s *Span) Bottom() ([]byte, int64) { if len(s.keys) == 0 { return nil, 0 } @@ -52,7 +52,7 @@ func (s *Span) Bottom() ([]byte, uint64) { } // Top returns the highest element in the Span, along with its index -func (s *Span) Top() ([]byte, uint64) { +func (s *Span) Top() ([]byte, int64) { l := len(s.keys) if l == 0 { return nil, 0 @@ -62,7 +62,7 @@ func (s *Span) Top() ([]byte, uint64) { } // GTE returns the lowest element in the Span that is >= h, along with its index -func (s *Span) GTE(h uint64) ([]byte, uint64) { +func (s *Span) GTE(h int64) ([]byte, int64) { for _, k := range s.keys { if k >= h { return s.Get(k), k @@ -73,8 +73,8 @@ func (s *Span) GTE(h uint64) ([]byte, uint64) { // LTE returns the highest element in the Span that is <= h, // along with its index -func (s *Span) LTE(h uint64) ([]byte, uint64) { - var k uint64 +func (s *Span) LTE(h int64) ([]byte, int64) { + var k int64 // start from the highest and go down for the first match for i := len(s.keys) - 1; i >= 0; i-- { k = s.keys[i] @@ -86,7 +86,7 @@ func (s *Span) LTE(h uint64) ([]byte, uint64) { } // addKey inserts this key, maintaining sorted order, no duplicates -func (s *Span) addKey(h uint64) { +func (s *Span) addKey(h int64) { for i, k := range s.keys { // don't add duplicates if h == k { diff --git a/state/span_test.go b/state/span_test.go index 8362f3d90f56..b8c708fa81b7 100644 --- a/state/span_test.go +++ b/state/span_test.go @@ -8,7 +8,7 @@ import ( ) type kv struct { - k uint64 + k int64 v []byte } @@ -28,7 +28,7 @@ func TestBasicSpan(t *testing.T) { lots := make([]kv, 1000) for i := range lots { - lots[i] = kv{uint64(3 * i), []byte{byte(i / 100), byte(i % 100)}} + lots[i] = kv{int64(3 * i), []byte{byte(i / 100), byte(i % 100)}} } cases := []bscase{ From efbc4b99586e5e37be2aca004141ad2adde8ccfe Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 8 Dec 2017 19:41:38 -0500 Subject: [PATCH 094/117] client: subscribe event->query --- client/proxy.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/proxy.go b/client/proxy.go index 0acb79031ad0..26d12069c16a 100644 --- a/client/proxy.go +++ b/client/proxy.go @@ -49,8 +49,8 @@ func RPCRoutes(c rpcclient.Client) map[string]*rpc.RPCFunc { // Subscribe/unsubscribe are reserved for websocket events. // We can just use the core tendermint impl, which uses the // EventSwitch we registered in NewWebsocketManager above - "subscribe": rpc.NewWSRPCFunc(core.Subscribe, "event"), - "unsubscribe": rpc.NewWSRPCFunc(core.Unsubscribe, "event"), + "subscribe": rpc.NewWSRPCFunc(core.Subscribe, "query"), + "unsubscribe": rpc.NewWSRPCFunc(core.Unsubscribe, "query"), // info API "status": rpc.NewRPCFunc(c.Status, ""), From f00ce7aeca04db15ff6df3b1f272493ba9e79104 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sun, 10 Dec 2017 15:55:52 -0500 Subject: [PATCH 095/117] fix unit tests --- app/app_test.go | 14 +++++++------- app/store.go | 6 +++--- app/val_test.go | 2 +- client/query_test.go | 4 ++-- errors/code.go | 19 +++++++++---------- errors/main.go | 4 ++-- errors/main_test.go | 18 ++++++++---------- examples/basecoin/cmd/baseserver/main.go | 9 ++++++--- examples/counter/plugins/counter/counter.go | 3 +-- .../counter/plugins/counter/counter_test.go | 4 ++-- modules/coin/ibc_test.go | 6 +++--- modules/coin/rest/handlers.go | 5 +++-- modules/eyes/errors.go | 4 +--- modules/ibc/ibc_test.go | 6 +++--- modules/ibc/provider_test.go | 4 ++-- modules/nonce/rest/handlers.go | 5 +++-- modules/roles/rest/handlers.go | 3 +-- state/merkle.go | 4 ++-- 18 files changed, 59 insertions(+), 61 deletions(-) diff --git a/app/app_test.go b/app/app_test.go index ac5b1b890990..6c4d88dd5211 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -118,7 +118,7 @@ func (at *appTest) reset() { at.initAccount(at.acctOut) resabci := at.app.Commit() - require.True(at.t, resabci.Code.IsOK(), resabci) + require.True(at.t, resabci.IsOK(), resabci) } func getBalance(key sdk.Actor, store state.SimpleDB) (coin.Coins, error) { @@ -145,7 +145,7 @@ func (at *appTest) execDeliver(t *testing.T, tx sdk.Tx) (res abci.ResponseDelive res = at.app.DeliverTx(txBytes) // check the tags - if res.Code.IsOK() { + if res.IsOK() { tags := res.Tags require.NotEmpty(tags) require.Equal("height", tags[0].Key) @@ -270,13 +270,13 @@ func TestTx(t *testing.T) { //Regular CheckTx at.reset() cres, _, _ = at.execCheck(t, at.getTx(coin.Coins{{"mycoin", 5}}, 1)) - assert.True(cres.Code.IsOK(), "ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", cres) + assert.True(cres.IsOK(), "ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", cres) //Regular DeliverTx at.reset() amt := coin.Coins{{"mycoin", 3}} dres, diffIn, diffOut = at.execDeliver(t, at.getTx(amt, 1)) - assert.True(dres.Code.IsOK(), "ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", dres) + assert.True(dres.IsOK(), "ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", dres) assert.Equal(amt.Negative(), diffIn) assert.Equal(amt, diffOut) @@ -285,7 +285,7 @@ func TestTx(t *testing.T) { amt = coin.Coins{{"mycoin", 4}} toll := coin.Coin{"mycoin", 1} dres, diffIn, diffOut = at.execDeliver(t, at.feeTx(amt, toll, 1)) - assert.True(dres.Code.IsOK(), "ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", dres) + assert.True(dres.IsOK(), "ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", dres) payment := amt.Plus(coin.Coins{toll}).Negative() assert.Equal(payment, diffIn) assert.Equal(amt, diffOut) @@ -297,7 +297,7 @@ func TestQuery(t *testing.T) { at := newAppTest(t) dres, _, _ := at.execDeliver(t, at.getTx(coin.Coins{{"mycoin", 5}}, 1)) - assert.True(dres.Code.IsOK(), "Commit, DeliverTx: Expected OK return from DeliverTx, Error: %v", dres) + assert.True(dres.IsOK(), "Commit, DeliverTx: Expected OK return from DeliverTx, Error: %v", dres) resQueryPreCommit := at.app.Query(abci.RequestQuery{ Path: "/account", @@ -305,7 +305,7 @@ func TestQuery(t *testing.T) { }) cres := at.app.Commit() - assert.True(cres.Code.IsOK(), cres) + assert.True(cres.IsOK(), cres) key := stack.PrefixedKey(coin.NameCoin, at.acctIn.Address()) resQueryPostCommit := at.app.Query(abci.RequestQuery{ diff --git a/app/store.go b/app/store.go index 3b523f3e5cc0..6ea079b7bc14 100644 --- a/app/store.go +++ b/app/store.go @@ -135,7 +135,7 @@ func (app *StoreApp) SetOption(res abci.RequestSetOption) abci.ResponseSetOption func (app *StoreApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) { if len(reqQuery.Data) == 0 { resQuery.Log = "Query cannot be zero length" - resQuery.Code = abci.CodeType_EncodingError + resQuery.Code = errors.CodeTypeEncodingErr return } @@ -150,7 +150,7 @@ func (app *StoreApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQu // is not yet in the blockchain withProof := app.CommittedHeight() - 1 - if tree.Tree.VersionExists(withProof) { + if tree.Tree.VersionExists(uint64(withProof)) { height = withProof } else { height = app.CommittedHeight() @@ -176,7 +176,7 @@ func (app *StoreApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQu } default: - resQuery.Code = abci.CodeType_UnknownRequest + resQuery.Code = errors.CodeTypeUnknownRequest resQuery.Log = cmn.Fmt("Unexpected Query path: %v", reqQuery.Path) } return diff --git a/app/val_test.go b/app/val_test.go index 677a903ea9d6..5c976806740e 100644 --- a/app/val_test.go +++ b/app/val_test.go @@ -79,7 +79,7 @@ func TestEndBlock(t *testing.T) { tx := base.ValChangeTx{c}.Wrap() txBytes := wire.BinaryBytes(tx) res := app.DeliverTx(txBytes) - require.True(res.Code.IsOK(), "%#v", res) + require.True(res.IsOK(), "%#v", res) } diff := app.EndBlock(abci.RequestEndBlock{app.height}) // TODO: don't care about order here... diff --git a/client/query_test.go b/client/query_test.go index 8f93ff40044d..f6e049a7a532 100644 --- a/client/query_test.go +++ b/client/query_test.go @@ -55,7 +55,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 := int(br.Height) + brh := br.Height // This sets up our trust on the node based on some past point. source := certclient.NewProvider(cl) @@ -119,7 +119,7 @@ func TestTxProofs(t *testing.T) { require.NoError(err, "%+v", err) require.EqualValues(0, br.CheckTx.Code, "%#v", br.CheckTx) require.EqualValues(0, br.DeliverTx.Code) - brh := int(br.Height) + brh := br.Height source := certclient.NewProvider(cl) seed, err := source.GetByHeight(brh - 2) diff --git a/errors/code.go b/errors/code.go index ec9a24cf35d7..c49223898f80 100644 --- a/errors/code.go +++ b/errors/code.go @@ -1,15 +1,14 @@ package errors const ( - defaultErrCode uint32 = 0x1 + CodeTypeInternalErr uint32 = 1 + CodeTypeEncodingErr uint32 = 2 + CodeTypeUnauthorized uint32 = 3 + CodeTypeUnknownRequest uint32 = 4 + CodeTypeUnknownAddress uint32 = 5 + CodeTypeBaseUnknownAddress uint32 = 5 // lol fuck it + CodeTypeBadNonce uint32 = 6 - CodeTypeInternalErr uint32 = 0 - CodeTypeEncodingErr uint32 = 1 - CodeTypeUnauthorized uint32 = 2 - CodeTypeUnknownRequest uint32 = 3 - CodeTypeUnknownAddress uint32 = 4 - CodeTypeBaseUnknownAddress uint32 = 4 // lol fuck it - CodeTypeBadNonce uint32 = 5 - CodeTypeBaseInvalidInput uint32 = 20 - CodeTypeBaseInvalidOutput uint32 = 21 + CodeTypeBaseInvalidInput uint32 = 20 + CodeTypeBaseInvalidOutput uint32 = 21 ) diff --git a/errors/main.go b/errors/main.go index 9cfbe61978dc..6fd8c176f638 100644 --- a/errors/main.go +++ b/errors/main.go @@ -95,7 +95,7 @@ func Wrap(err error) TMError { return tm } - return WithCode(err, defaultErrCode) + return WithCode(err, CodeTypeInternalErr) } // WithCode adds a stacktrace if necessary and sets the code and msg, @@ -145,5 +145,5 @@ func HasErrorCode(err error, code uint32) bool { if tm, ok := err.(TMError); ok { return tm.ErrorCode() == code } - return code == defaultErrCode + return code == CodeTypeInternalErr } diff --git a/errors/main_test.go b/errors/main_test.go index f8f60845d25b..b9393c881d03 100644 --- a/errors/main_test.go +++ b/errors/main_test.go @@ -7,8 +7,6 @@ import ( pkerr "github.com/pkg/errors" "github.com/stretchr/testify/assert" - - abci "github.com/tendermint/abci/types" ) func TestCreateResult(t *testing.T) { @@ -17,15 +15,15 @@ func TestCreateResult(t *testing.T) { cases := []struct { err error msg string - code abci.CodeType + code uint32 }{ - {stderr.New("base"), "base", defaultErrCode}, - {pkerr.New("dave"), "dave", defaultErrCode}, - {New("nonce", abci.CodeType_BadNonce), "nonce", abci.CodeType_BadNonce}, - {Wrap(stderr.New("wrap")), "wrap", defaultErrCode}, - {WithCode(stderr.New("coded"), abci.CodeType_BaseInvalidInput), "coded", abci.CodeType_BaseInvalidInput}, - {ErrDecoding(), errDecoding.Error(), abci.CodeType_EncodingError}, - {ErrUnauthorized(), errUnauthorized.Error(), abci.CodeType_Unauthorized}, + {stderr.New("base"), "base", CodeTypeInternalErr}, + {pkerr.New("dave"), "dave", CodeTypeInternalErr}, + {New("nonce", CodeTypeBadNonce), "nonce", CodeTypeBadNonce}, + {Wrap(stderr.New("wrap")), "wrap", CodeTypeInternalErr}, + {WithCode(stderr.New("coded"), CodeTypeBaseInvalidInput), "coded", CodeTypeBaseInvalidInput}, + {ErrDecoding(), errDecoding.Error(), CodeTypeEncodingErr}, + {ErrUnauthorized(), errUnauthorized.Error(), CodeTypeUnauthorized}, } for idx, tc := range cases { diff --git a/examples/basecoin/cmd/baseserver/main.go b/examples/basecoin/cmd/baseserver/main.go index d41ac45a6de6..99c686d5620e 100644 --- a/examples/basecoin/cmd/baseserver/main.go +++ b/examples/basecoin/cmd/baseserver/main.go @@ -10,13 +10,16 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + rpcserver "github.com/tendermint/tendermint/rpc/lib/server" + "github.com/tendermint/tmlibs/cli" + tmlog "github.com/tendermint/tmlibs/log" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/commands" rest "github.com/cosmos/cosmos-sdk/client/rest" coinrest "github.com/cosmos/cosmos-sdk/modules/coin/rest" noncerest "github.com/cosmos/cosmos-sdk/modules/nonce/rest" rolerest "github.com/cosmos/cosmos-sdk/modules/roles/rest" - "github.com/tendermint/tmlibs/cli" ) var srvCli = &cobra.Command{ @@ -79,13 +82,13 @@ func serve(cmd *cobra.Command, args []string) error { port := viper.GetInt(envPortFlag) addr := fmt.Sprintf(":%d", port) - onDisconnect := rpc.OnDisconnect(func(remoteAddr string) { + onDisconnect := rpcserver.OnDisconnect(func(remoteAddr string) { // FIXME: TODO // n.eventBus.UnsubscribeAll(context.Background(), remoteAddr) }) routes := client.RPCRoutes(rpcClient) wm := rpcserver.NewWebsocketManager(routes, onDisconnect) - wsLogger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "ws") + wsLogger := tmlog.NewTMLogger(tmlog.NewSyncWriter(os.Stdout)).With("module", "ws") wm.SetLogger(wsLogger) router.HandleFunc("/websocket", wm.WebsocketHandler) diff --git a/examples/counter/plugins/counter/counter.go b/examples/counter/plugins/counter/counter.go index 7ce08761db46..6cfd05d65dc8 100644 --- a/examples/counter/plugins/counter/counter.go +++ b/examples/counter/plugins/counter/counter.go @@ -3,7 +3,6 @@ package counter import ( "fmt" - abci "github.com/tendermint/abci/types" "github.com/tendermint/go-wire" sdk "github.com/cosmos/cosmos-sdk" @@ -74,7 +73,7 @@ var ( // ErrInvalidCounter - custom error class func ErrInvalidCounter() error { - return errors.WithCode(errInvalidCounter, abci.CodeType_BaseInvalidInput) + return errors.WithCode(errInvalidCounter, errors.CodeTypeBaseInvalidInput) } // IsInvalidCounterErr - custom error class check diff --git a/examples/counter/plugins/counter/counter_test.go b/examples/counter/plugins/counter/counter_test.go index f727bb571577..34269d273b1b 100644 --- a/examples/counter/plugins/counter/counter_test.go +++ b/examples/counter/plugins/counter/counter_test.go @@ -53,7 +53,7 @@ func TestCounterPlugin(t *testing.T) { // Test a basic send, no fee res := DeliverCounterTx(true, nil, 1) - assert.True(res.Code.IsOK(), res.String()) + assert.True(res.IsOK(), res.String()) // Test an invalid send, no fee res = DeliverCounterTx(false, nil, 2) @@ -65,7 +65,7 @@ func TestCounterPlugin(t *testing.T) { // Test an valid send, with supported fee res = DeliverCounterTx(true, coin.Coins{{"gold", 100}}, 3) - assert.True(res.Code.IsOK(), res.String()) + assert.True(res.IsOK(), res.String()) // Test unsupported fee res = DeliverCounterTx(true, coin.Coins{{"silver", 100}}, 4) diff --git a/modules/coin/ibc_test.go b/modules/coin/ibc_test.go index a51b5359d893..f350171f4cd6 100644 --- a/modules/coin/ibc_test.go +++ b/modules/coin/ibc_test.go @@ -3,14 +3,14 @@ package coin import ( "testing" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" sdk "github.com/cosmos/cosmos-sdk" "github.com/cosmos/cosmos-sdk/errors" "github.com/cosmos/cosmos-sdk/modules/auth" "github.com/cosmos/cosmos-sdk/modules/ibc" "github.com/cosmos/cosmos-sdk/stack" "github.com/cosmos/cosmos-sdk/state" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" wire "github.com/tendermint/go-wire" ) @@ -24,7 +24,7 @@ func TestIBCPostPacket(t *testing.T) { otherID := "chain-2" ourID := "dex" - start := 200 + start := int64(200) // create the app and our chain app := stack.New(). diff --git a/modules/coin/rest/handlers.go b/modules/coin/rest/handlers.go index 2e1841f8ae30..8559c642ed9d 100644 --- a/modules/coin/rest/handlers.go +++ b/modules/coin/rest/handlers.go @@ -48,14 +48,15 @@ func doQueryAccount(w http.ResponseWriter, r *http.Request) { return } - var h int + var h int64 qHeight := r.URL.Query().Get("height") if qHeight != "" { - h, err = strconv.Atoi(qHeight) + _h, err := strconv.Atoi(qHeight) if err != nil { common.WriteError(w, err) return } + h = int64(_h) } actor = coin.ChainAddr(actor) diff --git a/modules/eyes/errors.go b/modules/eyes/errors.go index 286e24776e6c..55ad167f0a6d 100644 --- a/modules/eyes/errors.go +++ b/modules/eyes/errors.go @@ -3,15 +3,13 @@ package eyes import ( "fmt" - abci "github.com/tendermint/abci/types" - "github.com/cosmos/cosmos-sdk/errors" ) var ( errMissingData = fmt.Errorf("All tx fields must be filled") - malformed = errors.CodeTypeEncodingError + malformed = errors.CodeTypeEncodingErr ) //nolint diff --git a/modules/ibc/ibc_test.go b/modules/ibc/ibc_test.go index 659d28456cae..42166218a728 100644 --- a/modules/ibc/ibc_test.go +++ b/modules/ibc/ibc_test.go @@ -150,7 +150,7 @@ func TestIBCUpdate(t *testing.T) { // this is the root seed, that others are evaluated against keys := lite.GenValKeys(7) appHash := []byte{0, 4, 7, 23} - start := 100 // initial height + start := int64(100) // initial height root := genEmptyCommit(keys, "chain-1", 100, appHash, len(keys)) keys2 := keys.Extend(2) @@ -225,7 +225,7 @@ func TestIBCCreatePacket(t *testing.T) { // this is the root seed, that others are evaluated against keys := lite.GenValKeys(7) appHash := []byte{1, 2, 3, 4} - start := 100 // initial height + start := int64(100) // initial height chainID := "cosmos-hub" root := genEmptyCommit(keys, chainID, start, appHash, len(keys)) @@ -327,7 +327,7 @@ func TestIBCPostPacket(t *testing.T) { otherID := "chain-1" ourID := "hub" - start := 200 + start := int64(200) msg := "it's okay" // create the app and our chain diff --git a/modules/ibc/provider_test.go b/modules/ibc/provider_test.go index 120253312a42..4690198c7960 100644 --- a/modules/ibc/provider_test.go +++ b/modules/ibc/provider_test.go @@ -83,7 +83,7 @@ func makeCommits(keys lite.ValKeys, count int, chainID, app string) []lite.FullC // two commits for each validator, to check how we handle dups // (10, 0), (10, 1), (10, 1), (10, 2), (10, 2), ... vals := keys.ToValidators(10, int64(count/2)) - h := 20 + 10*i + h := int64(20 + 10*i) commits[i] = keys.GenFullCommit(chainID, h, nil, vals, appHash, 0, len(keys)) } return commits @@ -130,7 +130,7 @@ func checkProvider(t *testing.T, p lite.Provider, chainID, app string) { fc, err = p.GetByHeight(47) if assert.Nil(err) { // we only step by 10, so 40 must be the one below this - assert.Equal(40, fc.Height()) + assert.Equal(int64(40), fc.Height()) } } diff --git a/modules/nonce/rest/handlers.go b/modules/nonce/rest/handlers.go index 05c0b2cd899c..9186f6c36a60 100644 --- a/modules/nonce/rest/handlers.go +++ b/modules/nonce/rest/handlers.go @@ -30,14 +30,15 @@ func doQueryNonce(w http.ResponseWriter, r *http.Request) { return } - var h int + var h int64 qHeight := r.URL.Query().Get("height") if qHeight != "" { - h, err = strconv.Atoi(qHeight) + _h, err := strconv.Atoi(qHeight) if err != nil { common.WriteError(w, err) return } + h = int64(_h) } actor = coin.ChainAddr(actor) diff --git a/modules/roles/rest/handlers.go b/modules/roles/rest/handlers.go index 315ddcb13dd0..4d5f08b9710a 100644 --- a/modules/roles/rest/handlers.go +++ b/modules/roles/rest/handlers.go @@ -6,7 +6,6 @@ import ( "github.com/gorilla/mux" - abci "github.com/tendermint/abci/types" sdk "github.com/cosmos/cosmos-sdk" "github.com/cosmos/cosmos-sdk/client/commands" "github.com/cosmos/cosmos-sdk/errors" @@ -37,7 +36,7 @@ type RoleInput struct { func decodeRoleHex(roleInHex string) ([]byte, error) { parsedRole, err := hex.DecodeString(common.StripHex(roleInHex)) if err != nil { - err = errors.WithMessage("invalid hex", err, errors.CodeTypeEncodingError) + err = errors.WithMessage("invalid hex", err, errors.CodeTypeEncodingErr) return nil, err } return parsedRole, nil diff --git a/state/merkle.go b/state/merkle.go index 7d11aa8ddb58..2ee244249926 100644 --- a/state/merkle.go +++ b/state/merkle.go @@ -53,8 +53,8 @@ func (s State) Check() SimpleDB { } // LatestHeight is the last block height we have committed -func (s State) LatestHeight() uint64 { - return s.committed.Tree.LatestVersion() +func (s State) LatestHeight() int64 { + return int64(s.committed.Tree.LatestVersion()) } // LatestHash is the root hash of the last state we have From 71d8b36b619a3f200369ec9134ec4dd9cab5e99e Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sun, 10 Dec 2017 22:14:59 +0000 Subject: [PATCH 096/117] upgrade successful tx codes bash common --- tests/cli/common.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/cli/common.sh b/tests/cli/common.sh index 8675cb7802d7..28e44e56cb0c 100644 --- a/tests/cli/common.sh +++ b/tests/cli/common.sh @@ -87,9 +87,9 @@ indexer = "kv" index_tags = "height,coin.sender,coin.receiver" EOF - echo "Starting ${SERVER_EXE} server..." - startServer $SERVE_DIR $SERVER_LOG - return $? +echo "Starting ${SERVER_EXE} server..." +startServer $SERVE_DIR $SERVER_LOG +return $? } # XXX Ex Usage: startServer $SERVE_DIR $SERVER_LOG @@ -181,8 +181,8 @@ checkRole() { txSucceeded() { if (assertTrue "line=${LINENO}, sent tx ($3): $2" $1); then TX=$2 - assertEquals "line=${LINENO}, good check ($3): $TX" null $(echo $TX | jq .check_tx.code) - assertEquals "line=${LINENO}, good deliver ($3): $TX" null $(echo $TX | jq .deliver_tx.code) + assertEquals "line=${LINENO}, good check ($3): $TX" 0 $(echo $TX | jq .check_tx.code) + assertEquals "line=${LINENO}, good deliver ($3): $TX" 0 $(echo $TX | jq .deliver_tx.code) else return 1 fi From ec42d83cf3efea7ffec57d37900992c7034acead Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Mon, 6 Nov 2017 16:06:49 -0500 Subject: [PATCH 097/117] docs: pull in staking docs --- docs/conf.py | 8 +++++++- docs/index.rst | 14 +++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index ff69cce3344c..b0b25cb494e9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -20,6 +20,8 @@ # import sys # sys.path.insert(0, os.path.abspath('.')) +import urllib + import sphinx_rtd_theme # -- General configuration ------------------------------------------------ @@ -169,5 +171,9 @@ 'Miscellaneous'), ] +repo = "https://raw/githubusercontent.com/cosmos/gaia/" +branch = "docs" # will become master +directory = "docs" - +urllib.urlretrieve(repo+branch+directory+'atlas-testnet.rst', filename='atlas-testnet.rst') +urllib.urlretrieve(repo+branch+directory+'local-testnet.rst', filename='local-testnet.rst') diff --git a/docs/index.rst b/docs/index.rst index 77f41c985f48..349d2784ffa2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -4,13 +4,16 @@ contain the root `toctree` directive. Welcome to the Cosmos SDK! -====================================== +========================== .. image:: graphics/cosmos-sdk-image.png :height: 250px :width: 500px :align: center +SDK and Basecoin +---------------- + .. toctree:: :maxdepth: 2 @@ -25,3 +28,12 @@ Welcome to the Cosmos SDK! ibc.rst glossary.rst stdlib.rst + +Staking Module +-------------- + +.. toctree:: + :maxdepth: 2 + + atlas-testnet.rst + local-testnet.rst From 8c0f414296dea8f20aead3d2d0f724859349d4be Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Sat, 25 Nov 2017 14:47:35 +0000 Subject: [PATCH 098/117] docs: revert conf.py, add gaia docs --- docs/atlas-testnet.rst | 95 ++++++++++++++++++++++++++ docs/conf.py | 9 --- docs/local-testnet.rst | 148 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 243 insertions(+), 9 deletions(-) create mode 100644 docs/atlas-testnet.rst create mode 100644 docs/local-testnet.rst diff --git a/docs/atlas-testnet.rst b/docs/atlas-testnet.rst new file mode 100644 index 000000000000..2f78e9e63d83 --- /dev/null +++ b/docs/atlas-testnet.rst @@ -0,0 +1,95 @@ +Atlas Testnet Example +===================== + +Atlas is a community testnet which can be used to test setting up a +cosmos validator node. In addition to this tutorial you can also +follow `this video `__. + +To work on the Atlas you will need some tokens to get started. To do +this first generate a new key: + +:: + + gaia keys new bob + gaia keys list + +This will output a bunch of information. Read it carefully, then enter +your key into `this utility `__ with +your key address and it will send you some ``fermion`` testnet tokens :). +Fermions are the native staking token on the Atlas tesnet; see below for +information on checking your balance. + +Now, to sync with the testnet, we need the genesis file and seeds. The +easiest way to get them is to clone and navigate to the tendermint +testnet repo: + +:: + + git clone https://github.com/tendermint/testnets ~/testnets + cd ~/testnets/gaia-1/gaia + +Now we can start a new node in the background; note that it may +take awhile to sync with the existing testnet. + +:: + + gaia node start --home=$HOME/testnets/gaia-1/gaia + +Once blocks slow down to about one block per second, you're all caught up. + +The ``gaia node start`` command will automaticaly generate a validator +private key found in ``~/testnets/gaia-1/gaia/priv_validator.json``. +Let's get the pubkey data for our validator node. The pubkey is located under +``"pub_key"{"data":`` within the json file + +:: + + cat ~/testnets/gaia-1/gaia/priv_validator.json + PUBKEY= + +If you have a json parser like ``jq``, you can get the pubkey like so: + +:: + + PUBKEY=$(cat $GAIANET/priv_validator.json | jq -r .pub_key.data) + +Next let's initialize the gaia client to start interacting with the +testnet: + +:: + + gaia init --chain-id=atlas --node=tcp://localhost:46657 + +And check our balance: + +:: + + gaia query account $MYADDR + +Where ``$MYADDR`` is the address originally generated by ``gaia keys new bob``. + +We are now ready to bond some tokens: + +:: + + gaia tx bond --amount=5fermion --name=bob --pubkey=$PUBKEY + +Bonding tokens means that your balance is tied up as *stake*. Don't +worry, you'll be able to get it back later. As soon as some tokens have +been bonded the validator node which we started earlier will have power +in the network and begin to participate in consensus! + +We can now check the validator set and see that we are a part of the +club! + +:: + + gaia query validators + +Finally lets unbond to get back our tokens + +:: + + gaia tx unbond --amount=5fermion --name=bob + +Remember to unbond before stopping your node, otherwise ... ? diff --git a/docs/conf.py b/docs/conf.py index b0b25cb494e9..3af51ef95904 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -20,8 +20,6 @@ # import sys # sys.path.insert(0, os.path.abspath('.')) -import urllib - import sphinx_rtd_theme # -- General configuration ------------------------------------------------ @@ -170,10 +168,3 @@ author, 'Cosmos-SDK', 'One line description of project.', 'Miscellaneous'), ] - -repo = "https://raw/githubusercontent.com/cosmos/gaia/" -branch = "docs" # will become master -directory = "docs" - -urllib.urlretrieve(repo+branch+directory+'atlas-testnet.rst', filename='atlas-testnet.rst') -urllib.urlretrieve(repo+branch+directory+'local-testnet.rst', filename='local-testnet.rst') diff --git a/docs/local-testnet.rst b/docs/local-testnet.rst new file mode 100644 index 000000000000..63c530188017 --- /dev/null +++ b/docs/local-testnet.rst @@ -0,0 +1,148 @@ +Local Testnet Example +===================== + +This tutorial demonstrates the basics of setting up a gaia +testnet locally + +First, generate a new key with a name, and save the address: + +:: + + gaia keys new alice + gaia keys list + +This will output: + +:: + + Enter a passphrase: + Repeat the passphrase: + alice E9E103F788AADD9C0842231E496B2139C118FA60 + **Important** write this seed phrase in a safe place. + It is the only way to recover your account if you ever forget your password. + + inject position weather divorce shine immense middle affair piece oval silver type until spike educate abandon + +which has your address and will be re-used throughout this tutorial. +We recommend doing something like ``MYADDR=``. Writing +down the recovery phrase is crucial for production keys, however, +for the tutorial you can skip this step. + +Now initialize a gaia chain: + +:: + + gaia node init E9E103F788AADD9C0842231E496B2139C118FA60 --home=$HOME/.gaia1 --chain-id=gaia-test + +This will create all the files necessary to run a single node chain in +``$HOME/.gaia1``: a ``priv_validator.json`` file with the validators +private key, and a ``genesis.json`` file with the list of validators and +accounts. In this case, we have one random validator, and ``$MYADDR`` is +an independent account that has a bunch of coins. + +We can add a second node on our local machine by initiating a node in a +new directory, and copying in the genesis: + +:: + + gaia node init E9E103F788AADD9C0842231E496B2139C118FA60 --home=$HOME/.gaia2 --chain-id=test + cp $HOME/.gaia1/genesis.json $HOME/.gaia2/genesis.json + +We need to also modify ``$HOME/.gaia2/config.toml`` to set new seeds +and ports. It should look like: + +:: + + proxy_app = "tcp://127.0.0.1:46668" + moniker = "anonymous" + fast_sync = true + db_backend = "leveldb" + log_level = "state:info,*:error" + + [rpc] + laddr = "tcp://0.0.0.0:46667" + + [p2p] + laddr = "tcp://0.0.0.0:46666" + seeds = "0.0.0.0:46656" + +Great, now that we've initialized the chains, we can start both nodes: + +NOTE: each command below must be started in seperate terminal windows. + +:: + + gaia node start --home=$HOME/.gaia1 + gaia node start --home=$HOME/.gaia2 + +Now we can initialize a client for the first node, and look up our +account: + +:: + + gaia init --chain-id=test --node=tcp://localhost:46657 + gaia query account E9E103F788AADD9C0842231E496B2139C118FA60 + +Nice. We can also lookup the validator set: + +:: + + gaia query validators + +Notice it's empty! This is because the initial validators are special - +the app doesn't know about them, so they can't be removed. To see what +tendermint itself thinks the validator set is, use: + +:: + + curl localhost:46657/validators + +Ok, let's add the second node as a validator. First, we need the pubkey +data: + +:: + + cat $HOME/.gaia2/priv_validator.json + +If you have a json parser like ``jq``, you can get just the pubkey: + +:: + + cat $HOME/.gaia2/priv_validator.json | jq .pub_key.data + +Now we can bond some coins to that pubkey: + +:: + + gaia tx bond --amount=10fermion --name=alice --pubkey= + +We should see our account balance decrement, and the pubkey get added to +the app's list of bonds: + +:: + + gaia query account E9E103F788AADD9C0842231E496B2139C118FA60 + gaia query validators + +To confirm for certain the new validator is active, check tendermint: + +:: + + curl localhost:46657/validators + +If you now kill your second node, blocks will stop streaming in, because +there aren't enough validators online. Turn it back on and they will +start streaming again. + +Finally, to relinquish all your power, unbond some coins. You should see +your VotingPower reduce and your account balance increase. + +:: + + gaia tx unbond --amount=10fermion --name=alice + gaia query validators + gaia query account E9E103F788AADD9C0842231E496B2139C118FA60 + +Once you unbond enough, you will no longer be needed to make new blocks. + +That concludes an overview of the ``gaia`` tooling for local testing. From 57c15ff13a2e30dad1124a66638921ce850f60c2 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Sat, 25 Nov 2017 14:56:42 +0000 Subject: [PATCH 099/117] docs: it's gaia cli, not gaia --- docs/atlas-testnet.rst | 14 +++++++------- docs/local-testnet.rst | 22 +++++++++++----------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/atlas-testnet.rst b/docs/atlas-testnet.rst index 2f78e9e63d83..73572bbb08f7 100644 --- a/docs/atlas-testnet.rst +++ b/docs/atlas-testnet.rst @@ -10,8 +10,8 @@ this first generate a new key: :: - gaia keys new bob - gaia keys list + gaia cli keys new bob + gaia cli keys list This will output a bunch of information. Read it carefully, then enter your key into `this utility `__ with @@ -58,13 +58,13 @@ testnet: :: - gaia init --chain-id=atlas --node=tcp://localhost:46657 + gaia cli init --chain-id=atlas --node=tcp://localhost:46657 And check our balance: :: - gaia query account $MYADDR + gaia cli query account $MYADDR Where ``$MYADDR`` is the address originally generated by ``gaia keys new bob``. @@ -72,7 +72,7 @@ We are now ready to bond some tokens: :: - gaia tx bond --amount=5fermion --name=bob --pubkey=$PUBKEY + gaia cli tx bond --amount=5fermion --name=bob --pubkey=$PUBKEY Bonding tokens means that your balance is tied up as *stake*. Don't worry, you'll be able to get it back later. As soon as some tokens have @@ -84,12 +84,12 @@ club! :: - gaia query validators + gaia cli query validators Finally lets unbond to get back our tokens :: - gaia tx unbond --amount=5fermion --name=bob + gaia cli tx unbond --amount=5fermion --name=bob Remember to unbond before stopping your node, otherwise ... ? diff --git a/docs/local-testnet.rst b/docs/local-testnet.rst index 63c530188017..aa26eda18c7b 100644 --- a/docs/local-testnet.rst +++ b/docs/local-testnet.rst @@ -8,8 +8,8 @@ First, generate a new key with a name, and save the address: :: - gaia keys new alice - gaia keys list + gaia cli keys new alice + gaia cli keys list This will output: @@ -80,14 +80,14 @@ account: :: - gaia init --chain-id=test --node=tcp://localhost:46657 - gaia query account E9E103F788AADD9C0842231E496B2139C118FA60 + gaia cli init --chain-id=test --node=tcp://localhost:46657 + gaia cli query account E9E103F788AADD9C0842231E496B2139C118FA60 Nice. We can also lookup the validator set: :: - gaia query validators + gaia cli query validators Notice it's empty! This is because the initial validators are special - the app doesn't know about them, so they can't be removed. To see what @@ -114,15 +114,15 @@ Now we can bond some coins to that pubkey: :: - gaia tx bond --amount=10fermion --name=alice --pubkey= + gaia cli tx bond --amount=10fermion --name=alice --pubkey= We should see our account balance decrement, and the pubkey get added to the app's list of bonds: :: - gaia query account E9E103F788AADD9C0842231E496B2139C118FA60 - gaia query validators + gaia cli query account E9E103F788AADD9C0842231E496B2139C118FA60 + gaia cli query validators To confirm for certain the new validator is active, check tendermint: @@ -139,9 +139,9 @@ your VotingPower reduce and your account balance increase. :: - gaia tx unbond --amount=10fermion --name=alice - gaia query validators - gaia query account E9E103F788AADD9C0842231E496B2139C118FA60 + gaia cli tx unbond --amount=10fermion --name=alice + gaia cli query validators + gaia cli query account E9E103F788AADD9C0842231E496B2139C118FA60 Once you unbond enough, you will no longer be needed to make new blocks. From a1dc35d3ca07513da4ab0b2a59ad479ca37650f7 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Mon, 27 Nov 2017 15:51:57 +0000 Subject: [PATCH 100/117] gaia docs: s/gaia cli/gaia client/g --- docs/atlas-testnet.rst | 14 +++++++------- docs/local-testnet.rst | 22 +++++++++++----------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/atlas-testnet.rst b/docs/atlas-testnet.rst index 73572bbb08f7..eab9a75926d4 100644 --- a/docs/atlas-testnet.rst +++ b/docs/atlas-testnet.rst @@ -10,8 +10,8 @@ this first generate a new key: :: - gaia cli keys new bob - gaia cli keys list + gaia client keys new bob + gaia client keys list This will output a bunch of information. Read it carefully, then enter your key into `this utility `__ with @@ -58,13 +58,13 @@ testnet: :: - gaia cli init --chain-id=atlas --node=tcp://localhost:46657 + gaia client init --chain-id=atlas --node=tcp://localhost:46657 And check our balance: :: - gaia cli query account $MYADDR + gaia client query account $MYADDR Where ``$MYADDR`` is the address originally generated by ``gaia keys new bob``. @@ -72,7 +72,7 @@ We are now ready to bond some tokens: :: - gaia cli tx bond --amount=5fermion --name=bob --pubkey=$PUBKEY + gaia client tx bond --amount=5fermion --name=bob --pubkey=$PUBKEY Bonding tokens means that your balance is tied up as *stake*. Don't worry, you'll be able to get it back later. As soon as some tokens have @@ -84,12 +84,12 @@ club! :: - gaia cli query validators + gaia client query validators Finally lets unbond to get back our tokens :: - gaia cli tx unbond --amount=5fermion --name=bob + gaia client tx unbond --amount=5fermion --name=bob Remember to unbond before stopping your node, otherwise ... ? diff --git a/docs/local-testnet.rst b/docs/local-testnet.rst index aa26eda18c7b..3591b13cce22 100644 --- a/docs/local-testnet.rst +++ b/docs/local-testnet.rst @@ -8,8 +8,8 @@ First, generate a new key with a name, and save the address: :: - gaia cli keys new alice - gaia cli keys list + gaia client keys new alice + gaia client keys list This will output: @@ -80,14 +80,14 @@ account: :: - gaia cli init --chain-id=test --node=tcp://localhost:46657 - gaia cli query account E9E103F788AADD9C0842231E496B2139C118FA60 + gaia client init --chain-id=test --node=tcp://localhost:46657 + gaia client query account E9E103F788AADD9C0842231E496B2139C118FA60 Nice. We can also lookup the validator set: :: - gaia cli query validators + gaia client query validators Notice it's empty! This is because the initial validators are special - the app doesn't know about them, so they can't be removed. To see what @@ -114,15 +114,15 @@ Now we can bond some coins to that pubkey: :: - gaia cli tx bond --amount=10fermion --name=alice --pubkey= + gaia client tx bond --amount=10fermion --name=alice --pubkey= We should see our account balance decrement, and the pubkey get added to the app's list of bonds: :: - gaia cli query account E9E103F788AADD9C0842231E496B2139C118FA60 - gaia cli query validators + gaia client query account E9E103F788AADD9C0842231E496B2139C118FA60 + gaia client query validators To confirm for certain the new validator is active, check tendermint: @@ -139,9 +139,9 @@ your VotingPower reduce and your account balance increase. :: - gaia cli tx unbond --amount=10fermion --name=alice - gaia cli query validators - gaia cli query account E9E103F788AADD9C0842231E496B2139C118FA60 + gaia client tx unbond --amount=10fermion --name=alice + gaia client query validators + gaia client query account E9E103F788AADD9C0842231E496B2139C118FA60 Once you unbond enough, you will no longer be needed to make new blocks. From d22479dbf92f2a17de36196f0de302aad966baaf Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Mon, 27 Nov 2017 18:16:48 +0000 Subject: [PATCH 101/117] docs: add gaia overview --- docs/index.rst | 5 +++-- docs/staking-module.rst | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 docs/staking-module.rst diff --git a/docs/index.rst b/docs/index.rst index 349d2784ffa2..61217616a6ff 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -34,6 +34,7 @@ Staking Module .. toctree:: :maxdepth: 2 - - atlas-testnet.rst + + staking-module.rst local-testnet.rst + atlas-testnet.rst diff --git a/docs/staking-module.rst b/docs/staking-module.rst new file mode 100644 index 000000000000..1c5c68ae2b15 --- /dev/null +++ b/docs/staking-module.rst @@ -0,0 +1,36 @@ +Using Gaia +========== + +The purpose of the ``gaia`` staking module is to provide users with the ability to 1) declare candidacy as a validator, 2) bond/unbond to a candidate. + +For the time being, the ``gaia`` tooling is installed seperately from the Cosmos-SDK: + +:: + + go get github.com/cosmos/gaia + cd $GOPATH/src/github.com/cosmos/gaia + make get_vendor_deps + make install + +The ``gaia`` tool has three primary commands: + +:: + + Available Commands: + node The Cosmos Network delegation-game blockchain test + rest-server REST client for gaia commands + client Gaia light client + + version Show version info + help Help about any command + +and a handful of flags that are highlighted only as necessary. + +The ``gaia node`` command is a proxt for running a tendermint node. You be using +this command to either initialize a new node, or - using existing files - joining +the testnet. + +The ``gaia rest-server`` command is used by (insert). + +Lastly, the ``gaia client`` command is the workhorse of the staking module. It allows +for sending various transactions and other types of interaction with a running chain. From ffad075af027c27fa6d5ffc692828a9c65676501 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Tue, 28 Nov 2017 00:06:22 +0000 Subject: [PATCH 102/117] ... --- docs/local-testnet.rst | 4 ++-- docs/staking-module.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/local-testnet.rst b/docs/local-testnet.rst index 3591b13cce22..004723cdacce 100644 --- a/docs/local-testnet.rst +++ b/docs/local-testnet.rst @@ -45,7 +45,7 @@ new directory, and copying in the genesis: :: - gaia node init E9E103F788AADD9C0842231E496B2139C118FA60 --home=$HOME/.gaia2 --chain-id=test + gaia node init E9E103F788AADD9C0842231E496B2139C118FA60 --home=$HOME/.gaia2 --chain-id=gaia-test cp $HOME/.gaia1/genesis.json $HOME/.gaia2/genesis.json We need to also modify ``$HOME/.gaia2/config.toml`` to set new seeds @@ -80,7 +80,7 @@ account: :: - gaia client init --chain-id=test --node=tcp://localhost:46657 + gaia client init --chain-id=gaia-test --node=tcp://localhost:46657 gaia client query account E9E103F788AADD9C0842231E496B2139C118FA60 Nice. We can also lookup the validator set: diff --git a/docs/staking-module.rst b/docs/staking-module.rst index 1c5c68ae2b15..bf6540f7ed87 100644 --- a/docs/staking-module.rst +++ b/docs/staking-module.rst @@ -26,11 +26,11 @@ The ``gaia`` tool has three primary commands: and a handful of flags that are highlighted only as necessary. -The ``gaia node`` command is a proxt for running a tendermint node. You be using +The ``gaia node`` command is a proxt for running a tendermint node. You'll be using this command to either initialize a new node, or - using existing files - joining the testnet. -The ``gaia rest-server`` command is used by (insert). +The ``gaia rest-server`` command is used by the `cosmos UI `__. Lastly, the ``gaia client`` command is the workhorse of the staking module. It allows for sending various transactions and other types of interaction with a running chain. From cb436b50a1a6d9903abc4fbb813670d4b72ad0c5 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Fri, 1 Dec 2017 17:50:37 +0000 Subject: [PATCH 103/117] gaiaaa --- docs/local-testnet.rst | 90 +++++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 28 deletions(-) diff --git a/docs/local-testnet.rst b/docs/local-testnet.rst index 004723cdacce..ffa6343a69a5 100644 --- a/docs/local-testnet.rst +++ b/docs/local-testnet.rst @@ -4,12 +4,14 @@ Local Testnet Example This tutorial demonstrates the basics of setting up a gaia testnet locally -First, generate a new key with a name, and save the address: +Generate Keys +------------- + +First, generate a new key with a name: :: gaia client keys new alice - gaia client keys list This will output: @@ -26,9 +28,35 @@ This will output: which has your address and will be re-used throughout this tutorial. We recommend doing something like ``MYADDR=``. Writing down the recovery phrase is crucial for production keys, however, -for the tutorial you can skip this step. +for this tutorial you can skip this step. + +Because ``alice`` will be delclaring candidacy to be a validator, we need another key, ``bob`` who will delegate his tokens to ``alice``. + +:: + + gaia client keys new bob + +Now we can see the keys we've created: + +:: + + gaia client keys list + +which show's something like: + +:: + + All keys: + alice E9E103F788AADD9C0842231E496B2139C118FA60 + bob 7E00832E8CC9D15E3AE6EEBAE09C3CB83AA04361 + +Try add the ``--output json`` flag to the above command to get more information. +We've got our keys made, so let's move on to the next step. + +Initialize the chain +-------------------- -Now initialize a gaia chain: +Now initialize a gaia chain, using ``alice``'s address: :: @@ -37,10 +65,9 @@ Now initialize a gaia chain: This will create all the files necessary to run a single node chain in ``$HOME/.gaia1``: a ``priv_validator.json`` file with the validators private key, and a ``genesis.json`` file with the list of validators and -accounts. In this case, we have one random validator, and ``$MYADDR`` is -an independent account that has a bunch of coins. +accounts. -We can add a second node on our local machine by initiating a node in a +We'll add a second node on our local machine by initiating a node in a new directory, and copying in the genesis: :: @@ -48,7 +75,7 @@ new directory, and copying in the genesis: gaia node init E9E103F788AADD9C0842231E496B2139C118FA60 --home=$HOME/.gaia2 --chain-id=gaia-test cp $HOME/.gaia1/genesis.json $HOME/.gaia2/genesis.json -We need to also modify ``$HOME/.gaia2/config.toml`` to set new seeds +We also need to modify ``$HOME/.gaia2/config.toml`` to set new seeds and ports. It should look like: :: @@ -68,7 +95,7 @@ and ports. It should look like: Great, now that we've initialized the chains, we can start both nodes: -NOTE: each command below must be started in seperate terminal windows. +NOTE: each command below must be started in seperate terminal windows. Alternatively, to run this testnet across multiple machines, you'd replace the ``seeds = "0.0.0.0"`` in ``~/.gaia2.config.toml``, and could skip the modifications we made to the config file above because port conflicts would be avoided. :: @@ -83,64 +110,71 @@ account: gaia client init --chain-id=gaia-test --node=tcp://localhost:46657 gaia client query account E9E103F788AADD9C0842231E496B2139C118FA60 -Nice. We can also lookup the validator set: +To see what tendermint considers the validator set is, use: :: - gaia client query validators + curl localhost:46657/validators -Notice it's empty! This is because the initial validators are special - -the app doesn't know about them, so they can't be removed. To see what -tendermint itself thinks the validator set is, use: +and compare the information in this file: ``~/.gaia1/priv_validator.json``. The ``address`` and ``pub_key`` fields should match. -:: +Add Second Validator +-------------------- - curl localhost:46657/validators +Next, let's add the second node as a validator. -Ok, let's add the second node as a validator. First, we need the pubkey -data: +First, we need the pub_key data: :: cat $HOME/.gaia2/priv_validator.json -If you have a json parser like ``jq``, you can get just the pubkey: +the first part will look like: :: - cat $HOME/.gaia2/priv_validator.json | jq .pub_key.data + {"address":"7B78527942C831E16907F10C3263D5ED933F7E99","pub_key":{"type":"ed25519","data":"96864CE7085B2E342B0F96F2E92B54B18C6CC700186238810D5AA7DFDAFDD3B2"}, -Now we can bond some coins to that pubkey: +and you want the ``pub_key`` ``data`` that starts with ``96864CE``. + +Now we can declare candidacy to that pubkey: :: - gaia client tx bond --amount=10fermion --name=alice --pubkey= + gaia client tx declare-candidacy --amount=10fermion --name=alice --pubkey= -We should see our account balance decrement, and the pubkey get added to -the app's list of bonds: +We should see our account balance decrement: :: gaia client query account E9E103F788AADD9C0842231E496B2139C118FA60 - gaia client query validators -To confirm for certain the new validator is active, check tendermint: +To confirm for certain the new validator is active, ask the tendermint node: :: curl localhost:46657/validators -If you now kill your second node, blocks will stop streaming in, because +If you now kill either node, blocks will stop streaming in, because there aren't enough validators online. Turn it back on and they will start streaming again. +Now that ``alice`` has declared her candidacy, which essentially bonded 10 fermions and made her a validator, we're going to get ``bob`` to delegate some coins to ``alice``. + +Delegate +-------- + + + +Unbond +------ + Finally, to relinquish all your power, unbond some coins. You should see your VotingPower reduce and your account balance increase. :: gaia client tx unbond --amount=10fermion --name=alice - gaia client query validators gaia client query account E9E103F788AADD9C0842231E496B2139C118FA60 Once you unbond enough, you will no longer be needed to make new blocks. From f32b2dd1418317f5a43671df43d6694263d79a1c Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Mon, 4 Dec 2017 21:43:21 +0000 Subject: [PATCH 104/117] gaiiiiiaaaaaa --- docs/local-testnet.rst | 110 +++++++++++++++++++++++++++++++++-------- 1 file changed, 90 insertions(+), 20 deletions(-) diff --git a/docs/local-testnet.rst b/docs/local-testnet.rst index ffa6343a69a5..ed5e21041865 100644 --- a/docs/local-testnet.rst +++ b/docs/local-testnet.rst @@ -1,13 +1,15 @@ Local Testnet Example ===================== -This tutorial demonstrates the basics of setting up a gaia -testnet locally +This tutorial demonstrates the basics of: setting up a gaia +testnet locally, sending transactions, declaring candidacy, +bonding, and unbonding. Various other commands of the ``gaia`` +tooling are also introduced. Generate Keys ------------- -First, generate a new key with a name: +First, let's generate a key named ``alice``.: :: @@ -19,7 +21,7 @@ This will output: Enter a passphrase: Repeat the passphrase: - alice E9E103F788AADD9C0842231E496B2139C118FA60 + alice 5D93A6059B6592833CBC8FA3DA90EE0382198985 **Important** write this seed phrase in a safe place. It is the only way to recover your account if you ever forget your password. @@ -30,11 +32,12 @@ We recommend doing something like ``MYADDR=``. Writing down the recovery phrase is crucial for production keys, however, for this tutorial you can skip this step. -Because ``alice`` will be delclaring candidacy to be a validator, we need another key, ``bob`` who will delegate his tokens to ``alice``. +Because ``alice`` will be the initial validator, we need another key, ``bob`` who will first receives tokens from ``alice``, then declare candidacy as a validator. We also need an account for ``charlie`` who will bond and unbond to ``bob``. :: gaia client keys new bob + gaia client keys new charlie Now we can see the keys we've created: @@ -42,15 +45,17 @@ Now we can see the keys we've created: gaia client keys list -which show's something like: +which shows something like: :: All keys: - alice E9E103F788AADD9C0842231E496B2139C118FA60 - bob 7E00832E8CC9D15E3AE6EEBAE09C3CB83AA04361 + alice 5D93A6059B6592833CBC8FA3DA90EE0382198985 + bob 5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 + charlie 48F74F48281C89E5E4BE9092F735EA519768E8EF -Try add the ``--output json`` flag to the above command to get more information. +Try adding the ``--output json`` flag to the above command to get more information. +The information for these keys is stored in ``~/.cosmos-gaia-cli``. We've got our keys made, so let's move on to the next step. Initialize the chain @@ -60,7 +65,7 @@ Now initialize a gaia chain, using ``alice``'s address: :: - gaia node init E9E103F788AADD9C0842231E496B2139C118FA60 --home=$HOME/.gaia1 --chain-id=gaia-test + gaia node init 5D93A6059B6592833CBC8FA3DA90EE0382198985 --home=$HOME/.gaia1 --chain-id=gaia-test This will create all the files necessary to run a single node chain in ``$HOME/.gaia1``: a ``priv_validator.json`` file with the validators @@ -68,11 +73,11 @@ private key, and a ``genesis.json`` file with the list of validators and accounts. We'll add a second node on our local machine by initiating a node in a -new directory, and copying in the genesis: +new directory, with the same address, and copying in the genesis: :: - gaia node init E9E103F788AADD9C0842231E496B2139C118FA60 --home=$HOME/.gaia2 --chain-id=gaia-test + gaia node init 5D93A6059B6592833CBC8FA3DA90EE0382198985 --home=$HOME/.gaia2 --chain-id=gaia-test cp $HOME/.gaia1/genesis.json $HOME/.gaia2/genesis.json We also need to modify ``$HOME/.gaia2/config.toml`` to set new seeds @@ -95,7 +100,7 @@ and ports. It should look like: Great, now that we've initialized the chains, we can start both nodes: -NOTE: each command below must be started in seperate terminal windows. Alternatively, to run this testnet across multiple machines, you'd replace the ``seeds = "0.0.0.0"`` in ``~/.gaia2.config.toml``, and could skip the modifications we made to the config file above because port conflicts would be avoided. +NOTE: each command below must be started in seperate terminal windows. Alternatively, to run this testnet across multiple machines, you'd replace the ``seeds = "0.0.0.0"`` in ``~/.gaia2.config.toml`` with the IP of the first node, and could skip the modifications we made to the config file above because port conflicts would be avoided. :: @@ -108,7 +113,7 @@ account: :: gaia client init --chain-id=gaia-test --node=tcp://localhost:46657 - gaia client query account E9E103F788AADD9C0842231E496B2139C118FA60 + gaia client query account 5D93A6059B6592833CBC8FA3DA90EE0382198985 To see what tendermint considers the validator set is, use: @@ -118,6 +123,51 @@ To see what tendermint considers the validator set is, use: and compare the information in this file: ``~/.gaia1/priv_validator.json``. The ``address`` and ``pub_key`` fields should match. +Send Tokens +----------- + +We'll have ``alice`` who is currently quite rich, send some ``fermions`` to ``bob``: + +:: + + gaia client tx send --amount=992fermion --sequence=1 --name=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 + +where the ``--sequence`` flag is to be incremented for each transaction, the ``--name`` flag names the sender, and the ``--to`` flag takes ``bob``'s address. You'll see something like: + +:: + + Please enter passphrase for alice: + { + "check_tx": { + "gas": 30 + }, + "deliver_tx": { + "tags": [ + { + "key": "height", + "value_type": 1, + "value_int": 2963 + }, + { + "key": "coin.sender", + "value_string": "5D93A6059B6592833CBC8FA3DA90EE0382198985" + }, + { + "key": "coin.receiver", + "value_string": "5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6" + } + ] + }, + "hash": "423BD7EA3C4B36AF8AFCCA381C0771F8A698BA77", + "height": 2963 + } + +Check out ``bob``'s account, which should now have 992 fermions: + +:: + + gaia client query account 5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 + Add Second Validator -------------------- @@ -137,17 +187,32 @@ the first part will look like: and you want the ``pub_key`` ``data`` that starts with ``96864CE``. -Now we can declare candidacy to that pubkey: +Now ``bob`` can declare candidacy to that pubkey: + +:: + + gaia client tx declare-candidacy --amount=10fermion --name=bob --pubkey= --moniker=bobby + +with an output like: :: - gaia client tx declare-candidacy --amount=10fermion --name=alice --pubkey= + Please enter passphrase for bob: + { + "check_tx": { + "gas": 30 + }, + "deliver_tx": {}, + "hash": "2A2A61FFBA1D7A59138E0068C82CC830E5103799", + "height": 4075 + } + -We should see our account balance decrement: +We should see ``bob``'s account balance decrease by 10 fermions: :: - gaia client query account E9E103F788AADD9C0842231E496B2139C118FA60 + gaia client query account 5D93A6059B6592833CBC8FA3DA90EE0382198985 To confirm for certain the new validator is active, ask the tendermint node: @@ -159,11 +224,16 @@ If you now kill either node, blocks will stop streaming in, because there aren't enough validators online. Turn it back on and they will start streaming again. -Now that ``alice`` has declared her candidacy, which essentially bonded 10 fermions and made her a validator, we're going to get ``bob`` to delegate some coins to ``alice``. +Now that ``bob`` has declared candidacy, which essentially bonded 10 fermions and made him a validator, we're going to get ``charlie`` to delegate some coins to ``bob``. Delegate -------- +First let's have ``alice`` send some coins to ``charlie``: + +:: + + gaia client tx send --amount=999fermion --sequence=2 --name=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF Unbond @@ -175,7 +245,7 @@ your VotingPower reduce and your account balance increase. :: gaia client tx unbond --amount=10fermion --name=alice - gaia client query account E9E103F788AADD9C0842231E496B2139C118FA60 + gaia client query account 5D93A6059B6592833CBC8FA3DA90EE0382198985 Once you unbond enough, you will no longer be needed to make new blocks. From 8ae5f6abcdedac1963e58ccfa20e7c462f46ecdb Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Tue, 5 Dec 2017 14:52:37 +0000 Subject: [PATCH 105/117] docs: finish local testnet example --- docs/local-testnet.rst | 65 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/docs/local-testnet.rst b/docs/local-testnet.rst index ed5e21041865..f74f8859f058 100644 --- a/docs/local-testnet.rst +++ b/docs/local-testnet.rst @@ -9,7 +9,7 @@ tooling are also introduced. Generate Keys ------------- -First, let's generate a key named ``alice``.: +First, let's generate a key named ``alice``: :: @@ -233,7 +233,62 @@ First let's have ``alice`` send some coins to ``charlie``: :: - gaia client tx send --amount=999fermion --sequence=2 --name=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF + gaia client tx send --amount=999fermion --sequence=2 --name=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF + +Then ``charlie`` will delegate some fermions to ``bob``: + +:: + + gaia client tx delegate --amount=10fermion --name=charlie --pubkey= + +You'll see output like: + +:: + + Please enter passphrase for charlie: + { + "check_tx": { + "gas": 30 + }, + "deliver_tx": {}, + "hash": "C3443BA30FCCC1F6E3A3D6AAAEE885244F8554F0", + "height": 51585 + } + +And that's it. You can query ``charlie``'s account to see the decrease in fermions. + +To get more information about the candidate, try: + +:: + + gaia client query candidate --pubkey= + +and you'll see output similar to: + +:: + + { + "height": 51899, + "data": { + "pub_key": { + "type": "ed25519", + "data": "52D6FCD8C92A97F7CCB01205ADF310A18411EA8FDCC10E65BF2FCDB05AD1689B" + }, + "owner": { + "chain": "", + "app": "sigs", + "addr": "5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6" + }, + "shares": 20, + "voting_power": 20, + "description": { + "moniker": "bobby", + "identity": "", + "website": "", + "details": "" + } + } + } Unbond @@ -244,9 +299,7 @@ your VotingPower reduce and your account balance increase. :: - gaia client tx unbond --amount=10fermion --name=alice - gaia client query account 5D93A6059B6592833CBC8FA3DA90EE0382198985 - -Once you unbond enough, you will no longer be needed to make new blocks. + gaia client tx unbond --amount=5fermion --name=charlie --pubkey= + gaia client query account 48F74F48281C89E5E4BE9092F735EA519768E8EF That concludes an overview of the ``gaia`` tooling for local testing. From c6c3c6af1efcfe0a9fbc1230ac1c03e83a20f678 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 6 Dec 2017 04:14:35 +0000 Subject: [PATCH 106/117] docs: re-organize gaia docs --- docs/atlas-testnet.rst | 68 ++++------- docs/local-testnet.rst | 246 ++-------------------------------------- docs/staking-module.rst | 242 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 274 insertions(+), 282 deletions(-) diff --git a/docs/atlas-testnet.rst b/docs/atlas-testnet.rst index eab9a75926d4..767b3d7c7ebe 100644 --- a/docs/atlas-testnet.rst +++ b/docs/atlas-testnet.rst @@ -1,11 +1,14 @@ -Atlas Testnet Example -===================== +Atlas Testnet +============= Atlas is a community testnet which can be used to test setting up a cosmos validator node. In addition to this tutorial you can also follow `this video `__. -To work on the Atlas you will need some tokens to get started. To do +Get Tokens +---------- + +To work on the Atlas you'll need some tokens to get started. To do this first generate a new key: :: @@ -15,9 +18,10 @@ this first generate a new key: This will output a bunch of information. Read it carefully, then enter your key into `this utility `__ with -your key address and it will send you some ``fermion`` testnet tokens :). -Fermions are the native staking token on the Atlas tesnet; see below for -information on checking your balance. +your key address and it will send you some ``fermion`` testnet tokens. + +Get Files +--------- Now, to sync with the testnet, we need the genesis file and seeds. The easiest way to get them is to clone and navigate to the tendermint @@ -28,6 +32,10 @@ testnet repo: git clone https://github.com/tendermint/testnets ~/testnets cd ~/testnets/gaia-1/gaia + +Start Node +---------- + Now we can start a new node in the background; note that it may take awhile to sync with the existing testnet. @@ -35,32 +43,18 @@ take awhile to sync with the existing testnet. gaia node start --home=$HOME/testnets/gaia-1/gaia -Once blocks slow down to about one block per second, you're all caught up. +Once blocks slow down to about one per second, you're all caught up. The ``gaia node start`` command will automaticaly generate a validator private key found in ``~/testnets/gaia-1/gaia/priv_validator.json``. -Let's get the pubkey data for our validator node. The pubkey is located under -``"pub_key"{"data":`` within the json file - -:: - cat ~/testnets/gaia-1/gaia/priv_validator.json - PUBKEY= - -If you have a json parser like ``jq``, you can get the pubkey like so: - -:: - - PUBKEY=$(cat $GAIANET/priv_validator.json | jq -r .pub_key.data) - -Next let's initialize the gaia client to start interacting with the -testnet: +Finally, let's initialize the gaia client to interact with the testnet: :: gaia client init --chain-id=atlas --node=tcp://localhost:46657 -And check our balance: +and check our balance: :: @@ -68,28 +62,6 @@ And check our balance: Where ``$MYADDR`` is the address originally generated by ``gaia keys new bob``. -We are now ready to bond some tokens: - -:: - - gaia client tx bond --amount=5fermion --name=bob --pubkey=$PUBKEY - -Bonding tokens means that your balance is tied up as *stake*. Don't -worry, you'll be able to get it back later. As soon as some tokens have -been bonded the validator node which we started earlier will have power -in the network and begin to participate in consensus! - -We can now check the validator set and see that we are a part of the -club! - -:: - - gaia client query validators - -Finally lets unbond to get back our tokens - -:: - - gaia client tx unbond --amount=5fermion --name=bob - -Remember to unbond before stopping your node, otherwise ... ? +You are now ready to declare candidacy or delegate some fermions. See the +`staking module overview <./staking-module.html>`__ for more information +on using the ``gaia client``. diff --git a/docs/local-testnet.rst b/docs/local-testnet.rst index f74f8859f058..e3f69bded120 100644 --- a/docs/local-testnet.rst +++ b/docs/local-testnet.rst @@ -1,64 +1,18 @@ -Local Testnet Example -===================== +Local Testnet +============= -This tutorial demonstrates the basics of: setting up a gaia -testnet locally, sending transactions, declaring candidacy, -bonding, and unbonding. Various other commands of the ``gaia`` -tooling are also introduced. +This tutorial demonstrates the basics of setting up a gaia +testnet locally. -Generate Keys -------------- - -First, let's generate a key named ``alice``: +If you haven't already made a key, make one now: :: gaia client keys new alice -This will output: - -:: - - Enter a passphrase: - Repeat the passphrase: - alice 5D93A6059B6592833CBC8FA3DA90EE0382198985 - **Important** write this seed phrase in a safe place. - It is the only way to recover your account if you ever forget your password. - - inject position weather divorce shine immense middle affair piece oval silver type until spike educate abandon - -which has your address and will be re-used throughout this tutorial. -We recommend doing something like ``MYADDR=``. Writing -down the recovery phrase is crucial for production keys, however, -for this tutorial you can skip this step. - -Because ``alice`` will be the initial validator, we need another key, ``bob`` who will first receives tokens from ``alice``, then declare candidacy as a validator. We also need an account for ``charlie`` who will bond and unbond to ``bob``. - -:: - - gaia client keys new bob - gaia client keys new charlie - -Now we can see the keys we've created: - -:: - - gaia client keys list - -which shows something like: - -:: - - All keys: - alice 5D93A6059B6592833CBC8FA3DA90EE0382198985 - bob 5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 - charlie 48F74F48281C89E5E4BE9092F735EA519768E8EF +otherwise, use an existing key. -Try adding the ``--output json`` flag to the above command to get more information. -The information for these keys is stored in ``~/.cosmos-gaia-cli``. -We've got our keys made, so let's move on to the next step. - -Initialize the chain +Initialize The Chain -------------------- Now initialize a gaia chain, using ``alice``'s address: @@ -98,7 +52,10 @@ and ports. It should look like: laddr = "tcp://0.0.0.0:46666" seeds = "0.0.0.0:46656" -Great, now that we've initialized the chains, we can start both nodes: +Start Nodes +----------- + +Now that we've initialized the chains, we can start both nodes: NOTE: each command below must be started in seperate terminal windows. Alternatively, to run this testnet across multiple machines, you'd replace the ``seeds = "0.0.0.0"`` in ``~/.gaia2.config.toml`` with the IP of the first node, and could skip the modifications we made to the config file above because port conflicts would be avoided. @@ -123,183 +80,4 @@ To see what tendermint considers the validator set is, use: and compare the information in this file: ``~/.gaia1/priv_validator.json``. The ``address`` and ``pub_key`` fields should match. -Send Tokens ------------ - -We'll have ``alice`` who is currently quite rich, send some ``fermions`` to ``bob``: - -:: - - gaia client tx send --amount=992fermion --sequence=1 --name=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 - -where the ``--sequence`` flag is to be incremented for each transaction, the ``--name`` flag names the sender, and the ``--to`` flag takes ``bob``'s address. You'll see something like: - -:: - - Please enter passphrase for alice: - { - "check_tx": { - "gas": 30 - }, - "deliver_tx": { - "tags": [ - { - "key": "height", - "value_type": 1, - "value_int": 2963 - }, - { - "key": "coin.sender", - "value_string": "5D93A6059B6592833CBC8FA3DA90EE0382198985" - }, - { - "key": "coin.receiver", - "value_string": "5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6" - } - ] - }, - "hash": "423BD7EA3C4B36AF8AFCCA381C0771F8A698BA77", - "height": 2963 - } - -Check out ``bob``'s account, which should now have 992 fermions: - -:: - - gaia client query account 5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 - -Add Second Validator --------------------- - -Next, let's add the second node as a validator. - -First, we need the pub_key data: - -:: - - cat $HOME/.gaia2/priv_validator.json - -the first part will look like: - -:: - - {"address":"7B78527942C831E16907F10C3263D5ED933F7E99","pub_key":{"type":"ed25519","data":"96864CE7085B2E342B0F96F2E92B54B18C6CC700186238810D5AA7DFDAFDD3B2"}, - -and you want the ``pub_key`` ``data`` that starts with ``96864CE``. - -Now ``bob`` can declare candidacy to that pubkey: - -:: - - gaia client tx declare-candidacy --amount=10fermion --name=bob --pubkey= --moniker=bobby - -with an output like: - -:: - - Please enter passphrase for bob: - { - "check_tx": { - "gas": 30 - }, - "deliver_tx": {}, - "hash": "2A2A61FFBA1D7A59138E0068C82CC830E5103799", - "height": 4075 - } - - -We should see ``bob``'s account balance decrease by 10 fermions: - -:: - - gaia client query account 5D93A6059B6592833CBC8FA3DA90EE0382198985 - -To confirm for certain the new validator is active, ask the tendermint node: - -:: - - curl localhost:46657/validators - -If you now kill either node, blocks will stop streaming in, because -there aren't enough validators online. Turn it back on and they will -start streaming again. - -Now that ``bob`` has declared candidacy, which essentially bonded 10 fermions and made him a validator, we're going to get ``charlie`` to delegate some coins to ``bob``. - -Delegate --------- - -First let's have ``alice`` send some coins to ``charlie``: - -:: - - gaia client tx send --amount=999fermion --sequence=2 --name=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF - -Then ``charlie`` will delegate some fermions to ``bob``: - -:: - - gaia client tx delegate --amount=10fermion --name=charlie --pubkey= - -You'll see output like: - -:: - - Please enter passphrase for charlie: - { - "check_tx": { - "gas": 30 - }, - "deliver_tx": {}, - "hash": "C3443BA30FCCC1F6E3A3D6AAAEE885244F8554F0", - "height": 51585 - } - -And that's it. You can query ``charlie``'s account to see the decrease in fermions. - -To get more information about the candidate, try: - -:: - - gaia client query candidate --pubkey= - -and you'll see output similar to: - -:: - - { - "height": 51899, - "data": { - "pub_key": { - "type": "ed25519", - "data": "52D6FCD8C92A97F7CCB01205ADF310A18411EA8FDCC10E65BF2FCDB05AD1689B" - }, - "owner": { - "chain": "", - "app": "sigs", - "addr": "5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6" - }, - "shares": 20, - "voting_power": 20, - "description": { - "moniker": "bobby", - "identity": "", - "website": "", - "details": "" - } - } - } - - -Unbond ------- - -Finally, to relinquish all your power, unbond some coins. You should see -your VotingPower reduce and your account balance increase. - -:: - - gaia client tx unbond --amount=5fermion --name=charlie --pubkey= - gaia client query account 48F74F48281C89E5E4BE9092F735EA519768E8EF - -That concludes an overview of the ``gaia`` tooling for local testing. +To add a second validator on your testnet, you'll need to bond some tokens be declaring candidacy. diff --git a/docs/staking-module.rst b/docs/staking-module.rst index bf6540f7ed87..bc67480ba2c0 100644 --- a/docs/staking-module.rst +++ b/docs/staking-module.rst @@ -34,3 +34,245 @@ The ``gaia rest-server`` command is used by the `cosmos UI `__ or +join the `atlas testnet <./atlas-testnet.html>`__. Either step is required before proceeding +(although you should browse below and make some keys first). + +Generating Keys +--------------- + +First, let's generate a key named ``alice``: + +:: + + gaia client keys new alice + +This will output: + +:: + + Enter a passphrase: + Repeat the passphrase: + alice 5D93A6059B6592833CBC8FA3DA90EE0382198985 + **Important** write this seed phrase in a safe place. + It is the only way to recover your account if you ever forget your password. + + inject position weather divorce shine immense middle affair piece oval silver type until spike educate abandon + +which has your address and will be re-used throughout this tutorial. +We recommend doing something like ``MYADDR=``. Writing +down the recovery phrase is crucial for production keys, however, +for this tutorial you can skip this step. + +Because ``alice`` will be the initial validator, we need another key, ``bob`` who will first receives tokens from ``alice``, then declare candidacy as a validator. We also need an account for ``charlie`` who will bond and unbond to ``bob``. + +:: + + gaia client keys new bob + gaia client keys new charlie + +Now we can see the keys we've created: + +:: + + gaia client keys list + +which shows something like: + +:: + + All keys: + alice 5D93A6059B6592833CBC8FA3DA90EE0382198985 + bob 5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 + charlie 48F74F48281C89E5E4BE9092F735EA519768E8EF + +Try adding the ``--output json`` flag to the above command to get more information. +The information for these keys is stored in ``~/.cosmos-gaia-cli``. +We've got our keys made, so let's move on to the next step. + +Sending Tokens +-------------- + +We'll have ``alice`` who is currently quite rich, send some ``fermions`` to ``bob``: + +:: + + gaia client tx send --amount=992fermion --sequence=1 --name=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 + +where the ``--sequence`` flag is to be incremented for each transaction, the ``--name`` flag names the sender, and the ``--to`` flag takes ``bob``'s address. You'll see something like: + +:: + + Please enter passphrase for alice: + { + "check_tx": { + "gas": 30 + }, + "deliver_tx": { + "tags": [ + { + "key": "height", + "value_type": 1, + "value_int": 2963 + }, + { + "key": "coin.sender", + "value_string": "5D93A6059B6592833CBC8FA3DA90EE0382198985" + }, + { + "key": "coin.receiver", + "value_string": "5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6" + } + ] + }, + "hash": "423BD7EA3C4B36AF8AFCCA381C0771F8A698BA77", + "height": 2963 + } + +Check out ``bob``'s account, which should now have 992 fermions: + +:: + + gaia client query account 5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 + +Adding a Second Validator +------------------------- + +Next, let's add the second node as a validator. + +First, we need the pub_key data: + +:: + + cat $HOME/.gaia2/priv_validator.json + +the first part will look like: + +:: + + {"address":"7B78527942C831E16907F10C3263D5ED933F7E99","pub_key":{"type":"ed25519","data":"96864CE7085B2E342B0F96F2E92B54B18C6CC700186238810D5AA7DFDAFDD3B2"}, + +and you want the ``pub_key`` ``data`` that starts with ``96864CE``. + +Now ``bob`` can declare candidacy to that pubkey: + +:: + + gaia client tx declare-candidacy --amount=10fermion --name=bob --pubkey= --moniker=bobby + +with an output like: + +:: + + Please enter passphrase for bob: + { + "check_tx": { + "gas": 30 + }, + "deliver_tx": {}, + "hash": "2A2A61FFBA1D7A59138E0068C82CC830E5103799", + "height": 4075 + } + + +We should see ``bob``'s account balance decrease by 10 fermions: + +:: + + gaia client query account 5D93A6059B6592833CBC8FA3DA90EE0382198985 + +To confirm for certain the new validator is active, ask the tendermint node: + +:: + + curl localhost:46657/validators + +If you now kill either node, blocks will stop streaming in, because +there aren't enough validators online. Turn it back on and they will +start streaming again. + +Now that ``bob`` has declared candidacy, which essentially bonded 10 fermions and made him a validator, we're going to get ``charlie`` to delegate some coins to ``bob``. + +Delegating +---------- + +First let's have ``alice`` send some coins to ``charlie``: + +:: + + gaia client tx send --amount=999fermion --sequence=2 --name=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF + +Then ``charlie`` will delegate some fermions to ``bob``: + +:: + + gaia client tx delegate --amount=10fermion --name=charlie --pubkey= + +You'll see output like: + +:: + + Please enter passphrase for charlie: + { + "check_tx": { + "gas": 30 + }, + "deliver_tx": {}, + "hash": "C3443BA30FCCC1F6E3A3D6AAAEE885244F8554F0", + "height": 51585 + } + +And that's it. You can query ``charlie``'s account to see the decrease in fermions. + +To get more information about the candidate, try: + +:: + + gaia client query candidate --pubkey= + +and you'll see output similar to: + +:: + + { + "height": 51899, + "data": { + "pub_key": { + "type": "ed25519", + "data": "52D6FCD8C92A97F7CCB01205ADF310A18411EA8FDCC10E65BF2FCDB05AD1689B" + }, + "owner": { + "chain": "", + "app": "sigs", + "addr": "5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6" + }, + "shares": 20, + "voting_power": 20, + "description": { + "moniker": "bobby", + "identity": "", + "website": "", + "details": "" + } + } + } + + +Unbonding +--------- + +Finally, to relinquish all your power, unbond some coins. You should see +your VotingPower reduce and your account balance increase. + +:: + + gaia client tx unbond --amount=5fermion --name=charlie --pubkey= + gaia client query account 48F74F48281C89E5E4BE9092F735EA519768E8EF + +That concludes an overview of the ``gaia`` tooling for local testing. From 891562998ec7556e94f45a61c61b45ab99cf2af9 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Sat, 9 Dec 2017 00:28:27 +0000 Subject: [PATCH 107/117] docs: organize files into dirs --- .../basics.rst} | 0 .../kubernetes.rst} | 0 .../plugins.rst} | 0 docs/{basecoin-tool.rst => basecoin/tool.rst} | 0 docs/index.rst | 46 ++++++++++++------- docs/{ => sdk}/install.rst | 0 docs/{ => sdk}/key-management.rst | 0 docs/{ => sdk}/overview.rst | 0 docs/{ => sdk}/roles-and-multi-sig.rst | 0 .../{staking-module.rst => staking/intro.rst} | 0 docs/{ => staking}/local-testnet.rst | 0 .../public-testnet.rst} | 0 12 files changed, 30 insertions(+), 16 deletions(-) rename docs/{basecoin-basics.rst => basecoin/basics.rst} (100%) rename docs/{basecoin-kubernetes.rst => basecoin/kubernetes.rst} (100%) rename docs/{basecoin-plugins.rst => basecoin/plugins.rst} (100%) rename docs/{basecoin-tool.rst => basecoin/tool.rst} (100%) rename docs/{ => sdk}/install.rst (100%) rename docs/{ => sdk}/key-management.rst (100%) rename docs/{ => sdk}/overview.rst (100%) rename docs/{ => sdk}/roles-and-multi-sig.rst (100%) rename docs/{staking-module.rst => staking/intro.rst} (100%) rename docs/{ => staking}/local-testnet.rst (100%) rename docs/{atlas-testnet.rst => staking/public-testnet.rst} (100%) diff --git a/docs/basecoin-basics.rst b/docs/basecoin/basics.rst similarity index 100% rename from docs/basecoin-basics.rst rename to docs/basecoin/basics.rst diff --git a/docs/basecoin-kubernetes.rst b/docs/basecoin/kubernetes.rst similarity index 100% rename from docs/basecoin-kubernetes.rst rename to docs/basecoin/kubernetes.rst diff --git a/docs/basecoin-plugins.rst b/docs/basecoin/plugins.rst similarity index 100% rename from docs/basecoin-plugins.rst rename to docs/basecoin/plugins.rst diff --git a/docs/basecoin-tool.rst b/docs/basecoin/tool.rst similarity index 100% rename from docs/basecoin-tool.rst rename to docs/basecoin/tool.rst diff --git a/docs/index.rst b/docs/index.rst index 61217616a6ff..4869cfc16444 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -11,23 +11,27 @@ Welcome to the Cosmos SDK! :width: 500px :align: center -SDK and Basecoin ----------------- +SDK +--- .. toctree:: :maxdepth: 2 - overview.rst - install.rst - basecoin-basics.rst - basecoin-tool.rst - key-management.rst - roles-and-multi-sig.rst - basecoin-plugins.rst - basecoin-kubernetes.rst - ibc.rst - glossary.rst - stdlib.rst + sdk/overview.rst + sdk/install.rst + sdk/key-management.rst + sdk/roles-and-multi-sig.rst + +Basecoin +-------- + +.. toctree:: + :maxdepth: 2 + + basecoin/basics.rst + basecoin/tool.rst + basecoin/plugins.rst + basecoin/kubernetes.rst Staking Module -------------- @@ -35,6 +39,16 @@ Staking Module .. toctree:: :maxdepth: 2 - staking-module.rst - local-testnet.rst - atlas-testnet.rst + staking/intro.rst + staking/local-testnet.rst + staking/atlas-testnet.rst + +Extras +------ + +.. toctree:: + :maxdepth: 2 + + ibc.rst + glossary.rst + stdlib.rst diff --git a/docs/install.rst b/docs/sdk/install.rst similarity index 100% rename from docs/install.rst rename to docs/sdk/install.rst diff --git a/docs/key-management.rst b/docs/sdk/key-management.rst similarity index 100% rename from docs/key-management.rst rename to docs/sdk/key-management.rst diff --git a/docs/overview.rst b/docs/sdk/overview.rst similarity index 100% rename from docs/overview.rst rename to docs/sdk/overview.rst diff --git a/docs/roles-and-multi-sig.rst b/docs/sdk/roles-and-multi-sig.rst similarity index 100% rename from docs/roles-and-multi-sig.rst rename to docs/sdk/roles-and-multi-sig.rst diff --git a/docs/staking-module.rst b/docs/staking/intro.rst similarity index 100% rename from docs/staking-module.rst rename to docs/staking/intro.rst diff --git a/docs/local-testnet.rst b/docs/staking/local-testnet.rst similarity index 100% rename from docs/local-testnet.rst rename to docs/staking/local-testnet.rst diff --git a/docs/atlas-testnet.rst b/docs/staking/public-testnet.rst similarity index 100% rename from docs/atlas-testnet.rst rename to docs/staking/public-testnet.rst From 2d5ea64e83ca77572b23b116d4c848adf55c706e Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Sat, 9 Dec 2017 19:16:12 +0000 Subject: [PATCH 108/117] docs: gaia pr comments --- docs/index.rst | 2 +- docs/sdk/key-management.rst | 4 ++- docs/staking/intro.rst | 60 ++++++++++++++++++++++++++------- docs/staking/public-testnet.rst | 35 +++++++++---------- 4 files changed, 67 insertions(+), 34 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 4869cfc16444..14b0a1c5c326 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -41,7 +41,7 @@ Staking Module staking/intro.rst staking/local-testnet.rst - staking/atlas-testnet.rst + staking/public-testnet.rst Extras ------ diff --git a/docs/sdk/key-management.rst b/docs/sdk/key-management.rst index ed22bfff43f2..0e7522cc6c83 100644 --- a/docs/sdk/key-management.rst +++ b/docs/sdk/key-management.rst @@ -2,7 +2,9 @@ Key Management ============== Here we explain a bit how to work with your keys, using the -``basecli keys`` subcommand. +``basecli keys`` subcommand. Note that because ``basecli`` is +an implementation of the Cosmmos SDK, other implementations, such +as ``gaia`` will have a compatible set of tooling. **Note:** This keys tooling is not considered production ready and is for dev only. diff --git a/docs/staking/intro.rst b/docs/staking/intro.rst index bc67480ba2c0..8a6fe7d7384d 100644 --- a/docs/staking/intro.rst +++ b/docs/staking/intro.rst @@ -1,9 +1,24 @@ Using Gaia ========== -The purpose of the ``gaia`` staking module is to provide users with the ability to 1) declare candidacy as a validator, 2) bond/unbond to a candidate. +This project is a demonstration of the Cosmos Hub with staking functionality; it is +designed to get validator acquianted with staking concepts and procedure. -For the time being, the ``gaia`` tooling is installed seperately from the Cosmos-SDK: +Potential validators will be declaring their candidacy, after which users can +delegate and, if they so wish, unbond. This can be practiced using a local or +public testnet. + +Setup Testnet +------------- + +The first thing you'll want to do is either `create a local testnet <./local-testnet.html>`__ or +join a `public testnet <./public-testnet.html>`__. Either step is required before proceeding +(although you should browse below and make some keys first). + +Install +------- + +The ``gaia`` tooling is an extension of the Cosmos-SDK; to install: :: @@ -12,7 +27,7 @@ For the time being, the ``gaia`` tooling is installed seperately from the Cosmos make get_vendor_deps make install -The ``gaia`` tool has three primary commands: +It has three primary commands: :: @@ -37,13 +52,6 @@ for sending various transactions and other types of interaction with a running c The rest of this tutorial will cover several commands from ``gaia client`` and assume that you've setup or joined a testnet. -Setup Testnet -------------- - -The first thing you'll want to do is either `create a local testnet <./local-testnet.html>`__ or -join the `atlas testnet <./atlas-testnet.html>`__. Either step is required before proceeding -(although you should browse below and make some keys first). - Generating Keys --------------- @@ -103,7 +111,7 @@ We'll have ``alice`` who is currently quite rich, send some ``fermions`` to ``bo :: - gaia client tx send --amount=992fermion --sequence=1 --name=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 + gaia client tx send --amount=1000fermion --sequence=1 --name=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 where the ``--sequence`` flag is to be incremented for each transaction, the ``--name`` flag names the sender, and the ``--to`` flag takes ``bob``'s address. You'll see something like: @@ -206,7 +214,7 @@ First let's have ``alice`` send some coins to ``charlie``: :: - gaia client tx send --amount=999fermion --sequence=2 --name=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF + gaia client tx send --amount=1000fermion --sequence=2 --name=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF Then ``charlie`` will delegate some fermions to ``bob``: @@ -263,11 +271,35 @@ and you'll see output similar to: } } +It's also possible the query the delegator's bond like so: + +:: + + gaia client query delegator-bond --delegator-address 48F74F48281C89E5E4BE9092F735EA519768E8EF --pubkey 52D6FCD8C92A97F7CCB01205ADF310A18411EA8FDCC10E65BF2FCDB05AD1689B + +with an output similar to: + +:: + + { + "height": 325782, + "data": { + "PubKey": { + "type": "ed25519", + "data": "52D6FCD8C92A97F7CCB01205ADF310A18411EA8FDCC10E65BF2FCDB05AD1689B" + }, + "Shares": 20 + } + } + + +where the ``--delegator-address`` is ``charlie``'s address and the ``-pubkey`` is the same as we've been using. + Unbonding --------- -Finally, to relinquish all your power, unbond some coins. You should see +Finally, to relinquish your voting power, unbond some coins. You should see your VotingPower reduce and your account balance increase. :: @@ -275,4 +307,6 @@ your VotingPower reduce and your account balance increase. gaia client tx unbond --amount=5fermion --name=charlie --pubkey= gaia client query account 48F74F48281C89E5E4BE9092F735EA519768E8EF +See the bond decrease with ``gaia client query delegator-bond`` like above. + That concludes an overview of the ``gaia`` tooling for local testing. diff --git a/docs/staking/public-testnet.rst b/docs/staking/public-testnet.rst index 767b3d7c7ebe..1681095c70e5 100644 --- a/docs/staking/public-testnet.rst +++ b/docs/staking/public-testnet.rst @@ -1,24 +1,18 @@ -Atlas Testnet -============= +Public Testnets +=============== -Atlas is a community testnet which can be used to test setting up a -cosmos validator node. In addition to this tutorial you can also -follow `this video `__. +Here we'll cover the basics of joining a public testnet. These testnets +come and go with various names are we release new versions of tendermint +core. This tutorial covers joining the ``gaia-1`` testnet. To join +other testnets, choose different initialization files, described below. Get Tokens ---------- -To work on the Atlas you'll need some tokens to get started. To do -this first generate a new key: - -:: - - gaia client keys new bob - gaia client keys list - -This will output a bunch of information. Read it carefully, then enter -your key into `this utility `__ with -your key address and it will send you some ``fermion`` testnet tokens. +If you haven't already `created a key <../sdk/key-management.html>`__, +do so now. Copy your key's address and enter it into +`this utility `__ which will send you +some ``fermion`` testnet tokens. Get Files --------- @@ -32,12 +26,15 @@ testnet repo: git clone https://github.com/tendermint/testnets ~/testnets cd ~/testnets/gaia-1/gaia +NOTE: to join a different testnet, change the ``gaia-1/gaia`` filepath +to another directory with testnet inititalization files *and* an +active testnet. Start Node ---------- -Now we can start a new node in the background; note that it may -take awhile to sync with the existing testnet. +Now we can start a new node:it may take awhile to sync with the +existing testnet. :: @@ -52,7 +49,7 @@ Finally, let's initialize the gaia client to interact with the testnet: :: - gaia client init --chain-id=atlas --node=tcp://localhost:46657 + gaia client init --chain-id=gaia-1 --node=tcp://localhost:46657 and check our balance: From 37a82757bd310f1534adc43da62307b0bbd2cb6c Mon Sep 17 00:00:00 2001 From: Andrii Sevastianov Date: Tue, 21 Nov 2017 12:28:49 +0200 Subject: [PATCH 109/117] Update install.rst It looks like some commands were deprecated. I am not sure but old versions are broken anymore. --- docs/sdk/install.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sdk/install.rst b/docs/sdk/install.rst index 5c606c0f4473..4857f63e79c9 100644 --- a/docs/sdk/install.rst +++ b/docs/sdk/install.rst @@ -10,7 +10,7 @@ Usually, Cosmos SDK can be installed like a normal Go program: :: - go get -u github.com/cosmos/cosmos-sdk/cmd/... + go get -u github.com/cosmos/cosmos-sdk If the dependencies have been updated with breaking changes, or if another branch is required, ``glide`` is used for dependency management. @@ -19,7 +19,7 @@ repo, the correct way to install is: :: - cd $GOPATH/src/github.com/tendermint/basecoin + cd $GOPATH/src/github.com/cosmos/cosmos-sdk git pull origin master make all From e2aa526aade7fb468c546804da6a339aa68dede5 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Mon, 11 Dec 2017 16:13:27 +0000 Subject: [PATCH 110/117] gaia docs: cleanup --- docs/staking/intro.rst | 64 ++++++++---------------------------------- 1 file changed, 11 insertions(+), 53 deletions(-) diff --git a/docs/staking/intro.rst b/docs/staking/intro.rst index 8a6fe7d7384d..786c9c44db03 100644 --- a/docs/staking/intro.rst +++ b/docs/staking/intro.rst @@ -8,13 +8,6 @@ Potential validators will be declaring their candidacy, after which users can delegate and, if they so wish, unbond. This can be practiced using a local or public testnet. -Setup Testnet -------------- - -The first thing you'll want to do is either `create a local testnet <./local-testnet.html>`__ or -join a `public testnet <./public-testnet.html>`__. Either step is required before proceeding -(although you should browse below and make some keys first). - Install ------- @@ -49,60 +42,25 @@ The ``gaia rest-server`` command is used by the `cosmos UI ``. Writing -down the recovery phrase is crucial for production keys, however, -for this tutorial you can skip this step. +Review the `key management tutorial <../sdk/key-management.html>`__ and create one key +if you'll be joining the public testnet, and three keys if you'll be trying out a local +testnet. -Because ``alice`` will be the initial validator, we need another key, ``bob`` who will first receives tokens from ``alice``, then declare candidacy as a validator. We also need an account for ``charlie`` who will bond and unbond to ``bob``. - -:: - - gaia client keys new bob - gaia client keys new charlie - -Now we can see the keys we've created: - -:: - - gaia client keys list - -which shows something like: - -:: +Setup Testnet +------------- - All keys: - alice 5D93A6059B6592833CBC8FA3DA90EE0382198985 - bob 5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 - charlie 48F74F48281C89E5E4BE9092F735EA519768E8EF +The first thing you'll want to do is either `create a local testnet <./local-testnet.html>`__ or +join a `public testnet <./public-testnet.html>`__. Either step is required before proceeding. -Try adding the ``--output json`` flag to the above command to get more information. -The information for these keys is stored in ``~/.cosmos-gaia-cli``. -We've got our keys made, so let's move on to the next step. +The rest of this tutorial will assume a local testnet with three participants: ``alice`` will be +the initial validator, ``bob`` will first receives tokens from ``alice`` then declare candidacy +as a validator, and ``charlie`` will bond then unbond to ``bob``. If you're joining the public +testnet, the token amounts will need to be adjusted. Sending Tokens -------------- From 3c8bd03209c1cd41d570cc3b64bf03b75373cd5a Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 11 Dec 2017 15:17:43 -0500 Subject: [PATCH 111/117] bring back basecli proxy ws --- client/proxy.go | 6 +----- glide.lock | 8 ++++---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/client/proxy.go b/client/proxy.go index 26d12069c16a..00b98f0bf7d6 100644 --- a/client/proxy.go +++ b/client/proxy.go @@ -25,11 +25,7 @@ func StartProxy(c rpcclient.Client, bind string, logger log.Logger) error { mux := http.NewServeMux() rpc.RegisterRPCFuncs(mux, r, logger) - onDisconnect := rpc.OnDisconnect(func(remoteAddr string) { - // FIXME: TODO - // n.eventBus.UnsubscribeAll(context.Background(), remoteAddr) - }) - wm := rpc.NewWebsocketManager(r, onDisconnect) + wm := rpc.NewWebsocketManager(r, rpc.EventSubscriber(c)) wm.SetLogger(logger) core.SetLogger(logger) mux.HandleFunc(wsEndpoint, wm.WebsocketHandler) diff --git a/glide.lock b/glide.lock index 2793a6242ff3..e6d71c944442 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: da24779c9db3af6dc6427b7d1ae84a725bf454f7785c09d3dfc1a160442aca9f -updated: 2017-12-08T18:41:01.918184161-05:00 +updated: 2017-12-11T15:11:10.66123844-05:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -143,7 +143,7 @@ imports: - keys/wordlist - nano - name: github.com/tendermint/go-wire - version: 51453fda64ba68061b42e17b17e68469993e0a02 + version: 27be46e25124ddf775e23317a83647ce62a93f6b subpackages: - data - data/base58 @@ -151,7 +151,7 @@ imports: - name: github.com/tendermint/iavl version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653 - name: github.com/tendermint/tendermint - version: 7e3a5b7ce8e8a92b81eb99e3a6c1451e6d271d36 + version: 5c58db3bb49e35d0cc2a32de904cb754e5fd1c7b subpackages: - blockchain - certifiers @@ -187,7 +187,7 @@ imports: - types - version - name: github.com/tendermint/tmlibs - version: b49bce2bc3fb8fa25f676b9b49cce5e10f89b0c6 + version: d836ee056db0e454ab33b0f17c03308bcce92c48 subpackages: - autofile - cli From 96eb709c3d51ce7abd5031161edf087301a75324 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 11 Dec 2017 15:22:03 -0500 Subject: [PATCH 112/117] fix ws on baseserver too --- examples/basecoin/cmd/baseserver/main.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/examples/basecoin/cmd/baseserver/main.go b/examples/basecoin/cmd/baseserver/main.go index 99c686d5620e..ae26c1fbc45f 100644 --- a/examples/basecoin/cmd/baseserver/main.go +++ b/examples/basecoin/cmd/baseserver/main.go @@ -82,12 +82,8 @@ func serve(cmd *cobra.Command, args []string) error { port := viper.GetInt(envPortFlag) addr := fmt.Sprintf(":%d", port) - onDisconnect := rpcserver.OnDisconnect(func(remoteAddr string) { - // FIXME: TODO - // n.eventBus.UnsubscribeAll(context.Background(), remoteAddr) - }) routes := client.RPCRoutes(rpcClient) - wm := rpcserver.NewWebsocketManager(routes, onDisconnect) + wm := rpcserver.NewWebsocketManager(routes, rpcserver.EventSubscriber(rpcClient)) wsLogger := tmlog.NewTMLogger(tmlog.NewSyncWriter(os.Stdout)).With("module", "ws") wm.SetLogger(wsLogger) router.HandleFunc("/websocket", wm.WebsocketHandler) From be493ddaaf40664fd25c4561fc8cf0ca9d35b570 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 29 Dec 2017 11:57:28 -0500 Subject: [PATCH 113/117] update for tendermint v0.15 --- app/store.go | 2 +- app/val_test.go | 2 +- glide.lock | 62 ++++++++++++++++++------------------ glide.yaml | 2 +- modules/ibc/provider_test.go | 3 +- modules/ibc/test_helpers.go | 4 ++- 6 files changed, 39 insertions(+), 36 deletions(-) diff --git a/app/store.go b/app/store.go index 6ea079b7bc14..e61eecf80a0e 100644 --- a/app/store.go +++ b/app/store.go @@ -214,7 +214,7 @@ func (app *StoreApp) BeginBlock(_ abci.RequestBeginBlock) (res abci.ResponseBegi // Returns a list of all validator changes made in this block func (app *StoreApp) EndBlock(_ abci.RequestEndBlock) (res abci.ResponseEndBlock) { // TODO: cleanup in case a validator exists multiple times in the list - res.Diffs = app.pending + res.ValidatorUpdates = app.pending app.pending = nil return } diff --git a/app/val_test.go b/app/val_test.go index 5c976806740e..869d26cd7df3 100644 --- a/app/val_test.go +++ b/app/val_test.go @@ -83,6 +83,6 @@ func TestEndBlock(t *testing.T) { } diff := app.EndBlock(abci.RequestEndBlock{app.height}) // TODO: don't care about order here... - assert.Equal(tc.expected, diff.Diffs, "%d", i) + assert.Equal(tc.expected, diff.ValidatorUpdates, "%d", i) } } diff --git a/glide.lock b/glide.lock index e6d71c944442..a206d73d1f6b 100644 --- a/glide.lock +++ b/glide.lock @@ -1,10 +1,10 @@ -hash: da24779c9db3af6dc6427b7d1ae84a725bf454f7785c09d3dfc1a160442aca9f -updated: 2017-12-11T15:11:10.66123844-05:00 +hash: 72888dd9269f49dc4907ba794a931c4f922fd540df66a5f85d305300b997d702 +updated: 2017-12-29T11:44:31.323713454-05:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd - name: github.com/btcsuite/btcd - version: c7588cbf7690cd9f047a28efa2dcd8f2435a4e5e + version: 2e60448ffcc6bf78332d1fe590260095f554dd78 subpackages: - btcec - name: github.com/BurntSushi/toml @@ -18,7 +18,7 @@ imports: - name: github.com/fsnotify/fsnotify version: 4da3e2cfbabc9f751898f250b49f2439785783a1 - name: github.com/go-kit/kit - version: d67bb4c202e3b91377d1079b110a6c9ce23ab2f8 + version: 953e747656a7bbb5e1f998608b460458958b70cc subpackages: - log - log/level @@ -26,13 +26,13 @@ imports: - name: github.com/go-logfmt/logfmt version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 - name: github.com/go-playground/locales - version: 1e5f1161c6416a5ff48840eb8724a394e48cc534 + version: e4cbcb5d0652150d40ad0646651076b6bd2be4f6 subpackages: - currency - name: github.com/go-playground/universal-translator version: 71201497bace774495daed26a3874fd339e0b538 - name: github.com/go-stack/stack - version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 + version: 259ab82a6cad3992b4e21ff5cac294ccb06474bc - name: github.com/gogo/protobuf version: 342cbe0a04158f6dcb03ca0079991a51a4248c02 subpackages: @@ -43,7 +43,7 @@ imports: - sortkeys - types - name: github.com/golang/protobuf - version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9 + version: 1e59b77b52bf8e4b449a57e6f79f21226d571845 subpackages: - proto - ptypes @@ -55,7 +55,7 @@ imports: - name: github.com/gorilla/context version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42 - name: github.com/gorilla/mux - version: 24fca303ac6da784b9e8269f724ddeb0b2eea5e7 + version: 5ab525f4fb1678e197ae59401e9050fa0b6cb5fd - name: github.com/gorilla/websocket version: ea4d1f681babbce9545c9c5f3d5194a789c89f5b - name: github.com/hashicorp/hcl @@ -70,7 +70,7 @@ imports: - json/scanner - json/token - name: github.com/howeyc/crc16 - version: 96a97a1abb579c7ff1a8ffa77f2e72d1c314b57f + version: 2b2a61e366a66d3efb279e46176e7291001e0354 - name: github.com/inconshreveable/mousetrap version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 - name: github.com/jmhodges/levigo @@ -78,21 +78,19 @@ imports: - name: github.com/kr/logfmt version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/magiconair/properties - version: 8d7837e64d3c1ee4e54a880c5a920ab4316fc90a + version: 49d762b9817ba1c2e9d0c69183c2b4a8b8f1d934 - name: github.com/mattn/go-isatty - version: a5cdd64afdee435007ee3e9f6ed4684af949d568 + version: 6ca4dbf54d38eea1a992b3c722a76a5d1c4cb25c - name: github.com/mitchellh/mapstructure version: 06020f85339e21b2478f756a78e295255ffa4d6a -- name: github.com/pelletier/go-buffruneio - version: c37440a7cf42ac63b919c752ca73a85067e05992 - name: github.com/pelletier/go-toml - version: 13d49d4606eb801b8f01ae542b4afc4c6ee3d84a + version: 0131db6d737cfbbfb678f8b7d92e55e27ce46224 - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d - name: github.com/rcrowley/go-metrics - version: 1f30fe9094a513ce4c700b9a54458bbb0c96996c + version: e181e095bae94582363434144c61a9653aff6e50 - name: github.com/spf13/afero - version: 5660eeed305fe5f69c8fc6cf899132a459a97064 + version: 57afd63c68602b63ed976de00dd066ccb3c319db subpackages: - mem - name: github.com/spf13/cast @@ -102,11 +100,11 @@ imports: - name: github.com/spf13/jwalterweatherman version: 12bd96e66386c1960ab0f74ced1362f66f552f7b - name: github.com/spf13/pflag - version: 97afa5e7ca8a08a383cb259e06636b5e2cc7897f + version: 4c012f6dcd9546820e378d0bdda4d8fc772cdfea - name: github.com/spf13/viper version: 25b30aa063fc18e48662b86996252eabdcf2f0c7 - name: github.com/syndtr/goleveldb - version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 + version: 34011bf325bce385408353a30b101fe5e923eb6e subpackages: - leveldb - leveldb/cache @@ -121,7 +119,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: fca2b508c185b855af1446ec4afc19bdfc7b315d + version: 70da70d8529392676b803f64f61092079391946b subpackages: - client - example/code @@ -134,7 +132,7 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-crypto - version: b4f04f196cd719660e43b91202cd60d9a95b1837 + version: 4041adbf92a970d01792b99d43312d08fc4a794a subpackages: - keys - keys/cryptostore @@ -151,7 +149,7 @@ imports: - name: github.com/tendermint/iavl version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653 - name: github.com/tendermint/tendermint - version: 5c58db3bb49e35d0cc2a32de904cb754e5fd1c7b + version: 60f95cd9ea1dbba01c25ca903f8bd76999fef7d9 subpackages: - blockchain - certifiers @@ -161,10 +159,12 @@ imports: - config - consensus - consensus/types + - evidence - lite - lite/client - lite/errors - lite/files + - lite/proxy - mempool - node - p2p @@ -187,7 +187,7 @@ imports: - types - version - name: github.com/tendermint/tmlibs - version: d836ee056db0e454ab33b0f17c03308bcce92c48 + version: 35e6f11ad445cf4cb19fefadba0517a86f00b1fc subpackages: - autofile - cli @@ -203,7 +203,7 @@ imports: - pubsub - pubsub/query - name: golang.org/x/crypto - version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e + version: 95a4943f35d008beabde8c11e5075a1b714e6419 subpackages: - curve25519 - nacl/box @@ -214,7 +214,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: cd69bc3fc700721b709c3a59e16e24c67b58f6ff + version: d866cfc389cec985d6fda2859936a575a55a3ab6 subpackages: - context - http2 @@ -224,18 +224,18 @@ imports: - lex/httplex - trace - name: golang.org/x/sys - version: 8dbc5d05d6edcc104950cc299a1ce6641235bc86 + version: 83801418e1b59fb1880e363299581ee543af32ca subpackages: - unix - name: golang.org/x/text - version: c01e4764d870b77f8abe5096ee19ad20d80e8075 + version: e19ae1496984b1c655b8044a65c0300a3c878dd3 subpackages: - secure/bidirule - transform - unicode/bidi - unicode/norm - name: google.golang.org/genproto - version: f676e0f3ac6395ff1a529ae59a6670878a8371a6 + version: a8101f21cf983e773d0c1133ebc5424792003214 subpackages: - googleapis/rpc/status - name: google.golang.org/grpc @@ -258,12 +258,12 @@ imports: - tap - transport - name: gopkg.in/go-playground/validator.v9 - version: 6d8c18553ea1ac493d049edd6f102f52e618f085 + version: b1f51f36f1c98cc97f777d6fc9d4b05eaa0cabb5 - name: gopkg.in/yaml.v2 - version: eb3733d160e74a9c7e442f435eb3bea458e1d19f + version: 287cf08546ab5e7e37d55a84f7ed3fd1db036de5 testImports: - name: github.com/davecgh/go-spew - version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 + version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 subpackages: - spew - name: github.com/pmezard/go-difflib @@ -271,7 +271,7 @@ testImports: subpackages: - difflib - name: github.com/stretchr/testify - version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 + version: 2aa2c176b9dab406a6970f6a55f513e8a8c8b18f subpackages: - assert - require diff --git a/glide.yaml b/glide.yaml index d309c51601b9..7bc38ec5f7cc 100644 --- a/glide.yaml +++ b/glide.yaml @@ -27,7 +27,7 @@ import: - package: github.com/tendermint/iavl version: develop - package: github.com/tendermint/tendermint - version: develop + version: release-v0.15.0 subpackages: - certifiers - certifiers/client diff --git a/modules/ibc/provider_test.go b/modules/ibc/provider_test.go index 4690198c7960..7c41c8bc8c5e 100644 --- a/modules/ibc/provider_test.go +++ b/modules/ibc/provider_test.go @@ -84,7 +84,8 @@ func makeCommits(keys lite.ValKeys, count int, chainID, app string) []lite.FullC // (10, 0), (10, 1), (10, 1), (10, 2), (10, 2), ... vals := keys.ToValidators(10, int64(count/2)) h := int64(20 + 10*i) - commits[i] = keys.GenFullCommit(chainID, h, nil, vals, appHash, 0, len(keys)) + consHash, resHash := []byte{}, []byte{} + commits[i] = keys.GenFullCommit(chainID, h, nil, vals, appHash, consHash, resHash, 0, len(keys)) } return commits } diff --git a/modules/ibc/test_helpers.go b/modules/ibc/test_helpers.go index 480a9254aca2..2b9dc63282f6 100644 --- a/modules/ibc/test_helpers.go +++ b/modules/ibc/test_helpers.go @@ -50,9 +50,11 @@ func (m MockChain) MakePostPacket(packet Packet, h int64) ( func genEmptyCommit(keys lite.ValKeys, chain string, h int64, appHash []byte, count int) lite.FullCommit { + var consHash []byte + var resHash []byte vals := keys.ToValidators(10, 0) - return keys.GenFullCommit(chain, h, nil, vals, appHash, 0, count) + return keys.GenFullCommit(chain, h, nil, vals, appHash, consHash, resHash, 0, count) } func makePostPacket(tree *iavl.Tree, packet Packet, fromID string, fromHeight int64) PostPacketTx { From a255fe4136298e157cc5d3dc6ce1e34745c6e205 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 29 Dec 2017 16:16:43 -0500 Subject: [PATCH 114/117] default chain_id is local --- server/commands/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/commands/init.go b/server/commands/init.go index b5ffebf78e63..c27278d11d38 100644 --- a/server/commands/init.go +++ b/server/commands/init.go @@ -36,7 +36,7 @@ func GetInitCmd(defaultDenom string, options []string) *cobra.Command { Short: "Initialize genesis files for a blockchain", RunE: initCmd, } - initCmd.Flags().String(FlagChainID, "test_chain_id", "Chain ID") + initCmd.Flags().String(FlagChainID, "local", "Chain ID") initCmd.Flags().String(FlagDenom, defaultDenom, "Coin denomination for genesis account") initCmd.Flags().StringSliceP(FlagOption, "p", options, "Genesis option in the format /