From f8e44b5b00d62eba5eaded6bcd1272422b46e581 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 18 Apr 2018 04:16:21 +0200 Subject: [PATCH 01/71] Error codespacing (#809) * Initial codespacing layout (ref #766) * Add codespace to Router (ref #766) * Implement Codespacer and update modules * Default codespaces, testcases * Update error formatting, codespacer tests * Add RegisterOrPanic testcase * Update CHANGELOG --- CHANGELOG.md | 1 + Gopkg.lock | 9 +- baseapp/baseapp.go | 34 +++-- client/lcd/lcd_test.go | 8 +- examples/basecoin/app/app.go | 6 +- examples/basecoin/app/app_test.go | 12 +- examples/democoin/app/app.go | 10 +- examples/democoin/app/app_test.go | 18 +-- examples/democoin/x/cool/errors.go | 6 +- examples/democoin/x/cool/handler.go | 2 +- examples/democoin/x/cool/keeper.go | 6 +- examples/democoin/x/pow/errors.go | 34 +++-- examples/democoin/x/pow/handler_test.go | 2 +- examples/democoin/x/pow/keeper.go | 19 +-- examples/democoin/x/pow/keeper_test.go | 2 +- examples/democoin/x/pow/types.go | 6 +- store/rootmultistore_test.go | 12 +- types/codespacer.go | 35 +++++ types/codespacer_test.go | 47 ++++++ types/errors.go | 191 +++++++++++++----------- types/errors_test.go | 9 +- types/rational.go | 8 +- types/result.go | 2 +- x/auth/ante_test.go | 4 +- x/bank/errors.go | 22 +-- x/bank/msgs.go | 6 +- x/ibc/errors.go | 14 +- x/ibc/handler.go | 2 +- x/ibc/ibc_test.go | 2 +- x/ibc/mapper.go | 12 +- x/ibc/types.go | 2 +- x/simplestake/errors.go | 22 +-- x/simplestake/handler.go | 4 +- x/simplestake/keeper.go | 22 +-- x/simplestake/keeper_test.go | 8 +- x/simplestake/msgs.go | 2 +- x/stake/errors.go | 82 +++++----- x/stake/handler.go | 24 +-- x/stake/keeper.go | 6 +- x/stake/msg.go | 28 ++-- x/stake/test_common.go | 2 +- 41 files changed, 438 insertions(+), 305 deletions(-) create mode 100644 types/codespacer.go create mode 100644 types/codespacer_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 1612f083f..873824c48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ BREAKING CHANGES * Remove go-wire, use go-amino * [store] Add `SubspaceIterator` and `ReverseSubspaceIterator` to `KVStore` interface * [basecoin] NewBasecoinApp takes a `dbm.DB` and uses namespaced DBs for substores +* All module keepers now require a codespace, see basecoin or democoin for usage BUG FIXES diff --git a/Gopkg.lock b/Gopkg.lock index eb2a1c8ca..6d225e261 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -342,7 +342,7 @@ "types/priv_validator", "version" ] - revision = "d0beaba7e8a5652506a34b5fab299cc2dc274c02" + revision = "a2930cd7233f04f5a651020669289296545e70dc" version = "v0.19.0" [[projects]] @@ -384,6 +384,7 @@ name = "golang.org/x/net" packages = [ "context", + "http/httpguts", "http2", "http2/hpack", "idna", @@ -391,13 +392,13 @@ "lex/httplex", "trace" ] - revision = "61147c48b25b599e5b561d2e9c4f3e1ef489ca41" + revision = "8d16fa6dc9a85c1cd3ed24ad08ff21cf94f10888" [[projects]] branch = "master" name = "golang.org/x/sys" packages = ["unix"] - revision = "3b87a42e500a6dc65dae1a55d0b641295971163e" + revision = "b126b21c05a91c856b027c16779c12e3bf236954" [[projects]] name = "golang.org/x/text" @@ -424,7 +425,7 @@ branch = "master" name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] - revision = "51d0944304c3cbce4afe9e5247e21100037bff78" + revision = "7fd901a49ba6a7f87732eb344f6e3c5b19d1b200" [[projects]] name = "google.golang.org/grpc" diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 884528876..115748ca5 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -24,11 +24,12 @@ var dbHeaderKey = []byte("header") // The ABCI application type BaseApp struct { // initialized on creation - Logger log.Logger - name string // application name from abci.Info - db dbm.DB // common DB backend - cms sdk.CommitMultiStore // Main (uncached) state - router Router // handle any kind of message + Logger log.Logger + name string // application name from abci.Info + db dbm.DB // common DB backend + cms sdk.CommitMultiStore // Main (uncached) state + router Router // handle any kind of message + codespacer *sdk.Codespacer // handle module codespacing // must be set txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx @@ -56,13 +57,18 @@ var _ abci.Application = (*BaseApp)(nil) // Create and name new BaseApp // NOTE: The db is used to store the version number for now. func NewBaseApp(name string, logger log.Logger, db dbm.DB) *BaseApp { - return &BaseApp{ - Logger: logger, - name: name, - db: db, - cms: store.NewCommitMultiStore(db), - router: NewRouter(), + app := &BaseApp{ + Logger: logger, + name: name, + db: db, + cms: store.NewCommitMultiStore(db), + router: NewRouter(), + codespacer: sdk.NewCodespacer(), } + // Register the undefined & root codespaces, which should not be used by any modules + app.codespacer.RegisterOrPanic(sdk.CodespaceUndefined) + app.codespacer.RegisterOrPanic(sdk.CodespaceRoot) + return app } // BaseApp Name @@ -70,6 +76,11 @@ func (app *BaseApp) Name() string { return app.name } +// Register the next available codespace through the baseapp's codespacer, starting from a default +func (app *BaseApp) RegisterCodespace(codespace sdk.CodespaceType) sdk.CodespaceType { + return app.codespacer.RegisterNext(codespace) +} + // Mount a store to the provided key in the BaseApp multistore func (app *BaseApp) MountStoresIAVL(keys ...*sdk.KVStoreKey) { for _, key := range keys { @@ -355,6 +366,7 @@ func (app *BaseApp) runTx(isCheckTx bool, txBytes []byte, tx sdk.Tx) (result sdk // Validate the Msg. err := msg.ValidateBasic() if err != nil { + err = err.WithDefaultCodespace(sdk.CodespaceRoot) return err.Result() } diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 0e7ce7b7b..e84ff8e9b 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -80,7 +80,7 @@ func TestKeys(t *testing.T) { jsonStr = []byte(fmt.Sprintf(`{"name":"%s", "password":"%s", "seed": "%s"}`, newName, newPassword, newSeed)) res, body = request(t, port, "POST", "/keys", jsonStr) - assert.Equal(t, http.StatusOK, res.StatusCode, body) + require.Equal(t, http.StatusOK, res.StatusCode, body) addr := body assert.Len(t, addr, 40, "Returned address has wrong format", addr) @@ -311,7 +311,11 @@ func TestTxs(t *testing.T) { // strt TM and the LCD in process, listening on their respective sockets func startTMAndLCD() (*nm.Node, net.Listener, error) { - viper.Set(cli.HomeFlag, os.TempDir()) + dir, err := ioutil.TempDir("", "lcd_test") + if err != nil { + return nil, nil, err + } + viper.Set(cli.HomeFlag, dir) kb, err := keys.GetKeyBase() // dbm.NewMemDB()) // :( if err != nil { return nil, nil, err diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index ae60e8a73..bb3ef05ac 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -65,8 +65,8 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp { // Add handlers. coinKeeper := bank.NewCoinKeeper(app.accountMapper) - ibcMapper := ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore) - stakeKeeper := simplestake.NewKeeper(app.capKeyStakingStore, coinKeeper) + ibcMapper := ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore, app.RegisterCodespace(ibc.DefaultCodespace)) + stakeKeeper := simplestake.NewKeeper(app.capKeyStakingStore, coinKeeper, app.RegisterCodespace(simplestake.DefaultCodespace)) app.Router(). AddRoute("bank", bank.NewHandler(coinKeeper)). AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)). @@ -123,7 +123,7 @@ func (app *BasecoinApp) txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) { // are registered by MakeTxCodec in bank.RegisterAmino. err := app.cdc.UnmarshalBinary(txBytes, &tx) if err != nil { - return nil, sdk.ErrTxDecode("").TraceCause(err, "") + return nil, sdk.ErrTxDecode("").Trace(err.Error()) } return tx, nil } diff --git a/examples/basecoin/app/app_test.go b/examples/basecoin/app/app_test.go index ead49adc2..bc1735dde 100644 --- a/examples/basecoin/app/app_test.go +++ b/examples/basecoin/app/app_test.go @@ -166,7 +166,7 @@ func TestSortGenesis(t *testing.T) { // Unsorted coins means invalid err := sendMsg5.ValidateBasic() - require.Equal(t, sdk.CodeInvalidCoins, err.ABCICode(), err.ABCILog()) + require.Equal(t, sdk.CodeInvalidCoins, err.Code(), err.ABCILog()) // Sort coins, should be valid sendMsg5.Inputs[0].Coins.Sort() @@ -243,7 +243,7 @@ func TestSendMsgWithAccounts(t *testing.T) { tx.Signatures[0].Sequence = 1 res := bapp.Deliver(tx) - assert.Equal(t, sdk.CodeUnauthorized, res.Code, res.Log) + assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log) // resigning the tx with the bumped sequence should work SignCheckDeliver(t, bapp, sendMsg1, []int64{1}, true, priv1) @@ -437,18 +437,18 @@ func SignCheckDeliver(t *testing.T, bapp *BasecoinApp, msg sdk.Msg, seq []int64, // Run a Check res := bapp.Check(tx) if expPass { - require.Equal(t, sdk.CodeOK, res.Code, res.Log) + require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) } else { - require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log) } // Simulate a Block bapp.BeginBlock(abci.RequestBeginBlock{}) res = bapp.Deliver(tx) if expPass { - require.Equal(t, sdk.CodeOK, res.Code, res.Log) + require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) } else { - require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log) } bapp.EndBlock(abci.RequestEndBlock{}) //bapp.Commit() diff --git a/examples/democoin/app/app.go b/examples/democoin/app/app.go index 151241d14..4e5e4e22f 100644 --- a/examples/democoin/app/app.go +++ b/examples/democoin/app/app.go @@ -70,10 +70,10 @@ func NewDemocoinApp(logger log.Logger, db dbm.DB) *DemocoinApp { // Add handlers. coinKeeper := bank.NewCoinKeeper(app.accountMapper) - coolKeeper := cool.NewKeeper(app.capKeyMainStore, coinKeeper) - powKeeper := pow.NewKeeper(app.capKeyPowStore, pow.NewPowConfig("pow", int64(1)), coinKeeper) - ibcMapper := ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore) - stakeKeeper := simplestake.NewKeeper(app.capKeyStakingStore, coinKeeper) + coolKeeper := cool.NewKeeper(app.capKeyMainStore, coinKeeper, app.RegisterCodespace(cool.DefaultCodespace)) + powKeeper := pow.NewKeeper(app.capKeyPowStore, pow.NewPowConfig("pow", int64(1)), coinKeeper, app.RegisterCodespace(pow.DefaultCodespace)) + ibcMapper := ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore, app.RegisterCodespace(ibc.DefaultCodespace)) + stakeKeeper := simplestake.NewKeeper(app.capKeyStakingStore, coinKeeper, app.RegisterCodespace(simplestake.DefaultCodespace)) app.Router(). AddRoute("bank", bank.NewHandler(coinKeeper)). AddRoute("cool", cool.NewHandler(coolKeeper)). @@ -136,7 +136,7 @@ func (app *DemocoinApp) txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) { // are registered by MakeTxCodec in bank.RegisterWire. err := app.cdc.UnmarshalBinary(txBytes, &tx) if err != nil { - return nil, sdk.ErrTxDecode("").TraceCause(err, "") + return nil, sdk.ErrTxDecode("").Trace(err.Error()) } return tx, nil } diff --git a/examples/democoin/app/app_test.go b/examples/democoin/app/app_test.go index ca4e2509e..f17e2a9b0 100644 --- a/examples/democoin/app/app_test.go +++ b/examples/democoin/app/app_test.go @@ -202,12 +202,12 @@ func TestSendMsgWithAccounts(t *testing.T) { // Run a Check res := bapp.Check(tx) - assert.Equal(t, sdk.CodeOK, res.Code, res.Log) + assert.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) // Simulate a Block bapp.BeginBlock(abci.RequestBeginBlock{}) res = bapp.Deliver(tx) - assert.Equal(t, sdk.CodeOK, res.Code, res.Log) + assert.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) // Check balances ctxDeliver := bapp.BaseApp.NewContext(false, abci.Header{}) @@ -218,19 +218,19 @@ func TestSendMsgWithAccounts(t *testing.T) { // Delivering again should cause replay error res = bapp.Deliver(tx) - assert.Equal(t, sdk.CodeInvalidSequence, res.Code, res.Log) + assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeInvalidSequence), sdk.ABCICodeType(res.Code), res.Log) // bumping the txnonce number without resigning should be an auth error tx.Signatures[0].Sequence = 1 res = bapp.Deliver(tx) - assert.Equal(t, sdk.CodeUnauthorized, res.Code, res.Log) + assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), sdk.ABCICodeType(res.Code), res.Log) // resigning the tx with the bumped sequence should work sequences = []int64{1} sig = priv1.Sign(sdk.StdSignBytes(chainID, sequences, fee, tx.Msg)) tx.Signatures[0].Signature = sig res = bapp.Deliver(tx) - assert.Equal(t, sdk.CodeOK, res.Code, res.Log) + assert.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) } func TestMineMsg(t *testing.T) { @@ -403,18 +403,18 @@ func SignCheckDeliver(t *testing.T, bapp *DemocoinApp, msg sdk.Msg, seq int64, e // Run a Check res := bapp.Check(tx) if expPass { - require.Equal(t, sdk.CodeOK, res.Code, res.Log) + require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) } else { - require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log) } // Simulate a Block bapp.BeginBlock(abci.RequestBeginBlock{}) res = bapp.Deliver(tx) if expPass { - require.Equal(t, sdk.CodeOK, res.Code, res.Log) + require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) } else { - require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log) } bapp.EndBlock(abci.RequestEndBlock{}) //bapp.Commit() diff --git a/examples/democoin/x/cool/errors.go b/examples/democoin/x/cool/errors.go index 5db3efc39..4c28f94ba 100644 --- a/examples/democoin/x/cool/errors.go +++ b/examples/democoin/x/cool/errors.go @@ -7,11 +7,13 @@ import ( ) const ( + DefaultCodespace sdk.CodespaceType = 6 + // Cool module reserves error 400-499 lawl CodeIncorrectCoolAnswer sdk.CodeType = 400 ) // ErrIncorrectCoolAnswer - Error returned upon an incorrect guess -func ErrIncorrectCoolAnswer(answer string) sdk.Error { - return sdk.NewError(CodeIncorrectCoolAnswer, fmt.Sprintf("Incorrect cool answer: %v", answer)) +func ErrIncorrectCoolAnswer(codespace sdk.CodespaceType, answer string) sdk.Error { + return sdk.NewError(codespace, CodeIncorrectCoolAnswer, fmt.Sprintf("Incorrect cool answer: %v", answer)) } diff --git a/examples/democoin/x/cool/handler.go b/examples/democoin/x/cool/handler.go index ce86ecd5b..e2b36b218 100644 --- a/examples/democoin/x/cool/handler.go +++ b/examples/democoin/x/cool/handler.go @@ -44,7 +44,7 @@ func handleQuizMsg(ctx sdk.Context, k Keeper, msg QuizMsg) sdk.Result { correct := k.CheckTrend(ctx, msg.CoolAnswer) if !correct { - return ErrIncorrectCoolAnswer(msg.CoolAnswer).Result() + return ErrIncorrectCoolAnswer(k.codespace, msg.CoolAnswer).Result() } if ctx.IsCheckTx() { diff --git a/examples/democoin/x/cool/keeper.go b/examples/democoin/x/cool/keeper.go index 0a4fc81e1..3b6c8e9ae 100644 --- a/examples/democoin/x/cool/keeper.go +++ b/examples/democoin/x/cool/keeper.go @@ -10,11 +10,13 @@ type Keeper struct { ck bank.CoinKeeper storeKey sdk.StoreKey // The (unexposed) key used to access the store from the Context. + + codespace sdk.CodespaceType } // NewKeeper - Returns the Keeper -func NewKeeper(key sdk.StoreKey, bankKeeper bank.CoinKeeper) Keeper { - return Keeper{bankKeeper, key} +func NewKeeper(key sdk.StoreKey, bankKeeper bank.CoinKeeper, codespace sdk.CodespaceType) Keeper { + return Keeper{bankKeeper, key, codespace} } // Key to knowing the trend on the streets! diff --git a/examples/democoin/x/pow/errors.go b/examples/democoin/x/pow/errors.go index b44eb93d6..d387f9b9a 100644 --- a/examples/democoin/x/pow/errors.go +++ b/examples/democoin/x/pow/errors.go @@ -7,6 +7,8 @@ import ( type CodeType = sdk.CodeType const ( + DefaultCodespace sdk.CodespaceType = 5 + CodeInvalidDifficulty CodeType = 201 CodeNonexistentDifficulty CodeType = 202 CodeNonexistentReward CodeType = 203 @@ -40,32 +42,32 @@ func codeToDefaultMsg(code CodeType) string { } } -func ErrInvalidDifficulty(msg string) sdk.Error { - return newError(CodeInvalidDifficulty, msg) +func ErrInvalidDifficulty(codespace sdk.CodespaceType, msg string) sdk.Error { + return newError(codespace, CodeInvalidDifficulty, msg) } -func ErrNonexistentDifficulty() sdk.Error { - return newError(CodeNonexistentDifficulty, "") +func ErrNonexistentDifficulty(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeNonexistentDifficulty, "") } -func ErrNonexistentReward() sdk.Error { - return newError(CodeNonexistentReward, "") +func ErrNonexistentReward(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeNonexistentReward, "") } -func ErrNonexistentCount() sdk.Error { - return newError(CodeNonexistentCount, "") +func ErrNonexistentCount(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeNonexistentCount, "") } -func ErrInvalidProof(msg string) sdk.Error { - return newError(CodeInvalidProof, msg) +func ErrInvalidProof(codespace sdk.CodespaceType, msg string) sdk.Error { + return newError(codespace, CodeInvalidProof, msg) } -func ErrNotBelowTarget(msg string) sdk.Error { - return newError(CodeNotBelowTarget, msg) +func ErrNotBelowTarget(codespace sdk.CodespaceType, msg string) sdk.Error { + return newError(codespace, CodeNotBelowTarget, msg) } -func ErrInvalidCount(msg string) sdk.Error { - return newError(CodeInvalidCount, msg) +func ErrInvalidCount(codespace sdk.CodespaceType, msg string) sdk.Error { + return newError(codespace, CodeInvalidCount, msg) } func msgOrDefaultMsg(msg string, code CodeType) string { @@ -76,7 +78,7 @@ func msgOrDefaultMsg(msg string, code CodeType) string { } } -func newError(code CodeType, msg string) sdk.Error { +func newError(codespace sdk.CodespaceType, code CodeType, msg string) sdk.Error { msg = msgOrDefaultMsg(msg, code) - return sdk.NewError(code, msg) + return sdk.NewError(codespace, code, msg) } diff --git a/examples/democoin/x/pow/handler_test.go b/examples/democoin/x/pow/handler_test.go index a05932780..4b1a571f7 100644 --- a/examples/democoin/x/pow/handler_test.go +++ b/examples/democoin/x/pow/handler_test.go @@ -22,7 +22,7 @@ func TestPowHandler(t *testing.T) { ctx := sdk.NewContext(ms, abci.Header{}, false, nil) config := NewPowConfig("pow", int64(1)) ck := bank.NewCoinKeeper(am) - keeper := NewKeeper(capKey, config, ck) + keeper := NewKeeper(capKey, config, ck, DefaultCodespace) handler := keeper.Handler diff --git a/examples/democoin/x/pow/keeper.go b/examples/democoin/x/pow/keeper.go index 73558632c..70453d6d6 100644 --- a/examples/democoin/x/pow/keeper.go +++ b/examples/democoin/x/pow/keeper.go @@ -21,17 +21,18 @@ type PowGenesis struct { } type Keeper struct { - key sdk.StoreKey - config PowConfig - ck bank.CoinKeeper + key sdk.StoreKey + config PowConfig + ck bank.CoinKeeper + codespace sdk.CodespaceType } func NewPowConfig(denomination string, reward int64) PowConfig { return PowConfig{denomination, reward} } -func NewKeeper(key sdk.StoreKey, config PowConfig, ck bank.CoinKeeper) Keeper { - return Keeper{key, config, ck} +func NewKeeper(key sdk.StoreKey, config PowConfig, ck bank.CoinKeeper, codespace sdk.CodespaceType) Keeper { + return Keeper{key, config, ck, codespace} } func (pk Keeper) InitGenesis(ctx sdk.Context, genesis PowGenesis) error { @@ -78,24 +79,24 @@ func (pk Keeper) CheckValid(ctx sdk.Context, difficulty uint64, count uint64) (u lastDifficulty, err := pk.GetLastDifficulty(ctx) if err != nil { - return 0, 0, ErrNonexistentDifficulty() + return 0, 0, ErrNonexistentDifficulty(pk.codespace) } newDifficulty := lastDifficulty + 1 lastCount, err := pk.GetLastCount(ctx) if err != nil { - return 0, 0, ErrNonexistentCount() + return 0, 0, ErrNonexistentCount(pk.codespace) } newCount := lastCount + 1 if count != newCount { - return 0, 0, ErrInvalidCount(fmt.Sprintf("invalid count: was %d, should have been %d", count, newCount)) + return 0, 0, ErrInvalidCount(pk.codespace, fmt.Sprintf("invalid count: was %d, should have been %d", count, newCount)) } if difficulty != newDifficulty { - return 0, 0, ErrInvalidDifficulty(fmt.Sprintf("invalid difficulty: was %d, should have been %d", difficulty, newDifficulty)) + return 0, 0, ErrInvalidDifficulty(pk.codespace, fmt.Sprintf("invalid difficulty: was %d, should have been %d", difficulty, newDifficulty)) } return newDifficulty, newCount, nil diff --git a/examples/democoin/x/pow/keeper_test.go b/examples/democoin/x/pow/keeper_test.go index cb3492a86..d0b60fa17 100644 --- a/examples/democoin/x/pow/keeper_test.go +++ b/examples/democoin/x/pow/keeper_test.go @@ -35,7 +35,7 @@ func TestPowKeeperGetSet(t *testing.T) { ctx := sdk.NewContext(ms, abci.Header{}, false, nil) config := NewPowConfig("pow", int64(1)) ck := bank.NewCoinKeeper(am) - keeper := NewKeeper(capKey, config, ck) + keeper := NewKeeper(capKey, config, ck, DefaultCodespace) err := keeper.InitGenesis(ctx, PowGenesis{uint64(1), uint64(0)}) assert.Nil(t, err) diff --git a/examples/democoin/x/pow/types.go b/examples/democoin/x/pow/types.go index ea368c306..69d56e4f1 100644 --- a/examples/democoin/x/pow/types.go +++ b/examples/democoin/x/pow/types.go @@ -52,7 +52,7 @@ func (msg MineMsg) ValidateBasic() sdk.Error { hex.Encode(hashHex, hash) hashHex = hashHex[:16] if !bytes.Equal(hashHex, msg.Proof) { - return ErrInvalidProof(fmt.Sprintf("hashHex: %s, proof: %s", hashHex, msg.Proof)) + return ErrInvalidProof(DefaultCodespace, fmt.Sprintf("hashHex: %s, proof: %s", hashHex, msg.Proof)) } // check proof below difficulty @@ -60,10 +60,10 @@ func (msg MineMsg) ValidateBasic() sdk.Error { target := math.MaxUint64 / msg.Difficulty hashUint, err := strconv.ParseUint(string(msg.Proof), 16, 64) if err != nil { - return ErrInvalidProof(fmt.Sprintf("proof: %s", msg.Proof)) + return ErrInvalidProof(DefaultCodespace, fmt.Sprintf("proof: %s", msg.Proof)) } if hashUint >= target { - return ErrNotBelowTarget(fmt.Sprintf("hashuint: %d, target: %d", hashUint, target)) + return ErrNotBelowTarget(DefaultCodespace, fmt.Sprintf("hashuint: %d, target: %d", hashUint, target)) } return nil diff --git a/store/rootmultistore_test.go b/store/rootmultistore_test.go index 3796bd477..f4164f0b5 100644 --- a/store/rootmultistore_test.go +++ b/store/rootmultistore_test.go @@ -128,34 +128,34 @@ func TestMultiStoreQuery(t *testing.T) { // Test bad path. query := abci.RequestQuery{Path: "/key", Data: k, Height: ver} qres := multi.Query(query) - assert.Equal(t, uint32(sdk.CodeUnknownRequest), qres.Code) + assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnknownRequest), sdk.ABCICodeType(qres.Code)) query.Path = "h897fy32890rf63296r92" qres = multi.Query(query) - assert.Equal(t, uint32(sdk.CodeUnknownRequest), qres.Code) + assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnknownRequest), sdk.ABCICodeType(qres.Code)) // Test invalid store name. query.Path = "/garbage/key" qres = multi.Query(query) - assert.Equal(t, uint32(sdk.CodeUnknownRequest), qres.Code) + assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnknownRequest), sdk.ABCICodeType(qres.Code)) // Test valid query with data. query.Path = "/store1/key" qres = multi.Query(query) - assert.Equal(t, uint32(sdk.CodeOK), qres.Code) + assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeOK), sdk.ABCICodeType(qres.Code)) assert.Equal(t, v, qres.Value) // Test valid but empty query. query.Path = "/store2/key" query.Prove = true qres = multi.Query(query) - assert.Equal(t, uint32(sdk.CodeOK), qres.Code) + assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeOK), sdk.ABCICodeType(qres.Code)) assert.Nil(t, qres.Value) // Test store2 data. query.Data = k2 qres = multi.Query(query) - assert.Equal(t, uint32(sdk.CodeOK), qres.Code) + assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeOK), sdk.ABCICodeType(qres.Code)) assert.Equal(t, v2, qres.Value) } diff --git a/types/codespacer.go b/types/codespacer.go new file mode 100644 index 000000000..92025c1a6 --- /dev/null +++ b/types/codespacer.go @@ -0,0 +1,35 @@ +package types + +// Codespacer is a simple struct to track reserved codespaces +type Codespacer struct { + reserved map[CodespaceType]bool +} + +// NewCodespacer generates a new Codespacer with the starting codespace +func NewCodespacer() *Codespacer { + return &Codespacer{ + reserved: make(map[CodespaceType]bool), + } +} + +// RegisterNext reserves and returns the next available codespace, starting from a default, and panics if the maximum codespace is reached +func (c *Codespacer) RegisterNext(codespace CodespaceType) CodespaceType { + for { + if !c.reserved[codespace] { + c.reserved[codespace] = true + return codespace + } + codespace++ + if codespace == MaximumCodespace { + panic("Maximum codespace reached!") + } + } +} + +// RegisterOrPanic reserved a codespace or panics if it is unavailable +func (c *Codespacer) RegisterOrPanic(codespace CodespaceType) { + if c.reserved[codespace] { + panic("Cannot register codespace, already reserved") + } + c.reserved[codespace] = true +} diff --git a/types/codespacer_test.go b/types/codespacer_test.go new file mode 100644 index 000000000..7052aa92a --- /dev/null +++ b/types/codespacer_test.go @@ -0,0 +1,47 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestRegisterNext(t *testing.T) { + codespacer := NewCodespacer() + // unregistered, allow + code1 := codespacer.RegisterNext(CodespaceType(2)) + require.Equal(t, code1, CodespaceType(2)) + // registered, pick next + code2 := codespacer.RegisterNext(CodespaceType(2)) + require.Equal(t, code2, CodespaceType(3)) + // pick next + code3 := codespacer.RegisterNext(CodespaceType(2)) + require.Equal(t, code3, CodespaceType(4)) + // skip 1 + code4 := codespacer.RegisterNext(CodespaceType(6)) + require.Equal(t, code4, CodespaceType(6)) + code5 := codespacer.RegisterNext(CodespaceType(2)) + require.Equal(t, code5, CodespaceType(5)) + code6 := codespacer.RegisterNext(CodespaceType(2)) + require.Equal(t, code6, CodespaceType(7)) + // panic on maximum + defer func() { + r := recover() + require.NotNil(t, r, "Did not panic on maximum codespace") + }() + codespacer.RegisterNext(MaximumCodespace - 1) + codespacer.RegisterNext(MaximumCodespace - 1) +} + +func TestRegisterOrPanic(t *testing.T) { + codespacer := NewCodespacer() + // unregistered, allow + code1 := codespacer.RegisterNext(CodespaceType(2)) + require.Equal(t, code1, CodespaceType(2)) + // panic on duplicate + defer func() { + r := recover() + require.NotNil(t, r, "Did not panic on duplicate codespace") + }() + codespacer.RegisterOrPanic(CodespaceType(2)) +} diff --git a/types/errors.go b/types/errors.go index 4874c4362..c2fe726a2 100644 --- a/types/errors.go +++ b/types/errors.go @@ -2,25 +2,42 @@ package types import ( "fmt" - "runtime" + + cmn "github.com/tendermint/tmlibs/common" abci "github.com/tendermint/abci/types" ) -// ABCI Response Code -type CodeType uint32 +// ABCICodeType - combined codetype / codespace +type ABCICodeType uint32 -// is everything okay? -func (code CodeType) IsOK() bool { - if code == CodeOK { +// CodeType - code identifier within codespace +type CodeType uint16 + +// CodespaceType - codespace identifier +type CodespaceType uint16 + +// IsOK - is everything okay? +func (code ABCICodeType) IsOK() bool { + if code == ABCICodeOK { return true } return false } -// ABCI Response Codes -// Base SDK reserves 0 - 99. +func ToABCICode(space CodespaceType, code CodeType) ABCICodeType { + // TODO: Make Tendermint more aware of codespaces. + if space == CodespaceRoot && code == CodeOK { + return ABCICodeOK + } + return ABCICodeType((uint32(space) << 16) | uint32(code)) +} + const ( + // ABCI error codes + ABCICodeOK ABCICodeType = 0 + + // Base error codes CodeOK CodeType = 0 CodeInternal CodeType = 1 CodeTxDecode CodeType = 2 @@ -34,7 +51,14 @@ const ( CodeInsufficientCoins CodeType = 10 CodeInvalidCoins CodeType = 11 - CodeGenesisParse CodeType = 0xdead // TODO: remove ? // why remove? + // CodespaceRoot is a codespace for error codes in this file only. + // Notice that 0 is an "unset" codespace, which can be overridden with + // Error.WithDefaultCodespace(). + CodespaceUndefined CodespaceType = 0 + CodespaceRoot CodespaceType = 1 + + // Maximum reservable codespace (2^16 - 1) + MaximumCodespace CodespaceType = 65535 ) // NOTE: Don't stringer this, we'll put better messages in later. @@ -44,8 +68,6 @@ func CodeToDefaultMsg(code CodeType) string { return "Internal error" case CodeTxDecode: return "Tx parse error" - case CodeGenesisParse: - return "Genesis parse error" case CodeInvalidSequence: return "Invalid sequence" case CodeUnauthorized: @@ -75,40 +97,37 @@ func CodeToDefaultMsg(code CodeType) string { // nolint func ErrInternal(msg string) Error { - return newError(CodeInternal, msg) + return newErrorWithRootCodespace(CodeInternal, msg) } func ErrTxDecode(msg string) Error { - return newError(CodeTxDecode, msg) -} -func ErrGenesisParse(msg string) Error { - return newError(CodeGenesisParse, msg) + return newErrorWithRootCodespace(CodeTxDecode, msg) } func ErrInvalidSequence(msg string) Error { - return newError(CodeInvalidSequence, msg) + return newErrorWithRootCodespace(CodeInvalidSequence, msg) } func ErrUnauthorized(msg string) Error { - return newError(CodeUnauthorized, msg) + return newErrorWithRootCodespace(CodeUnauthorized, msg) } func ErrInsufficientFunds(msg string) Error { - return newError(CodeInsufficientFunds, msg) + return newErrorWithRootCodespace(CodeInsufficientFunds, msg) } func ErrUnknownRequest(msg string) Error { - return newError(CodeUnknownRequest, msg) + return newErrorWithRootCodespace(CodeUnknownRequest, msg) } func ErrInvalidAddress(msg string) Error { - return newError(CodeInvalidAddress, msg) + return newErrorWithRootCodespace(CodeInvalidAddress, msg) } func ErrUnknownAddress(msg string) Error { - return newError(CodeUnknownAddress, msg) + return newErrorWithRootCodespace(CodeUnknownAddress, msg) } func ErrInvalidPubKey(msg string) Error { - return newError(CodeInvalidPubKey, msg) + return newErrorWithRootCodespace(CodeInvalidPubKey, msg) } func ErrInsufficientCoins(msg string) Error { - return newError(CodeInsufficientCoins, msg) + return newErrorWithRootCodespace(CodeInsufficientCoins, msg) } func ErrInvalidCoins(msg string) Error { - return newError(CodeInvalidCoins, msg) + return newErrorWithRootCodespace(CodeInvalidCoins, msg) } //---------------------------------------- @@ -117,104 +136,98 @@ func ErrInvalidCoins(msg string) Error { // sdk Error type type Error interface { Error() string - ABCICode() CodeType + Code() CodeType + Codespace() CodespaceType ABCILog() string + ABCICode() ABCICodeType + WithDefaultCodespace(codespace CodespaceType) Error Trace(msg string) Error - TraceCause(cause error, msg string) Error - Cause() error + T() interface{} Result() Result QueryResult() abci.ResponseQuery } -func NewError(code CodeType, msg string) Error { - return newError(code, msg) +// NewError - create an error +func NewError(codespace CodespaceType, code CodeType, msg string) Error { + return newError(codespace, code, msg) } -type traceItem struct { - msg string - filename string - lineno int +func newErrorWithRootCodespace(code CodeType, msg string) *sdkError { + return newError(CodespaceRoot, code, msg) } -func (ti traceItem) String() string { - return fmt.Sprintf("%v:%v %v", ti.filename, ti.lineno, ti.msg) -} - -type sdkError struct { - code CodeType - msg string - cause error - traces []traceItem -} - -func newError(code CodeType, msg string) *sdkError { - // TODO capture stacktrace if ENV is set. +func newError(codespace CodespaceType, code CodeType, msg string) *sdkError { if msg == "" { msg = CodeToDefaultMsg(code) } return &sdkError{ - code: code, - msg: msg, - cause: nil, - traces: nil, + codespace: codespace, + code: code, + err: cmn.NewErrorWithT(code, msg), } } +type sdkError struct { + codespace CodespaceType + code CodeType + err cmn.Error +} + // Implements ABCIError. func (err *sdkError) Error() string { - return fmt.Sprintf("Error{%d:%s,%v,%v}", err.code, err.msg, err.cause, len(err.traces)) + return fmt.Sprintf("Error{%d:%d,%#v}", err.codespace, err.code, err.err) } // Implements ABCIError. -func (err *sdkError) ABCICode() CodeType { +func (err *sdkError) ABCICode() ABCICodeType { + return ToABCICode(err.codespace, err.code) +} + +// Implements Error. +func (err *sdkError) Codespace() CodespaceType { + return err.codespace +} + +// Implements Error. +func (err *sdkError) Code() CodeType { return err.code } // Implements ABCIError. func (err *sdkError) ABCILog() string { - traceLog := "" - for _, ti := range err.traces { - traceLog += ti.String() + "\n" - } - return fmt.Sprintf("msg: %v\ntrace:\n%v", - err.msg, - traceLog, - ) + return fmt.Sprintf(`=== ABCI Log === +Codespace: %v +Code: %v +ABCICode: %v +Error: %#v +=== /ABCI Log === +`, err.codespace, err.code, err.ABCICode(), err.err) } // Add tracing information with msg. func (err *sdkError) Trace(msg string) Error { - return err.doTrace(msg, 2) -} - -// Add tracing information with cause and msg. -func (err *sdkError) TraceCause(cause error, msg string) Error { - err.cause = cause - return err.doTrace(msg, 2) -} - -func (err *sdkError) doTrace(msg string, n int) Error { - _, fn, line, ok := runtime.Caller(n) - if !ok { - if fn == "" { - fn = "" - } - if line <= 0 { - line = -1 - } + return &sdkError{ + codespace: err.codespace, + code: err.code, + err: err.err.Trace(msg), } - // Include file & line number & msg. - // Do not include the whole stack trace. - err.traces = append(err.traces, traceItem{ - filename: fn, - lineno: line, - msg: msg, - }) - return err } -func (err *sdkError) Cause() error { - return err.cause +// Implements Error. +func (err *sdkError) WithDefaultCodespace(cs CodespaceType) Error { + codespace := err.codespace + if codespace == CodespaceUndefined { + codespace = cs + } + return &sdkError{ + codespace: codespace, + code: err.code, + err: err.err, + } +} + +func (err *sdkError) T() interface{} { + return err.err.T() } func (err *sdkError) Result() Result { diff --git a/types/errors_test.go b/types/errors_test.go index 939cced7c..798eafefc 100644 --- a/types/errors_test.go +++ b/types/errors_test.go @@ -16,7 +16,6 @@ var codeTypes = []CodeType{ CodeUnknownRequest, CodeUnknownAddress, CodeInvalidPubKey, - CodeGenesisParse, } type errFn func(msg string) Error @@ -30,14 +29,12 @@ var errFns = []errFn{ ErrUnknownRequest, ErrUnknownAddress, ErrInvalidPubKey, - ErrGenesisParse, } func TestCodeType(t *testing.T) { - assert.True(t, CodeOK.IsOK()) + assert.True(t, ABCICodeOK.IsOK()) for _, c := range codeTypes { - assert.False(t, c.IsOK()) msg := CodeToDefaultMsg(c) assert.False(t, strings.HasPrefix(msg, "Unknown code")) } @@ -47,7 +44,7 @@ func TestErrFn(t *testing.T) { for i, errFn := range errFns { err := errFn("") codeType := codeTypes[i] - assert.Equal(t, err.ABCICode(), codeType) - assert.Equal(t, err.Result().Code, codeType) + assert.Equal(t, err.Code(), codeType) + assert.Equal(t, err.Result().Code, ToABCICode(CodespaceRoot, codeType)) } } diff --git a/types/rational.go b/types/rational.go index 8ebee7140..9199520b2 100644 --- a/types/rational.go +++ b/types/rational.go @@ -97,23 +97,23 @@ func NewRatFromDecimal(decimalStr string) (f Rat, err Error) { switch len(str) { case 1: if len(str[0]) == 0 { - return f, NewError(CodeUnknownRequest, "not a decimal string") + return f, ErrUnknownRequest("not a decimal string") } numStr = str[0] case 2: if len(str[0]) == 0 || len(str[1]) == 0 { - return f, NewError(CodeUnknownRequest, "not a decimal string") + return f, ErrUnknownRequest("not a decimal string") } numStr = str[0] + str[1] len := int64(len(str[1])) denom = new(big.Int).Exp(big.NewInt(10), big.NewInt(len), nil).Int64() default: - return f, NewError(CodeUnknownRequest, "not a decimal string") + return f, ErrUnknownRequest("not a decimal string") } num, errConv := strconv.Atoi(numStr) if errConv != nil { - return f, NewError(CodeUnknownRequest, errConv.Error()) + return f, ErrUnknownRequest(errConv.Error()) } if neg { diff --git a/types/result.go b/types/result.go index 412a9778d..7b0c1a593 100644 --- a/types/result.go +++ b/types/result.go @@ -9,7 +9,7 @@ import ( type Result struct { // Code is the response code, is stored back on the chain. - Code CodeType + Code ABCICodeType // Data is any data returned from the app. Data []byte diff --git a/x/auth/ante_test.go b/x/auth/ante_test.go index 58633ff9a..3baf8ee71 100644 --- a/x/auth/ante_test.go +++ b/x/auth/ante_test.go @@ -40,7 +40,7 @@ func privAndAddr() (crypto.PrivKey, sdk.Address) { func checkValidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx sdk.Tx) { _, result, abort := anteHandler(ctx, tx) assert.False(t, abort) - assert.Equal(t, sdk.CodeOK, result.Code) + assert.Equal(t, sdk.ABCICodeOK, result.Code) assert.True(t, result.IsOK()) } @@ -48,7 +48,7 @@ func checkValidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx func checkInvalidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx sdk.Tx, code sdk.CodeType) { _, result, abort := anteHandler(ctx, tx) assert.True(t, abort) - assert.Equal(t, code, result.Code) + assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, code), result.Code) } func newTestTx(ctx sdk.Context, msg sdk.Msg, privs []crypto.PrivKey, seqs []int64, fee sdk.StdFee) sdk.Tx { diff --git a/x/bank/errors.go b/x/bank/errors.go index 4223dd30b..d7c7e9748 100644 --- a/x/bank/errors.go +++ b/x/bank/errors.go @@ -7,6 +7,8 @@ import ( // Coin errors reserve 100 ~ 199. const ( + DefaultCodespace sdk.CodespaceType = 2 + CodeInvalidInput sdk.CodeType = 101 CodeInvalidOutput sdk.CodeType = 102 ) @@ -26,20 +28,20 @@ func codeToDefaultMsg(code sdk.CodeType) string { //---------------------------------------- // Error constructors -func ErrInvalidInput(msg string) sdk.Error { - return newError(CodeInvalidInput, msg) +func ErrInvalidInput(codespace sdk.CodespaceType, msg string) sdk.Error { + return newError(codespace, CodeInvalidInput, msg) } -func ErrNoInputs() sdk.Error { - return newError(CodeInvalidInput, "") +func ErrNoInputs(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidInput, "") } -func ErrInvalidOutput(msg string) sdk.Error { - return newError(CodeInvalidOutput, msg) +func ErrInvalidOutput(codespace sdk.CodespaceType, msg string) sdk.Error { + return newError(codespace, CodeInvalidOutput, msg) } -func ErrNoOutputs() sdk.Error { - return newError(CodeInvalidOutput, "") +func ErrNoOutputs(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidOutput, "") } //---------------------------------------- @@ -51,7 +53,7 @@ func msgOrDefaultMsg(msg string, code sdk.CodeType) string { return codeToDefaultMsg(code) } -func newError(code sdk.CodeType, msg string) sdk.Error { +func newError(codespace sdk.CodespaceType, code sdk.CodeType, msg string) sdk.Error { msg = msgOrDefaultMsg(msg, code) - return sdk.NewError(code, msg) + return sdk.NewError(codespace, code, msg) } diff --git a/x/bank/msgs.go b/x/bank/msgs.go index 15822eed7..c0f2ad46a 100644 --- a/x/bank/msgs.go +++ b/x/bank/msgs.go @@ -28,10 +28,10 @@ func (msg SendMsg) ValidateBasic() sdk.Error { // this just makes sure all the inputs and outputs are properly formatted, // not that they actually have the money inside if len(msg.Inputs) == 0 { - return ErrNoInputs().Trace("") + return ErrNoInputs(DefaultCodespace).Trace("") } if len(msg.Outputs) == 0 { - return ErrNoOutputs().Trace("") + return ErrNoOutputs(DefaultCodespace).Trace("") } // make sure all inputs and outputs are individually valid var totalIn, totalOut sdk.Coins @@ -102,7 +102,7 @@ func (msg IssueMsg) Type() string { return "bank" } // TODO: "bank/issue" func (msg IssueMsg) ValidateBasic() sdk.Error { // XXX if len(msg.Outputs) == 0 { - return ErrNoOutputs().Trace("") + return ErrNoOutputs(DefaultCodespace).Trace("") } for _, out := range msg.Outputs { if err := out.ValidateBasic(); err != nil { diff --git a/x/ibc/errors.go b/x/ibc/errors.go index f3c988b59..3c52bed7b 100644 --- a/x/ibc/errors.go +++ b/x/ibc/errors.go @@ -5,6 +5,8 @@ import ( ) const ( + DefaultCodespace sdk.CodespaceType = 3 + // IBC errors reserve 200 - 299. CodeInvalidSequence sdk.CodeType = 200 CodeIdenticalChains sdk.CodeType = 201 @@ -22,20 +24,20 @@ func codeToDefaultMsg(code sdk.CodeType) string { } } -func ErrInvalidSequence() sdk.Error { - return newError(CodeInvalidSequence, "") +func ErrInvalidSequence(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidSequence, "") } -func ErrIdenticalChains() sdk.Error { - return newError(CodeIdenticalChains, "") +func ErrIdenticalChains(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeIdenticalChains, "") } // ------------------------- // Helpers -func newError(code sdk.CodeType, msg string) sdk.Error { +func newError(codespace sdk.CodespaceType, code sdk.CodeType, msg string) sdk.Error { msg = msgOrDefaultMsg(msg, code) - return sdk.NewError(code, msg) + return sdk.NewError(codespace, code, msg) } func msgOrDefaultMsg(msg string, code sdk.CodeType) string { diff --git a/x/ibc/handler.go b/x/ibc/handler.go index 2922f6dab..dcd00359f 100644 --- a/x/ibc/handler.go +++ b/x/ibc/handler.go @@ -44,7 +44,7 @@ func handleIBCReceiveMsg(ctx sdk.Context, ibcm IBCMapper, ck bank.CoinKeeper, ms seq := ibcm.GetIngressSequence(ctx, packet.SrcChain) if msg.Sequence != seq { - return ErrInvalidSequence().Result() + return ErrInvalidSequence(ibcm.codespace).Result() } _, err := ck.AddCoins(ctx, packet.DestAddr, packet.Coins) diff --git a/x/ibc/ibc_test.go b/x/ibc/ibc_test.go index db172a5ca..1fc724e54 100644 --- a/x/ibc/ibc_test.go +++ b/x/ibc/ibc_test.go @@ -73,7 +73,7 @@ func TestIBC(t *testing.T) { assert.Nil(t, err) assert.Equal(t, mycoins, coins) - ibcm := NewIBCMapper(cdc, key) + ibcm := NewIBCMapper(cdc, key, DefaultCodespace) h := NewHandler(ibcm, ck) packet := IBCPacket{ SrcAddr: src, diff --git a/x/ibc/mapper.go b/x/ibc/mapper.go index 1e8f9de25..d3ecc779d 100644 --- a/x/ibc/mapper.go +++ b/x/ibc/mapper.go @@ -8,17 +8,19 @@ import ( ) type IBCMapper struct { - key sdk.StoreKey - cdc *wire.Codec + key sdk.StoreKey + cdc *wire.Codec + codespace sdk.CodespaceType } // XXX: The IBCMapper should not take a CoinKeeper. Rather have the CoinKeeper // take an IBCMapper. -func NewIBCMapper(cdc *wire.Codec, key sdk.StoreKey) IBCMapper { +func NewIBCMapper(cdc *wire.Codec, key sdk.StoreKey, codespace sdk.CodespaceType) IBCMapper { // XXX: How are these codecs supposed to work? return IBCMapper{ - key: key, - cdc: cdc, + key: key, + cdc: cdc, + codespace: codespace, } } diff --git a/x/ibc/types.go b/x/ibc/types.go index 495d2a900..2bf2c4267 100644 --- a/x/ibc/types.go +++ b/x/ibc/types.go @@ -33,7 +33,7 @@ func NewIBCPacket(srcAddr sdk.Address, destAddr sdk.Address, coins sdk.Coins, func (ibcp IBCPacket) ValidateBasic() sdk.Error { if ibcp.SrcChain == ibcp.DestChain { - return ErrIdenticalChains().Trace("") + return ErrIdenticalChains(DefaultCodespace).Trace("") } if !ibcp.Coins.IsValid() { return sdk.ErrInvalidCoins("") diff --git a/x/simplestake/errors.go b/x/simplestake/errors.go index f69ffcbeb..0fb7eebce 100644 --- a/x/simplestake/errors.go +++ b/x/simplestake/errors.go @@ -5,6 +5,8 @@ import ( ) const ( + DefaultCodespace sdk.CodespaceType = 4 + // simplestake errors reserve 300 - 399. CodeEmptyValidator sdk.CodeType = 300 CodeInvalidUnbond sdk.CodeType = 301 @@ -12,25 +14,25 @@ const ( CodeIncorrectStakingToken sdk.CodeType = 303 ) -func ErrIncorrectStakingToken() sdk.Error { - return newError(CodeIncorrectStakingToken, "") +func ErrIncorrectStakingToken(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeIncorrectStakingToken, "") } -func ErrEmptyValidator() sdk.Error { - return newError(CodeEmptyValidator, "") +func ErrEmptyValidator(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeEmptyValidator, "") } -func ErrInvalidUnbond() sdk.Error { - return newError(CodeInvalidUnbond, "") +func ErrInvalidUnbond(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidUnbond, "") } -func ErrEmptyStake() sdk.Error { - return newError(CodeEmptyStake, "") +func ErrEmptyStake(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeEmptyStake, "") } // ----------------------------- // Helpers -func newError(code sdk.CodeType, msg string) sdk.Error { - return sdk.NewError(code, msg) +func newError(codespace sdk.CodespaceType, code sdk.CodeType, msg string) sdk.Error { + return sdk.NewError(codespace, code, msg) } diff --git a/x/simplestake/handler.go b/x/simplestake/handler.go index 31e5a7d24..894da04b2 100644 --- a/x/simplestake/handler.go +++ b/x/simplestake/handler.go @@ -32,7 +32,7 @@ func handleBondMsg(ctx sdk.Context, k Keeper, msg BondMsg) sdk.Result { } return sdk.Result{ - Code: sdk.CodeOK, + Code: sdk.ABCICodeOK, ValidatorUpdates: abci.Validators{valSet}, } } @@ -49,7 +49,7 @@ func handleUnbondMsg(ctx sdk.Context, k Keeper, msg UnbondMsg) sdk.Result { } return sdk.Result{ - Code: sdk.CodeOK, + Code: sdk.ABCICodeOK, ValidatorUpdates: abci.Validators{valSet}, } } diff --git a/x/simplestake/keeper.go b/x/simplestake/keeper.go index 7dcdbc20f..934d0b5a0 100644 --- a/x/simplestake/keeper.go +++ b/x/simplestake/keeper.go @@ -15,17 +15,19 @@ const moduleName = "simplestake" type Keeper struct { ck bank.CoinKeeper - key sdk.StoreKey - cdc *wire.Codec + key sdk.StoreKey + cdc *wire.Codec + codespace sdk.CodespaceType } -func NewKeeper(key sdk.StoreKey, coinKeeper bank.CoinKeeper) Keeper { +func NewKeeper(key sdk.StoreKey, coinKeeper bank.CoinKeeper, codespace sdk.CodespaceType) Keeper { cdc := wire.NewCodec() wire.RegisterCrypto(cdc) return Keeper{ - key: key, - cdc: cdc, - ck: coinKeeper, + key: key, + cdc: cdc, + ck: coinKeeper, + codespace: codespace, } } @@ -59,7 +61,7 @@ func (k Keeper) deleteBondInfo(ctx sdk.Context, addr sdk.Address) { func (k Keeper) Bond(ctx sdk.Context, addr sdk.Address, pubKey crypto.PubKey, stake sdk.Coin) (int64, sdk.Error) { if stake.Denom != stakingToken { - return 0, ErrIncorrectStakingToken() + return 0, ErrIncorrectStakingToken(k.codespace) } _, err := k.ck.SubtractCoins(ctx, addr, []sdk.Coin{stake}) @@ -84,7 +86,7 @@ func (k Keeper) Bond(ctx sdk.Context, addr sdk.Address, pubKey crypto.PubKey, st func (k Keeper) Unbond(ctx sdk.Context, addr sdk.Address) (crypto.PubKey, int64, sdk.Error) { bi := k.getBondInfo(ctx, addr) if bi.isEmpty() { - return nil, 0, ErrInvalidUnbond() + return nil, 0, ErrInvalidUnbond(k.codespace) } k.deleteBondInfo(ctx, addr) @@ -102,7 +104,7 @@ func (k Keeper) Unbond(ctx sdk.Context, addr sdk.Address) (crypto.PubKey, int64, func (k Keeper) bondWithoutCoins(ctx sdk.Context, addr sdk.Address, pubKey crypto.PubKey, stake sdk.Coin) (int64, sdk.Error) { if stake.Denom != stakingToken { - return 0, ErrIncorrectStakingToken() + return 0, ErrIncorrectStakingToken(k.codespace) } bi := k.getBondInfo(ctx, addr) @@ -122,7 +124,7 @@ func (k Keeper) bondWithoutCoins(ctx sdk.Context, addr sdk.Address, pubKey crypt func (k Keeper) unbondWithoutCoins(ctx sdk.Context, addr sdk.Address) (crypto.PubKey, int64, sdk.Error) { bi := k.getBondInfo(ctx, addr) if bi.isEmpty() { - return nil, 0, ErrInvalidUnbond() + return nil, 0, ErrInvalidUnbond(k.codespace) } k.deleteBondInfo(ctx, addr) diff --git a/x/simplestake/keeper_test.go b/x/simplestake/keeper_test.go index 7f9a120b9..833227968 100644 --- a/x/simplestake/keeper_test.go +++ b/x/simplestake/keeper_test.go @@ -33,7 +33,7 @@ func TestKeeperGetSet(t *testing.T) { ms, _, capKey := setupMultiStore() ctx := sdk.NewContext(ms, abci.Header{}, false, nil) - stakeKeeper := NewKeeper(capKey, bank.NewCoinKeeper(nil)) + stakeKeeper := NewKeeper(capKey, bank.NewCoinKeeper(nil), DefaultCodespace) addr := sdk.Address([]byte("some-address")) bi := stakeKeeper.getBondInfo(ctx, addr) @@ -63,13 +63,13 @@ func TestBonding(t *testing.T) { accountMapper := auth.NewAccountMapper(cdc, authKey, &auth.BaseAccount{}) coinKeeper := bank.NewCoinKeeper(accountMapper) - stakeKeeper := NewKeeper(capKey, coinKeeper) + stakeKeeper := NewKeeper(capKey, coinKeeper, DefaultCodespace) addr := sdk.Address([]byte("some-address")) privKey := crypto.GenPrivKeyEd25519() pubKey := privKey.PubKey() _, _, err := stakeKeeper.unbondWithoutCoins(ctx, addr) - assert.Equal(t, err, ErrInvalidUnbond()) + assert.Equal(t, err, ErrInvalidUnbond(DefaultCodespace)) _, err = stakeKeeper.bondWithoutCoins(ctx, addr, pubKey, sdk.Coin{"steak", 10}) assert.Nil(t, err) @@ -82,5 +82,5 @@ func TestBonding(t *testing.T) { assert.Equal(t, pubKey, pk) _, _, err = stakeKeeper.unbondWithoutCoins(ctx, addr) - assert.Equal(t, err, ErrInvalidUnbond()) + assert.Equal(t, err, ErrInvalidUnbond(DefaultCodespace)) } diff --git a/x/simplestake/msgs.go b/x/simplestake/msgs.go index 9f4133484..963bfae7b 100644 --- a/x/simplestake/msgs.go +++ b/x/simplestake/msgs.go @@ -31,7 +31,7 @@ func (msg BondMsg) Type() string { func (msg BondMsg) ValidateBasic() sdk.Error { if msg.Stake.IsZero() { - return ErrEmptyStake() + return ErrEmptyStake(DefaultCodespace) } if msg.PubKey == nil { diff --git a/x/stake/errors.go b/x/stake/errors.go index e5b3e0cb3..008d51bc9 100644 --- a/x/stake/errors.go +++ b/x/stake/errors.go @@ -10,6 +10,8 @@ import ( type CodeType = sdk.CodeType const ( + DefaultCodespace sdk.CodespaceType = 4 + // Gaia errors reserve 200 ~ 299. CodeInvalidValidator CodeType = 201 CodeInvalidCandidate CodeType = 202 @@ -45,62 +47,62 @@ func codeToDefaultMsg(code CodeType) string { //---------------------------------------- // Error constructors -func ErrNotEnoughBondShares(shares string) sdk.Error { - return newError(CodeInvalidBond, fmt.Sprintf("not enough shares only have %v", shares)) +func ErrNotEnoughBondShares(codespace sdk.CodespaceType, shares string) sdk.Error { + return newError(codespace, CodeInvalidBond, fmt.Sprintf("not enough shares only have %v", shares)) } -func ErrCandidateEmpty() sdk.Error { - return newError(CodeInvalidValidator, "Cannot bond to an empty candidate") +func ErrCandidateEmpty(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidValidator, "Cannot bond to an empty candidate") } -func ErrBadBondingDenom() sdk.Error { - return newError(CodeInvalidBond, "Invalid coin denomination") +func ErrBadBondingDenom(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidBond, "Invalid coin denomination") } -func ErrBadBondingAmount() sdk.Error { - return newError(CodeInvalidBond, "Amount must be > 0") +func ErrBadBondingAmount(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidBond, "Amount must be > 0") } -func ErrNoBondingAcct() sdk.Error { - return newError(CodeInvalidValidator, "No bond account for this (address, validator) pair") +func ErrNoBondingAcct(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidValidator, "No bond account for this (address, validator) pair") } -func ErrCommissionNegative() sdk.Error { - return newError(CodeInvalidValidator, "Commission must be positive") +func ErrCommissionNegative(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidValidator, "Commission must be positive") } -func ErrCommissionHuge() sdk.Error { - return newError(CodeInvalidValidator, "Commission cannot be more than 100%") +func ErrCommissionHuge(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidValidator, "Commission cannot be more than 100%") } -func ErrBadValidatorAddr() sdk.Error { - return newError(CodeInvalidValidator, "Validator does not exist for that address") +func ErrBadValidatorAddr(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidValidator, "Validator does not exist for that address") } -func ErrBadCandidateAddr() sdk.Error { - return newError(CodeInvalidValidator, "Candidate does not exist for that address") +func ErrBadCandidateAddr(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidValidator, "Candidate does not exist for that address") } -func ErrBadDelegatorAddr() sdk.Error { - return newError(CodeInvalidValidator, "Delegator does not exist for that address") +func ErrBadDelegatorAddr(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidValidator, "Delegator does not exist for that address") } -func ErrCandidateExistsAddr() sdk.Error { - return newError(CodeInvalidValidator, "Candidate already exist, cannot re-declare candidacy") +func ErrCandidateExistsAddr(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidValidator, "Candidate already exist, cannot re-declare candidacy") } -func ErrCandidateRevoked() sdk.Error { - return newError(CodeInvalidValidator, "Candidacy for this address is currently revoked") +func ErrCandidateRevoked(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidValidator, "Candidacy for this address is currently revoked") } -func ErrMissingSignature() sdk.Error { - return newError(CodeInvalidValidator, "Missing signature") +func ErrMissingSignature(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidValidator, "Missing signature") } -func ErrBondNotNominated() sdk.Error { - return newError(CodeInvalidValidator, "Cannot bond to non-nominated account") +func ErrBondNotNominated(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidValidator, "Cannot bond to non-nominated account") } -func ErrNoCandidateForAddress() sdk.Error { - return newError(CodeInvalidValidator, "Validator does not exist for that address") +func ErrNoCandidateForAddress(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidValidator, "Validator does not exist for that address") } -func ErrNoDelegatorForAddress() sdk.Error { - return newError(CodeInvalidValidator, "Delegator does not contain validator bond") +func ErrNoDelegatorForAddress(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidValidator, "Delegator does not contain validator bond") } -func ErrInsufficientFunds() sdk.Error { - return newError(CodeInvalidInput, "Insufficient bond shares") +func ErrInsufficientFunds(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidInput, "Insufficient bond shares") } -func ErrBadShares() sdk.Error { - return newError(CodeInvalidInput, "bad shares provided as input, must be MAX or decimal") +func ErrBadShares(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidInput, "bad shares provided as input, must be MAX or decimal") } -func ErrBadRemoveValidator() sdk.Error { - return newError(CodeInvalidValidator, "Error removing validator") +func ErrBadRemoveValidator(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeInvalidValidator, "Error removing validator") } //---------------------------------------- @@ -114,7 +116,7 @@ func msgOrDefaultMsg(msg string, code CodeType) string { return codeToDefaultMsg(code) } -func newError(code CodeType, msg string) sdk.Error { +func newError(codespace sdk.CodespaceType, code CodeType, msg string) sdk.Error { msg = msgOrDefaultMsg(msg, code) - return sdk.NewError(code, msg) + return sdk.NewError(codespace, code, msg) } diff --git a/x/stake/handler.go b/x/stake/handler.go index 2f351a608..5f80ecb37 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -57,10 +57,10 @@ func handleMsgDeclareCandidacy(ctx sdk.Context, msg MsgDeclareCandidacy, k Keepe // check to see if the pubkey or sender has been registered before _, found := k.GetCandidate(ctx, msg.CandidateAddr) if found { - return ErrCandidateExistsAddr().Result() + return ErrCandidateExistsAddr(k.codespace).Result() } if msg.Bond.Denom != k.GetParams(ctx).BondDenom { - return ErrBadBondingDenom().Result() + return ErrBadBondingDenom(k.codespace).Result() } if ctx.IsCheckTx() { return sdk.Result{ @@ -85,7 +85,7 @@ func handleMsgEditCandidacy(ctx sdk.Context, msg MsgEditCandidacy, k Keeper) sdk // candidate must already be registered candidate, found := k.GetCandidate(ctx, msg.CandidateAddr) if !found { - return ErrBadCandidateAddr().Result() + return ErrBadCandidateAddr(k.codespace).Result() } if ctx.IsCheckTx() { return sdk.Result{ @@ -93,7 +93,7 @@ func handleMsgEditCandidacy(ctx sdk.Context, msg MsgEditCandidacy, k Keeper) sdk } } if candidate.Status == Unbonded { //candidate has been withdrawn - return ErrBondNotNominated().Result() + return ErrBondNotNominated(k.codespace).Result() } // XXX move to types @@ -111,13 +111,13 @@ func handleMsgDelegate(ctx sdk.Context, msg MsgDelegate, k Keeper) sdk.Result { candidate, found := k.GetCandidate(ctx, msg.CandidateAddr) if !found { - return ErrBadCandidateAddr().Result() + return ErrBadCandidateAddr(k.codespace).Result() } if msg.Bond.Denom != k.GetParams(ctx).BondDenom { - return ErrBadBondingDenom().Result() + return ErrBadBondingDenom(k.codespace).Result() } if candidate.Status == Revoked { - return ErrCandidateRevoked().Result() + return ErrCandidateRevoked(k.codespace).Result() } if ctx.IsCheckTx() { return sdk.Result{ @@ -165,10 +165,10 @@ func handleMsgUnbond(ctx sdk.Context, msg MsgUnbond, k Keeper) sdk.Result { // check if bond has any shares in it unbond bond, found := k.getDelegatorBond(ctx, msg.DelegatorAddr, msg.CandidateAddr) if !found { - return ErrNoDelegatorForAddress().Result() + return ErrNoDelegatorForAddress(k.codespace).Result() } if !bond.Shares.GT(sdk.ZeroRat) { // bond shares < msg shares - return ErrInsufficientFunds().Result() + return ErrInsufficientFunds(k.codespace).Result() } // test getting rational number from decimal provided @@ -180,18 +180,18 @@ func handleMsgUnbond(ctx sdk.Context, msg MsgUnbond, k Keeper) sdk.Result { // test that there are enough shares to unbond if msg.Shares == "MAX" { if !bond.Shares.GT(sdk.ZeroRat) { - return ErrNotEnoughBondShares(msg.Shares).Result() + return ErrNotEnoughBondShares(k.codespace, msg.Shares).Result() } } else { if bond.Shares.LT(shares) { - return ErrNotEnoughBondShares(msg.Shares).Result() + return ErrNotEnoughBondShares(k.codespace, msg.Shares).Result() } } // get candidate candidate, found := k.GetCandidate(ctx, msg.CandidateAddr) if !found { - return ErrNoCandidateForAddress().Result() + return ErrNoCandidateForAddress(k.codespace).Result() } if ctx.IsCheckTx() { diff --git a/x/stake/keeper.go b/x/stake/keeper.go index 0f29b177b..ae3dfb7c7 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -19,13 +19,17 @@ type Keeper struct { // caches gs Pool params Params + + // codespace + codespace sdk.CodespaceType } -func NewKeeper(ctx sdk.Context, cdc *wire.Codec, key sdk.StoreKey, ck bank.CoinKeeper) Keeper { +func NewKeeper(ctx sdk.Context, cdc *wire.Codec, key sdk.StoreKey, ck bank.CoinKeeper, codespace sdk.CodespaceType) Keeper { keeper := Keeper{ storeKey: key, cdc: cdc, coinKeeper: ck, + codespace: codespace, } return keeper } diff --git a/x/stake/msg.go b/x/stake/msg.go index 28a2edf79..b5ba09b5a 100644 --- a/x/stake/msg.go +++ b/x/stake/msg.go @@ -60,18 +60,18 @@ func (msg MsgDeclareCandidacy) GetSignBytes() []byte { // quick validity check func (msg MsgDeclareCandidacy) ValidateBasic() sdk.Error { if msg.CandidateAddr == nil { - return ErrCandidateEmpty() + return ErrCandidateEmpty(DefaultCodespace) } if msg.Bond.Denom != StakingToken { - return ErrBadBondingDenom() + return ErrBadBondingDenom(DefaultCodespace) } if msg.Bond.Amount <= 0 { - return ErrBadBondingAmount() + return ErrBadBondingAmount(DefaultCodespace) // return sdk.ErrInvalidCoins(sdk.Coins{msg.Bond}.String()) } empty := Description{} if msg.Description == empty { - return newError(CodeInvalidInput, "description must be included") + return newError(DefaultCodespace, CodeInvalidInput, "description must be included") } return nil } @@ -111,11 +111,11 @@ func (msg MsgEditCandidacy) GetSignBytes() []byte { // quick validity check func (msg MsgEditCandidacy) ValidateBasic() sdk.Error { if msg.CandidateAddr == nil { - return ErrCandidateEmpty() + return ErrCandidateEmpty(DefaultCodespace) } empty := Description{} if msg.Description == empty { - return newError(CodeInvalidInput, "Transaction must include some information to modify") + return newError(DefaultCodespace, CodeInvalidInput, "Transaction must include some information to modify") } return nil } @@ -157,16 +157,16 @@ func (msg MsgDelegate) GetSignBytes() []byte { // quick validity check func (msg MsgDelegate) ValidateBasic() sdk.Error { if msg.DelegatorAddr == nil { - return ErrBadDelegatorAddr() + return ErrBadDelegatorAddr(DefaultCodespace) } if msg.CandidateAddr == nil { - return ErrBadCandidateAddr() + return ErrBadCandidateAddr(DefaultCodespace) } if msg.Bond.Denom != StakingToken { - return ErrBadBondingDenom() + return ErrBadBondingDenom(DefaultCodespace) } if msg.Bond.Amount <= 0 { - return ErrBadBondingAmount() + return ErrBadBondingAmount(DefaultCodespace) // return sdk.ErrInvalidCoins(sdk.Coins{msg.Bond}.String()) } return nil @@ -209,18 +209,18 @@ func (msg MsgUnbond) GetSignBytes() []byte { // quick validity check func (msg MsgUnbond) ValidateBasic() sdk.Error { if msg.DelegatorAddr == nil { - return ErrBadDelegatorAddr() + return ErrBadDelegatorAddr(DefaultCodespace) } if msg.CandidateAddr == nil { - return ErrBadCandidateAddr() + return ErrBadCandidateAddr(DefaultCodespace) } if msg.Shares != "MAX" { rat, err := sdk.NewRatFromDecimal(msg.Shares) if err != nil { - return ErrBadShares() + return ErrBadShares(DefaultCodespace) } if rat.IsZero() || rat.LT(sdk.ZeroRat) { - return ErrBadShares() + return ErrBadShares(DefaultCodespace) } } return nil diff --git a/x/stake/test_common.go b/x/stake/test_common.go index 395a5bce0..6470abbc7 100644 --- a/x/stake/test_common.go +++ b/x/stake/test_common.go @@ -132,7 +132,7 @@ func createTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context &auth.BaseAccount{}, // prototype ).Seal() ck := bank.NewCoinKeeper(accountMapper) - keeper := NewKeeper(ctx, cdc, keyStake, ck) + keeper := NewKeeper(ctx, cdc, keyStake, ck, DefaultCodespace) keeper.setPool(ctx, initialPool()) keeper.setParams(ctx, defaultParams()) From f7437fd899edc54a4ec5e6d1a1467e69c21c493e Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 6 Apr 2018 14:35:54 -0400 Subject: [PATCH 02/71] connected stake cli --- examples/basecoin/app/app.go | 7 ++++--- examples/basecoin/app/app_test.go | 5 +++-- examples/basecoin/cmd/basecli/main.go | 21 +++++++++------------ x/stake/commands/query.go | 8 ++++---- x/stake/commands/tx.go | 4 ++-- x/stake/handler.go | 3 +-- x/stake/wire.go | 2 +- 7 files changed, 24 insertions(+), 26 deletions(-) diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index bb3ef05ac..9ef48bfb5 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -15,6 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/ibc" "github.com/cosmos/cosmos-sdk/x/simplestake" + "github.com/cosmos/cosmos-sdk/x/stake" "github.com/cosmos/cosmos-sdk/examples/basecoin/types" ) @@ -32,7 +33,7 @@ type BasecoinApp struct { capKeyMainStore *sdk.KVStoreKey capKeyAccountStore *sdk.KVStoreKey capKeyIBCStore *sdk.KVStoreKey - capKeyStakingStore *sdk.KVStoreKey + capKeyStakeStore *sdk.KVStoreKey // Manage getting and setting accounts accountMapper sdk.AccountMapper @@ -53,7 +54,7 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp { capKeyMainStore: sdk.NewKVStoreKey("main"), capKeyAccountStore: sdk.NewKVStoreKey("acc"), capKeyIBCStore: sdk.NewKVStoreKey("ibc"), - capKeyStakingStore: sdk.NewKVStoreKey("stake"), + capKeyStakeStore: sdk.NewKVStoreKey("stake"), } // Define the accountMapper. @@ -70,7 +71,7 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp { app.Router(). AddRoute("bank", bank.NewHandler(coinKeeper)). AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)). - AddRoute("simplestake", simplestake.NewHandler(stakeKeeper)) + AddRoute("stake", stake.NewHandler(stakeKeeper)) // Define the feeHandler. app.feeHandler = auth.BurnFeeHandler diff --git a/examples/basecoin/app/app_test.go b/examples/basecoin/app/app_test.go index bc1735dde..1f635f53f 100644 --- a/examples/basecoin/app/app_test.go +++ b/examples/basecoin/app/app_test.go @@ -143,7 +143,7 @@ func TestSortGenesis(t *testing.T) { // Note the order: the coins are unsorted! coinDenom1, coinDenom2 := "foocoin", "barcoin" - genState := fmt.Sprintf(`{ + str := `{ "accounts": [{ "address": "%s", "coins": [ @@ -157,7 +157,8 @@ func TestSortGenesis(t *testing.T) { } ] }] - }`, addr1.String(), coinDenom1, coinDenom2) + }` + genState := fmt.Sprintf(str, addr1.String(), coinDenom1, coinDenom2) // Initialize the chain vals := []abci.Validator{} diff --git a/examples/basecoin/cmd/basecli/main.go b/examples/basecoin/cmd/basecli/main.go index 6271adcec..bab24f91b 100644 --- a/examples/basecoin/cmd/basecli/main.go +++ b/examples/basecoin/cmd/basecli/main.go @@ -17,7 +17,7 @@ import ( authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands" bankcmd "github.com/cosmos/cosmos-sdk/x/bank/commands" ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/commands" - simplestakingcmd "github.com/cosmos/cosmos-sdk/x/simplestake/commands" + stakecmd "github.com/cosmos/cosmos-sdk/x/stake/commands" "github.com/cosmos/cosmos-sdk/examples/basecoin/app" "github.com/cosmos/cosmos-sdk/examples/basecoin/types" @@ -52,23 +52,20 @@ func main() { rootCmd.AddCommand( client.GetCommands( authcmd.GetAccountCmd("main", cdc, types.GetAccountDecoder(cdc)), + stakecmd.GetCmdQueryCandidates("stake", cdc), + stakecmd.GetCmdQueryCandidate("stake", cdc), + stakecmd.GetCmdQueryDelegatorBond("stake", cdc), + stakecmd.GetCmdQueryDelegatorBonds("stake", cdc), )...) rootCmd.AddCommand( client.PostCommands( bankcmd.SendTxCmd(cdc), - )...) - rootCmd.AddCommand( - client.PostCommands( ibccmd.IBCTransferCmd(cdc), - )...) - rootCmd.AddCommand( - client.PostCommands( ibccmd.IBCRelayCmd(cdc), - simplestakingcmd.BondTxCmd(cdc), - )...) - rootCmd.AddCommand( - client.PostCommands( - simplestakingcmd.UnbondTxCmd(cdc), + stakecmd.GetCmdDeclareCandidacy(cdc), + stakecmd.GetCmdEditCandidacy(cdc), + stakecmd.GetCmdDelegate(cdc), + stakecmd.GetCmdUnbond(cdc), )...) // add proxy, version and key info diff --git a/x/stake/commands/query.go b/x/stake/commands/query.go index 8cbb877ce..38e16f333 100644 --- a/x/stake/commands/query.go +++ b/x/stake/commands/query.go @@ -38,7 +38,7 @@ func init() { } // create command to query for all candidates -func GetCmdQueryCandidates(cdc *wire.Codec, storeName string) *cobra.Command { +func GetCmdQueryCandidates(storeName string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "candidates", Short: "Query for the set of validator-candidates pubkeys", @@ -74,7 +74,7 @@ func GetCmdQueryCandidates(cdc *wire.Codec, storeName string) *cobra.Command { } // get the command to query a candidate -func GetCmdQueryCandidate(cdc *wire.Codec, storeName string) *cobra.Command { +func GetCmdQueryCandidate(storeName string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "candidate", Short: "Query a validator-candidate account", @@ -116,7 +116,7 @@ func GetCmdQueryCandidate(cdc *wire.Codec, storeName string) *cobra.Command { } // get the command to query a single delegator bond -func GetCmdQueryDelegatorBond(cdc *wire.Codec, storeName string) *cobra.Command { +func GetCmdQueryDelegatorBond(storeName string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "delegator-bond", Short: "Query a delegators bond based on address and candidate pubkey", @@ -165,7 +165,7 @@ func GetCmdQueryDelegatorBond(cdc *wire.Codec, storeName string) *cobra.Command } // get the command to query all the candidates bonded to a delegator -func GetCmdQueryDelegatorBonds(cdc *wire.Codec, storeName string) *cobra.Command { +func GetCmdQueryDelegatorBonds(storeName string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "delegator-candidates", Short: "Query all delegators candidates' pubkeys based on address", diff --git a/x/stake/commands/tx.go b/x/stake/commands/tx.go index 5cc9747b6..679e59b15 100644 --- a/x/stake/commands/tx.go +++ b/x/stake/commands/tx.go @@ -20,8 +20,8 @@ import ( // nolint const ( - FlagAddressDelegator = "addressD" - FlagAddressCandidate = "addressC" + FlagAddressDelegator = "address-delegator" + FlagAddressCandidate = "address-candidate" FlagPubKey = "pubkey" FlagAmount = "amount" FlagShares = "shares" diff --git a/x/stake/handler.go b/x/stake/handler.go index 5f80ecb37..e1f624f10 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -4,7 +4,6 @@ import ( "bytes" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/bank" abci "github.com/tendermint/abci/types" ) @@ -18,7 +17,7 @@ const ( //_______________________________________________________________________ -func NewHandler(k Keeper, ck bank.CoinKeeper) sdk.Handler { +func NewHandler(k Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { // NOTE msg already has validate basic run switch msg := msg.(type) { diff --git a/x/stake/wire.go b/x/stake/wire.go index 4516f89f2..f444ce14e 100644 --- a/x/stake/wire.go +++ b/x/stake/wire.go @@ -4,7 +4,7 @@ import ( "github.com/cosmos/cosmos-sdk/wire" ) -// XXX complete +// TODO complete when go-amino is ported func RegisterWire(cdc *wire.Codec) { // TODO include option to always include prefix bytes. //cdc.RegisterConcrete(SendMsg{}, "cosmos-sdk/SendMsg", nil) From 179caa5768b1e35c25015f5b529c3729a104578a Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 7 Apr 2018 01:12:00 -0400 Subject: [PATCH 03/71] refactor gaia with stake --- Makefile | 4 +- cmd/gaia/app/account.go | 32 ++ cmd/gaia/app/app.go | 158 ++++++++++ cmd/gaia/app/app_test.go | 432 ++++++++++++++++++++++++++ cmd/gaia/cmd/gaiacli/main.go | 79 +++++ cmd/{ => gaia/cmd}/gaiad/main.go | 25 +- examples/basecoin/app/app.go | 7 +- examples/basecoin/app/app_test.go | 8 +- examples/basecoin/cmd/basecli/main.go | 21 +- x/stake/handler.go | 37 --- 10 files changed, 744 insertions(+), 59 deletions(-) create mode 100644 cmd/gaia/app/account.go create mode 100644 cmd/gaia/app/app.go create mode 100644 cmd/gaia/app/app_test.go create mode 100644 cmd/gaia/cmd/gaiacli/main.go rename cmd/{ => gaia/cmd}/gaiad/main.go (60%) diff --git a/Makefile b/Makefile index b5177621a..4d21c61c5 100644 --- a/Makefile +++ b/Makefile @@ -36,8 +36,8 @@ else endif install: - go install $(BUILD_FLAGS) ./cmd/gaiad - go install $(BUILD_FLAGS) ./cmd/gaiacli + go install $(BUILD_FLAGS) ./cmd/gaia/cmd/gaiad + go install $(BUILD_FLAGS) ./cmd/gaia/cmd/gaiacli install_examples: go install $(BUILD_FLAGS) ./examples/basecoin/cmd/basecoind diff --git a/cmd/gaia/app/account.go b/cmd/gaia/app/account.go new file mode 100644 index 000000000..3d5673b87 --- /dev/null +++ b/cmd/gaia/app/account.go @@ -0,0 +1,32 @@ +package app + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" +) + +// State to Unmarshal +type GenesisState struct { + Accounts []GenesisAccount `json:"accounts"` +} + +// GenesisAccount doesn't need pubkey or sequence +type GenesisAccount struct { + Address sdk.Address `json:"address"` + Coins sdk.Coins `json:"coins"` +} + +func NewGenesisAccount(acc auth.BaseAccount) GenesisAccount { + return GenesisAccount{ + Address: acc.Address, + Coins: acc.Coins, + } +} + +// convert GenesisAccount to GaiaAccount +func (ga *GenesisAccount) ToAccount() (acc auth.BaseAccount) { + return auth.BaseAccount{ + Address: ga.Address, + Coins: ga.Coins.Sort(), + } +} diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go new file mode 100644 index 000000000..64b1619f8 --- /dev/null +++ b/cmd/gaia/app/app.go @@ -0,0 +1,158 @@ +package app + +import ( + "encoding/json" + + abci "github.com/tendermint/abci/types" + oldwire "github.com/tendermint/go-wire" + cmn "github.com/tendermint/tmlibs/common" + dbm "github.com/tendermint/tmlibs/db" + "github.com/tendermint/tmlibs/log" + + bam "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/wire" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/ibc" + "github.com/cosmos/cosmos-sdk/x/stake" +) + +const ( + appName = "GaiaApp" +) + +// Extended ABCI application +type GaiaApp struct { + *bam.BaseApp + cdc *wire.Codec + + // keys to access the substores + capKeyMainStore *sdk.KVStoreKey + capKeyAccountStore *sdk.KVStoreKey + capKeyIBCStore *sdk.KVStoreKey + capKeyStakeStore *sdk.KVStoreKey + + // Manage getting and setting accounts + accountMapper sdk.AccountMapper +} + +func NewGaiaApp(logger log.Logger, dbs map[string]dbm.DB) *GaiaApp { + // create your application object + var app = &GaiaApp{ + BaseApp: bam.NewBaseApp(appName, logger, dbs["main"]), + cdc: MakeCodec(), + capKeyMainStore: sdk.NewKVStoreKey("main"), + capKeyAccountStore: sdk.NewKVStoreKey("acc"), + capKeyIBCStore: sdk.NewKVStoreKey("ibc"), + capKeyStakeStore: sdk.NewKVStoreKey("stake"), + } + + // define the accountMapper + app.accountMapper = auth.NewAccountMapperSealed( + app.capKeyMainStore, // target store + &auth.BaseAccount{}, // prototype + ) + + // add handlers + coinKeeper := bank.NewCoinKeeper(app.accountMapper) + ibcMapper := ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore) + stakeKeeper := stake.NewKeeper(app.cdc, app.capKeyStakeStore, coinKeeper) + app.Router(). + AddRoute("bank", bank.NewHandler(coinKeeper)). + AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)). + AddRoute("stake", stake.NewHandler(stakeKeeper)) + + // initialize BaseApp + app.SetTxDecoder(app.txDecoder) + app.SetInitChainer(app.initChainer) + app.SetEndBlocker(stake.NewEndBlocker(stakeKeeper)) + app.MountStoreWithDB(app.capKeyMainStore, sdk.StoreTypeIAVL, dbs["main"]) + app.MountStoreWithDB(app.capKeyAccountStore, sdk.StoreTypeIAVL, dbs["acc"]) + app.MountStoreWithDB(app.capKeyIBCStore, sdk.StoreTypeIAVL, dbs["ibc"]) + app.MountStoreWithDB(app.capKeyStakeStore, sdk.StoreTypeIAVL, dbs["stake"]) + + // NOTE: Broken until #532 lands + //app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore, app.capKeyStakingStore) + app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper)) + err := app.LoadLatestVersion(app.capKeyMainStore) + if err != nil { + cmn.Exit(err.Error()) + } + + return app +} + +// custom tx codec +// TODO: use new go-wire +func MakeCodec() *wire.Codec { + const ( + msgTypeSend = 0x1 + msgTypeIssue = 0x2 + msgTypeIBCTransferMsg = 0x3 + msgTypeIBCReceiveMsg = 0x4 + msgDeclareCandidacy = 0x5 + msgEditCandidacy = 0x6 + msgDelegate = 0x7 + msgUnbond = 0x8 + ) + var _ = oldwire.RegisterInterface( + struct{ sdk.Msg }{}, + oldwire.ConcreteType{bank.SendMsg{}, msgTypeSend}, + oldwire.ConcreteType{bank.IssueMsg{}, msgTypeIssue}, + oldwire.ConcreteType{ibc.IBCTransferMsg{}, msgTypeIBCTransferMsg}, + oldwire.ConcreteType{ibc.IBCReceiveMsg{}, msgTypeIBCReceiveMsg}, + oldwire.ConcreteType{stake.MsgDeclareCandidacy{}, msgDeclareCandidacy}, + oldwire.ConcreteType{stake.MsgEditCandidacy{}, msgEditCandidacy}, + oldwire.ConcreteType{stake.MsgDelegate{}, msgDelegate}, + oldwire.ConcreteType{stake.MsgUnbond{}, msgUnbond}, + ) + + const accTypeApp = 0x1 + var _ = oldwire.RegisterInterface( + struct{ sdk.Account }{}, + oldwire.ConcreteType{&auth.BaseAccount{}, accTypeApp}, + ) + cdc := wire.NewCodec() + + // cdc.RegisterInterface((*sdk.Msg)(nil), nil) + // bank.RegisterWire(cdc) // Register bank.[SendMsg,IssueMsg] + // crypto.RegisterWire(cdc) // Register crypto.[PubKey,PrivKey,Signature] + // ibc.RegisterWire(cdc) // Register ibc.[IBCTransferMsg, IBCReceiveMsg] + return cdc +} + +// custom logic for transaction decoding +func (app *GaiaApp) txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) { + var tx = sdk.StdTx{} + + if len(txBytes) == 0 { + return nil, sdk.ErrTxDecode("txBytes are empty") + } + + // StdTx.Msg is an interface. The concrete types + // are registered by MakeTxCodec in bank.RegisterWire. + err := app.cdc.UnmarshalBinary(txBytes, &tx) + if err != nil { + return nil, sdk.ErrTxDecode("").TraceCause(err, "") + } + return tx, nil +} + +// custom logic for gaia initialization +func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { + stateJSON := req.AppStateBytes + + genesisState := new(GenesisState) + err := json.Unmarshal(stateJSON, genesisState) + if err != nil { + panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468 + // return sdk.ErrGenesisParse("").TraceCause(err, "") + } + + for _, gacc := range genesisState.Accounts { + acc := gacc.ToAccount() + app.accountMapper.SetAccount(ctx, &acc) + } + return abci.ResponseInitChain{} +} diff --git a/cmd/gaia/app/app_test.go b/cmd/gaia/app/app_test.go new file mode 100644 index 000000000..a440e7e38 --- /dev/null +++ b/cmd/gaia/app/app_test.go @@ -0,0 +1,432 @@ +package app + +import ( + "encoding/json" + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/ibc" + + abci "github.com/tendermint/abci/types" + crypto "github.com/tendermint/go-crypto" + dbm "github.com/tendermint/tmlibs/db" + "github.com/tendermint/tmlibs/log" +) + +// Construct some global addrs and txs for tests. +var ( + chainID = "" // TODO + + accName = "foobart" + + priv1 = crypto.GenPrivKeyEd25519() + addr1 = priv1.PubKey().Address() + priv2 = crypto.GenPrivKeyEd25519() + addr2 = priv2.PubKey().Address() + addr3 = crypto.GenPrivKeyEd25519().PubKey().Address() + priv4 = crypto.GenPrivKeyEd25519() + addr4 = priv4.PubKey().Address() + coins = sdk.Coins{{"foocoin", 10}} + halfCoins = sdk.Coins{{"foocoin", 5}} + manyCoins = sdk.Coins{{"foocoin", 1}, {"barcoin", 1}} + fee = sdk.StdFee{ + sdk.Coins{{"foocoin", 0}}, + 0, + } + + sendMsg1 = bank.SendMsg{ + Inputs: []bank.Input{bank.NewInput(addr1, coins)}, + Outputs: []bank.Output{bank.NewOutput(addr2, coins)}, + } + + sendMsg2 = bank.SendMsg{ + Inputs: []bank.Input{bank.NewInput(addr1, coins)}, + Outputs: []bank.Output{ + bank.NewOutput(addr2, halfCoins), + bank.NewOutput(addr3, halfCoins), + }, + } + + sendMsg3 = bank.SendMsg{ + Inputs: []bank.Input{ + bank.NewInput(addr1, coins), + bank.NewInput(addr4, coins), + }, + Outputs: []bank.Output{ + bank.NewOutput(addr2, coins), + bank.NewOutput(addr3, coins), + }, + } + + sendMsg4 = bank.SendMsg{ + Inputs: []bank.Input{ + bank.NewInput(addr2, coins), + }, + Outputs: []bank.Output{ + bank.NewOutput(addr1, coins), + }, + } + + sendMsg5 = bank.SendMsg{ + Inputs: []bank.Input{ + bank.NewInput(addr1, manyCoins), + }, + Outputs: []bank.Output{ + bank.NewOutput(addr2, manyCoins), + }, + } +) + +func loggerAndDBs() (log.Logger, map[string]dbm.DB) { + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") + dbs := map[string]dbm.DB{ + "main": dbm.NewMemDB(), + "acc": dbm.NewMemDB(), + "ibc": dbm.NewMemDB(), + "staking": dbm.NewMemDB(), + } + return logger, dbs +} + +func newGaiaApp() *GaiaApp { + logger, dbs := loggerAndDBs() + return NewGaiaApp(logger, dbs) +} + +func setGenesisAccounts(gapp *GaiaApp, accs ...auth.BaseAccount) error { + genaccs := make([]GenesisAccount, len(accs)) + for i, acc := range accs { + genaccs[i] = NewGenesisAccount(acc) + } + + genesisState := GenesisState{ + Accounts: genaccs, + } + + stateBytes, err := json.MarshalIndent(genesisState, "", "\t") + if err != nil { + return err + } + + // Initialize the chain + vals := []abci.Validator{} + gapp.InitChain(abci.RequestInitChain{vals, stateBytes}) + gapp.Commit() + + return nil +} + +//_______________________________________________________________________ + +func TestMsgs(t *testing.T) { + gapp := newGaiaApp() + + msgs := []struct { + msg sdk.Msg + }{ + {sendMsg1}, + } + + for i, m := range msgs { + // Run a CheckDeliver + SignCheckDeliver(t, gapp, m.msg, []int64{int64(i)}, false, priv1) + } +} + +func TestSortGenesis(t *testing.T) { + logger, dbs := loggerAndDBs() + gapp := NewGaiaApp(logger, dbs) + + // Note the order: the coins are unsorted! + coinDenom1, coinDenom2 := "foocoin", "barcoin" + + str := `{ + "accounts": [{ + "address": "%s", + "coins": [ + { + "denom": "%s", + "amount": 10 + }, + { + "denom": "%s", + "amount": 20 + } + ] + }] + }` + genState := fmt.Sprintf(str, addr1.String(), coinDenom1, coinDenom2) + + // Initialize the chain + vals := []abci.Validator{} + gapp.InitChain(abci.RequestInitChain{vals, []byte(genState)}) + gapp.Commit() + + // Unsorted coins means invalid + err := sendMsg5.ValidateBasic() + require.Equal(t, sdk.CodeInvalidCoins, err.ABCICode(), err.ABCILog()) + + // Sort coins, should be valid + sendMsg5.Inputs[0].Coins.Sort() + sendMsg5.Outputs[0].Coins.Sort() + err = sendMsg5.ValidateBasic() + require.Nil(t, err) + + // Ensure we can send + SignCheckDeliver(t, gapp, sendMsg5, []int64{0}, true, priv1) +} + +func TestGenesis(t *testing.T) { + logger, dbs := loggerAndDBs() + gapp := NewGaiaApp(logger, dbs) + + // Construct some genesis bytes to reflect GaiaAccount + pk := crypto.GenPrivKeyEd25519().PubKey() + addr := pk.Address() + coins, err := sdk.ParseCoins("77foocoin,99barcoin") + require.Nil(t, err) + baseAcc := auth.BaseAccount{ + Address: addr, + Coins: coins, + } + + err = setGenesisAccounts(gapp, baseAcc) + assert.Nil(t, err) + + // A checkTx context + ctx := gapp.BaseApp.NewContext(true, abci.Header{}) + res1 := gapp.accountMapper.GetAccount(ctx, baseAcc.Address) + assert.Equal(t, baseAcc, res1) + + // reload app and ensure the account is still there + gapp = NewGaiaApp(logger, dbs) + ctx = gapp.BaseApp.NewContext(true, abci.Header{}) + res1 = gapp.accountMapper.GetAccount(ctx, baseAcc.Address) + assert.Equal(t, baseAcc, res1) +} + +func TestSendMsgWithAccounts(t *testing.T) { + gapp := newGaiaApp() + + // Construct some genesis bytes to reflect GaiaAccount + // Give 77 foocoin to the first key + coins, err := sdk.ParseCoins("77foocoin") + require.Nil(t, err) + baseAcc := auth.BaseAccount{ + Address: addr1, + Coins: coins, + } + + // Construct genesis state + err = setGenesisAccounts(gapp, baseAcc) + assert.Nil(t, err) + // A checkTx context (true) + ctxCheck := gapp.BaseApp.NewContext(true, abci.Header{}) + res1 := gapp.accountMapper.GetAccount(ctxCheck, addr1) + assert.Equal(t, baseAcc, res1.(*auth.BaseAccount)) + + // Run a CheckDeliver + SignCheckDeliver(t, gapp, sendMsg1, []int64{0}, true, priv1) + + // Check balances + CheckBalance(t, gapp, addr1, "67foocoin") + CheckBalance(t, gapp, addr2, "10foocoin") + + // Delivering again should cause replay error + SignCheckDeliver(t, gapp, sendMsg1, []int64{0}, false, priv1) + + // bumping the txnonce number without resigning should be an auth error + tx := genTx(sendMsg1, []int64{0}, priv1) + tx.Signatures[0].Sequence = 1 + res := gapp.Deliver(tx) + + assert.Equal(t, sdk.CodeUnauthorized, res.Code, res.Log) + + // resigning the tx with the bumped sequence should work + SignCheckDeliver(t, gapp, sendMsg1, []int64{1}, true, priv1) +} + +func TestSendMsgMultipleOut(t *testing.T) { + gapp := newGaiaApp() + + genCoins, err := sdk.ParseCoins("42foocoin") + require.Nil(t, err) + + acc1 := auth.BaseAccount{ + Address: addr1, + Coins: genCoins, + } + + acc2 := auth.BaseAccount{ + Address: addr2, + Coins: genCoins, + } + + err = setGenesisAccounts(gapp, acc1, acc2) + assert.Nil(t, err) + + // Simulate a Block + SignCheckDeliver(t, gapp, sendMsg2, []int64{0}, true, priv1) + + // Check balances + CheckBalance(t, gapp, addr1, "32foocoin") + CheckBalance(t, gapp, addr2, "47foocoin") + CheckBalance(t, gapp, addr3, "5foocoin") +} + +func TestSengMsgMultipleInOut(t *testing.T) { + gapp := newGaiaApp() + + genCoins, err := sdk.ParseCoins("42foocoin") + require.Nil(t, err) + + acc1 := auth.BaseAccount{ + Address: addr1, + Coins: genCoins, + } + + acc2 := auth.BaseAccount{ + Address: addr2, + Coins: genCoins, + } + + acc4 := auth.BaseAccount{ + Address: addr4, + Coins: genCoins, + } + + err = setGenesisAccounts(gapp, acc1, acc2, acc4) + assert.Nil(t, err) + + // CheckDeliver + SignCheckDeliver(t, gapp, sendMsg3, []int64{0, 0}, true, priv1, priv4) + + // Check balances + CheckBalance(t, gapp, addr1, "32foocoin") + CheckBalance(t, gapp, addr4, "32foocoin") + CheckBalance(t, gapp, addr2, "52foocoin") + CheckBalance(t, gapp, addr3, "10foocoin") +} + +func TestSendMsgDependent(t *testing.T) { + gapp := newGaiaApp() + + genCoins, err := sdk.ParseCoins("42foocoin") + require.Nil(t, err) + + acc1 := auth.BaseAccount{ + Address: addr1, + Coins: genCoins, + } + + err = setGenesisAccounts(gapp, acc1) + assert.Nil(t, err) + + // CheckDeliver + SignCheckDeliver(t, gapp, sendMsg1, []int64{0}, true, priv1) + + // Check balances + CheckBalance(t, gapp, addr1, "32foocoin") + CheckBalance(t, gapp, addr2, "10foocoin") + + // Simulate a Block + SignCheckDeliver(t, gapp, sendMsg4, []int64{0}, true, priv2) + + // Check balances + CheckBalance(t, gapp, addr1, "42foocoin") +} + +func TestIBCMsgs(t *testing.T) { + gapp := newGaiaApp() + + sourceChain := "source-chain" + destChain := "dest-chain" + + baseAcc := auth.BaseAccount{ + Address: addr1, + Coins: coins, + } + + err := setGenesisAccounts(gapp, baseAcc) + assert.Nil(t, err) + // A checkTx context (true) + ctxCheck := gapp.BaseApp.NewContext(true, abci.Header{}) + res1 := gapp.accountMapper.GetAccount(ctxCheck, addr1) + assert.Equal(t, baseAcc, res1) + + packet := ibc.IBCPacket{ + SrcAddr: addr1, + DestAddr: addr1, + Coins: coins, + SrcChain: sourceChain, + DestChain: destChain, + } + + transferMsg := ibc.IBCTransferMsg{ + IBCPacket: packet, + } + + receiveMsg := ibc.IBCReceiveMsg{ + IBCPacket: packet, + Relayer: addr1, + Sequence: 0, + } + + SignCheckDeliver(t, gapp, transferMsg, []int64{0}, true, priv1) + CheckBalance(t, gapp, addr1, "") + SignCheckDeliver(t, gapp, transferMsg, []int64{1}, false, priv1) + SignCheckDeliver(t, gapp, receiveMsg, []int64{2}, true, priv1) + CheckBalance(t, gapp, addr1, "10foocoin") + SignCheckDeliver(t, gapp, receiveMsg, []int64{3}, false, priv1) +} + +func genTx(msg sdk.Msg, seq []int64, priv ...crypto.PrivKeyEd25519) sdk.StdTx { + sigs := make([]sdk.StdSignature, len(priv)) + for i, p := range priv { + sigs[i] = sdk.StdSignature{ + PubKey: p.PubKey(), + Signature: p.Sign(sdk.StdSignBytes(chainID, seq, fee, msg)), + Sequence: seq[i], + } + } + + return sdk.NewStdTx(msg, fee, sigs) + +} + +func SignCheckDeliver(t *testing.T, gapp *GaiaApp, msg sdk.Msg, seq []int64, expPass bool, priv ...crypto.PrivKeyEd25519) { + + // Sign the tx + tx := genTx(msg, seq, priv...) + // Run a Check + res := gapp.Check(tx) + if expPass { + require.Equal(t, sdk.CodeOK, res.Code, res.Log) + } else { + require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + } + + // Simulate a Block + gapp.BeginBlock(abci.RequestBeginBlock{}) + res = gapp.Deliver(tx) + if expPass { + require.Equal(t, sdk.CodeOK, res.Code, res.Log) + } else { + require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + } + gapp.EndBlock(abci.RequestEndBlock{}) + //gapp.Commit() +} + +func CheckBalance(t *testing.T, gapp *GaiaApp, addr sdk.Address, balExpected string) { + ctxDeliver := gapp.BaseApp.NewContext(false, abci.Header{}) + res2 := gapp.accountMapper.GetAccount(ctxDeliver, addr) + assert.Equal(t, balExpected, fmt.Sprintf("%v", res2.GetCoins())) +} diff --git a/cmd/gaia/cmd/gaiacli/main.go b/cmd/gaia/cmd/gaiacli/main.go new file mode 100644 index 000000000..c5c3190c3 --- /dev/null +++ b/cmd/gaia/cmd/gaiacli/main.go @@ -0,0 +1,79 @@ +package main + +import ( + "os" + + "github.com/spf13/cobra" + + "github.com/tendermint/tmlibs/cli" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/keys" + "github.com/cosmos/cosmos-sdk/client/lcd" + "github.com/cosmos/cosmos-sdk/client/rpc" + "github.com/cosmos/cosmos-sdk/client/tx" + + "github.com/cosmos/cosmos-sdk/version" + authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands" + bankcmd "github.com/cosmos/cosmos-sdk/x/bank/commands" + ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/commands" + stakecmd "github.com/cosmos/cosmos-sdk/x/stake/commands" + + "github.com/cosmos/cosmos-sdk/cmd/gaia/app" +) + +// rootCmd is the entry point for this binary +var ( + rootCmd = &cobra.Command{ + Use: "gaiacli", + Short: "Gaia light-client", + } +) + +func main() { + cobra.EnableCommandSorting = false + cdc := app.MakeCodec() + + // TODO: setup keybase, viper object, etc. to be passed into + // the below functions and eliminate global vars, like we do + // with the cdc + + // add standard rpc, and tx commands + rpc.AddCommands(rootCmd) + rootCmd.AddCommand(client.LineBreak) + tx.AddCommands(rootCmd, cdc) + rootCmd.AddCommand(client.LineBreak) + + // add query/post commands (custom to binary) + rootCmd.AddCommand( + client.GetCommands( + authcmd.GetAccountCmd("main", cdc, authcmd.GetAccountDecoder(cdc)), + stakecmd.GetCmdQueryCandidates("stake", cdc), + stakecmd.GetCmdQueryCandidate("stake", cdc), + stakecmd.GetCmdQueryDelegatorBond("stake", cdc), + stakecmd.GetCmdQueryDelegatorBonds("stake", cdc), + )...) + rootCmd.AddCommand( + client.PostCommands( + bankcmd.SendTxCmd(cdc), + ibccmd.IBCTransferCmd(cdc), + ibccmd.IBCRelayCmd(cdc), + stakecmd.GetCmdDeclareCandidacy(cdc), + stakecmd.GetCmdEditCandidacy(cdc), + stakecmd.GetCmdDelegate(cdc), + stakecmd.GetCmdUnbond(cdc), + )...) + + // add proxy, version and key info + rootCmd.AddCommand( + client.LineBreak, + lcd.ServeCommand(cdc), + keys.Commands(), + client.LineBreak, + version.VersionCmd, + ) + + // prepare and add flags + executor := cli.PrepareMainCmd(rootCmd, "GA", os.ExpandEnv("$HOME/.gaiacli")) + executor.Execute() +} diff --git a/cmd/gaiad/main.go b/cmd/gaia/cmd/gaiad/main.go similarity index 60% rename from cmd/gaiad/main.go rename to cmd/gaia/cmd/gaiad/main.go index 9ebf196db..f966c446a 100644 --- a/cmd/gaiad/main.go +++ b/cmd/gaia/cmd/gaiad/main.go @@ -11,7 +11,7 @@ import ( dbm "github.com/tendermint/tmlibs/db" "github.com/tendermint/tmlibs/log" - "github.com/cosmos/cosmos-sdk/examples/basecoin/app" + "github.com/cosmos/cosmos-sdk/cmd/gaia/app" "github.com/cosmos/cosmos-sdk/server" ) @@ -25,7 +25,6 @@ var ( } ) -// TODO: distinguish from basecoin func generateApp(rootDir string, logger log.Logger) (abci.Application, error) { dataDir := filepath.Join(rootDir, "data") db, err := dbm.NewGoLevelDB("gaia", dataDir) @@ -33,6 +32,25 @@ func generateApp(rootDir string, logger log.Logger) (abci.Application, error) { return nil, err } bapp := app.NewBasecoinApp(logger, db) + //dbAcc, err := dbm.NewGoLevelDB("gaia-acc", dataDir) + //if err != nil { + //return nil, err + //} + //dbIBC, err := dbm.NewGoLevelDB("gaia-ibc", dataDir) + //if err != nil { + //return nil, err + //} + //dbStaking, err := dbm.NewGoLevelDB("gaia-staking", dataDir) + //if err != nil { + //return nil, err + //} + //dbs := map[string]dbm.DB{ + //"main": dbMain, + //"acc": dbAcc, + //"ibc": dbIBC, + //"staking": dbStaking, + //} + //bapp := app.NewGaiaApp(logger, dbs) return bapp, nil } @@ -40,6 +58,7 @@ func main() { server.AddCommands(rootCmd, server.DefaultGenAppState, generateApp, context) // prepare and add flags - executor := cli.PrepareBaseCmd(rootCmd, "GA", os.ExpandEnv("$HOME/.gaiad")) + rootDir := os.ExpandEnv("$HOME/.gaiad") + executor := cli.PrepareBaseCmd(rootCmd, "GA", rootDir) executor.Execute() } diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index 9ef48bfb5..bb3ef05ac 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -15,7 +15,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/ibc" "github.com/cosmos/cosmos-sdk/x/simplestake" - "github.com/cosmos/cosmos-sdk/x/stake" "github.com/cosmos/cosmos-sdk/examples/basecoin/types" ) @@ -33,7 +32,7 @@ type BasecoinApp struct { capKeyMainStore *sdk.KVStoreKey capKeyAccountStore *sdk.KVStoreKey capKeyIBCStore *sdk.KVStoreKey - capKeyStakeStore *sdk.KVStoreKey + capKeyStakingStore *sdk.KVStoreKey // Manage getting and setting accounts accountMapper sdk.AccountMapper @@ -54,7 +53,7 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp { capKeyMainStore: sdk.NewKVStoreKey("main"), capKeyAccountStore: sdk.NewKVStoreKey("acc"), capKeyIBCStore: sdk.NewKVStoreKey("ibc"), - capKeyStakeStore: sdk.NewKVStoreKey("stake"), + capKeyStakingStore: sdk.NewKVStoreKey("stake"), } // Define the accountMapper. @@ -71,7 +70,7 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp { app.Router(). AddRoute("bank", bank.NewHandler(coinKeeper)). AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)). - AddRoute("stake", stake.NewHandler(stakeKeeper)) + AddRoute("simplestake", simplestake.NewHandler(stakeKeeper)) // Define the feeHandler. app.feeHandler = auth.BurnFeeHandler diff --git a/examples/basecoin/app/app_test.go b/examples/basecoin/app/app_test.go index 1f635f53f..36461a8e3 100644 --- a/examples/basecoin/app/app_test.go +++ b/examples/basecoin/app/app_test.go @@ -143,7 +143,7 @@ func TestSortGenesis(t *testing.T) { // Note the order: the coins are unsorted! coinDenom1, coinDenom2 := "foocoin", "barcoin" - str := `{ + genState := fmt.Sprintf(`{ "accounts": [{ "address": "%s", "coins": [ @@ -157,8 +157,7 @@ func TestSortGenesis(t *testing.T) { } ] }] - }` - genState := fmt.Sprintf(str, addr1.String(), coinDenom1, coinDenom2) + }`, addr1.String(), coinDenom1, coinDenom2) // Initialize the chain vals := []abci.Validator{} @@ -345,9 +344,10 @@ func TestQuizMsg(t *testing.T) { // Construct genesis state // Construct some genesis bytes to reflect basecoin/types/AppAccount + coins := sdk.Coins{} baseAcc := auth.BaseAccount{ Address: addr1, - Coins: nil, + Coins: coins, } acc1 := &types.AppAccount{baseAcc, "foobart"} diff --git a/examples/basecoin/cmd/basecli/main.go b/examples/basecoin/cmd/basecli/main.go index bab24f91b..6271adcec 100644 --- a/examples/basecoin/cmd/basecli/main.go +++ b/examples/basecoin/cmd/basecli/main.go @@ -17,7 +17,7 @@ import ( authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands" bankcmd "github.com/cosmos/cosmos-sdk/x/bank/commands" ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/commands" - stakecmd "github.com/cosmos/cosmos-sdk/x/stake/commands" + simplestakingcmd "github.com/cosmos/cosmos-sdk/x/simplestake/commands" "github.com/cosmos/cosmos-sdk/examples/basecoin/app" "github.com/cosmos/cosmos-sdk/examples/basecoin/types" @@ -52,20 +52,23 @@ func main() { rootCmd.AddCommand( client.GetCommands( authcmd.GetAccountCmd("main", cdc, types.GetAccountDecoder(cdc)), - stakecmd.GetCmdQueryCandidates("stake", cdc), - stakecmd.GetCmdQueryCandidate("stake", cdc), - stakecmd.GetCmdQueryDelegatorBond("stake", cdc), - stakecmd.GetCmdQueryDelegatorBonds("stake", cdc), )...) rootCmd.AddCommand( client.PostCommands( bankcmd.SendTxCmd(cdc), + )...) + rootCmd.AddCommand( + client.PostCommands( ibccmd.IBCTransferCmd(cdc), + )...) + rootCmd.AddCommand( + client.PostCommands( ibccmd.IBCRelayCmd(cdc), - stakecmd.GetCmdDeclareCandidacy(cdc), - stakecmd.GetCmdEditCandidacy(cdc), - stakecmd.GetCmdDelegate(cdc), - stakecmd.GetCmdUnbond(cdc), + simplestakingcmd.BondTxCmd(cdc), + )...) + rootCmd.AddCommand( + client.PostCommands( + simplestakingcmd.UnbondTxCmd(cdc), )...) // add proxy, version and key info diff --git a/x/stake/handler.go b/x/stake/handler.go index e1f624f10..af1ad291d 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -252,40 +252,3 @@ func handleMsgUnbond(ctx sdk.Context, msg MsgUnbond, k Keeper) sdk.Result { k.setPool(ctx, p) return sdk.Result{} } - -// TODO use or remove -//// Perform all the actions required to bond tokens to a delegator bond from their account -//func BondCoins(ctx sdk.Context, k Keeper, bond DelegatorBond, -//candidate Candidate, amount sdk.Coin) (DelegatorBond, Candidate, Pool, sdk.Error) { - -//pool := k.GetPool(ctx) -//_, err := k.coinKeeper.SubtractCoins(ctx, bond.DelegatorAddr, sdk.Coins{amount}) -//if err != nil { -//return bond, candidate, pool, err -//} -//pool, candidate, newShares := pool.candidateAddTokens(candidate, amount.Amount) -//bond.Shares = bond.Shares.Add(newShares) -//return bond, candidate, pool, nil -//} -//// Perform all the actions required to bond tokens to a delegator bond from their account -//func UnbondCoins(ctx sdk.Context, k Keeper, bond DelegatorBond, -//candidate Candidate, shares sdk.Rat) (DelegatorBond, Candidate, Pool, sdk.Error) { - -//pool := k.GetPool(ctx) - -//// subtract bond tokens from delegator bond -//if bond.Shares.LT(shares) { -//errMsg := fmt.Sprintf("cannot unbond %v shares, only have %v shares available", shares, bond.Shares) -//return bond, candidate, pool, sdk.ErrInsufficientFunds(errMsg) -//} -//bond.Shares = bond.Shares.Sub(shares) - -//pool, candidate, returnAmount := p.candidateRemoveShares(candidate, shares) -//returnCoins := sdk.Coins{{k.GetParams(ctx).BondDenom, returnAmount}} - -//_, err := k.coinKeeper.AddCoins(ctx, candidate.Address, returnCoins) -//if err != nil { -//return err -//} -//return bond, candidate, pool, nil -//} From 8a34b91facbe8dd113163d4c92dfa66ae4caa9a9 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 7 Apr 2018 01:50:46 -0400 Subject: [PATCH 04/71] fix existing gaia tests --- cmd/gaia/app/account.go | 32 ------------------------ cmd/gaia/app/app.go | 53 ++++++++++++++++++++++++++++++++++------ cmd/gaia/app/app_test.go | 38 +++++++++++++++------------- x/stake/handler.go | 16 +++++++++++- x/stake/handler_test.go | 9 +++++++ x/stake/keeper.go | 12 --------- x/stake/keeper_test.go | 29 ---------------------- x/stake/test_common.go | 25 +++++++++++++++++++ x/stake/types.go | 24 +++++++++--------- 9 files changed, 127 insertions(+), 111 deletions(-) delete mode 100644 cmd/gaia/app/account.go diff --git a/cmd/gaia/app/account.go b/cmd/gaia/app/account.go deleted file mode 100644 index 3d5673b87..000000000 --- a/cmd/gaia/app/account.go +++ /dev/null @@ -1,32 +0,0 @@ -package app - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth" -) - -// State to Unmarshal -type GenesisState struct { - Accounts []GenesisAccount `json:"accounts"` -} - -// GenesisAccount doesn't need pubkey or sequence -type GenesisAccount struct { - Address sdk.Address `json:"address"` - Coins sdk.Coins `json:"coins"` -} - -func NewGenesisAccount(acc auth.BaseAccount) GenesisAccount { - return GenesisAccount{ - Address: acc.Address, - Coins: acc.Coins, - } -} - -// convert GenesisAccount to GaiaAccount -func (ga *GenesisAccount) ToAccount() (acc auth.BaseAccount) { - return auth.BaseAccount{ - Address: ga.Address, - Coins: ga.Coins.Sort(), - } -} diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 64b1619f8..6cf67b0f2 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -35,6 +35,9 @@ type GaiaApp struct { // Manage getting and setting accounts accountMapper sdk.AccountMapper + coinKeeper bank.CoinKeeper + ibcMapper ibc.IBCMapper + stakeKeeper stake.Keeper } func NewGaiaApp(logger log.Logger, dbs map[string]dbm.DB) *GaiaApp { @@ -55,18 +58,18 @@ func NewGaiaApp(logger log.Logger, dbs map[string]dbm.DB) *GaiaApp { ) // add handlers - coinKeeper := bank.NewCoinKeeper(app.accountMapper) - ibcMapper := ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore) - stakeKeeper := stake.NewKeeper(app.cdc, app.capKeyStakeStore, coinKeeper) + app.coinKeeper = bank.NewCoinKeeper(app.accountMapper) + app.ibcMapper = ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore) + app.stakeKeeper = stake.NewKeeper(app.cdc, app.capKeyStakeStore, app.coinKeeper) app.Router(). - AddRoute("bank", bank.NewHandler(coinKeeper)). - AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)). - AddRoute("stake", stake.NewHandler(stakeKeeper)) + AddRoute("bank", bank.NewHandler(app.coinKeeper)). + AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.coinKeeper)). + AddRoute("stake", stake.NewHandler(app.stakeKeeper)) // initialize BaseApp app.SetTxDecoder(app.txDecoder) app.SetInitChainer(app.initChainer) - app.SetEndBlocker(stake.NewEndBlocker(stakeKeeper)) + app.SetEndBlocker(stake.NewEndBlocker(app.stakeKeeper)) app.MountStoreWithDB(app.capKeyMainStore, sdk.StoreTypeIAVL, dbs["main"]) app.MountStoreWithDB(app.capKeyAccountStore, sdk.StoreTypeIAVL, dbs["acc"]) app.MountStoreWithDB(app.capKeyIBCStore, sdk.StoreTypeIAVL, dbs["ibc"]) @@ -150,9 +153,43 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci // return sdk.ErrGenesisParse("").TraceCause(err, "") } + // load the accounts for _, gacc := range genesisState.Accounts { acc := gacc.ToAccount() - app.accountMapper.SetAccount(ctx, &acc) + app.accountMapper.SetAccount(ctx, acc) } + + // load the initial stake information + stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData) + return abci.ResponseInitChain{} } + +//__________________________________________________________ + +// State to Unmarshal +type GenesisState struct { + Accounts []GenesisAccount `json:"accounts"` + StakeData json.RawMessage `json:"stake"` +} + +// GenesisAccount doesn't need pubkey or sequence +type GenesisAccount struct { + Address sdk.Address `json:"address"` + Coins sdk.Coins `json:"coins"` +} + +func NewGenesisAccount(acc *auth.BaseAccount) GenesisAccount { + return GenesisAccount{ + Address: acc.Address, + Coins: acc.Coins, + } +} + +// convert GenesisAccount to GaiaAccount +func (ga *GenesisAccount) ToAccount() (acc *auth.BaseAccount) { + return &auth.BaseAccount{ + Address: ga.Address, + Coins: ga.Coins.Sort(), + } +} diff --git a/cmd/gaia/app/app_test.go b/cmd/gaia/app/app_test.go index a440e7e38..a9cc4b739 100644 --- a/cmd/gaia/app/app_test.go +++ b/cmd/gaia/app/app_test.go @@ -13,6 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/ibc" + "github.com/cosmos/cosmos-sdk/x/stake" abci "github.com/tendermint/abci/types" crypto "github.com/tendermint/go-crypto" @@ -100,14 +101,15 @@ func newGaiaApp() *GaiaApp { return NewGaiaApp(logger, dbs) } -func setGenesisAccounts(gapp *GaiaApp, accs ...auth.BaseAccount) error { +func setGenesis(gapp *GaiaApp, accs ...*auth.BaseAccount) error { genaccs := make([]GenesisAccount, len(accs)) for i, acc := range accs { genaccs[i] = NewGenesisAccount(acc) } genesisState := GenesisState{ - Accounts: genaccs, + Accounts: genaccs, + StakeData: stake.GetGenesisJSON(), } stateBytes, err := json.MarshalIndent(genesisState, "", "\t") @@ -127,6 +129,7 @@ func setGenesisAccounts(gapp *GaiaApp, accs ...auth.BaseAccount) error { func TestMsgs(t *testing.T) { gapp := newGaiaApp() + assert.Nil(t, setGenesis(gapp)) msgs := []struct { msg sdk.Msg @@ -180,6 +183,7 @@ func TestSortGenesis(t *testing.T) { require.Nil(t, err) // Ensure we can send + assert.Nil(t, setGenesis(gapp)) // initialize the pool SignCheckDeliver(t, gapp, sendMsg5, []int64{0}, true, priv1) } @@ -192,12 +196,12 @@ func TestGenesis(t *testing.T) { addr := pk.Address() coins, err := sdk.ParseCoins("77foocoin,99barcoin") require.Nil(t, err) - baseAcc := auth.BaseAccount{ + baseAcc := &auth.BaseAccount{ Address: addr, Coins: coins, } - err = setGenesisAccounts(gapp, baseAcc) + err = setGenesis(gapp, baseAcc) assert.Nil(t, err) // A checkTx context @@ -219,13 +223,13 @@ func TestSendMsgWithAccounts(t *testing.T) { // Give 77 foocoin to the first key coins, err := sdk.ParseCoins("77foocoin") require.Nil(t, err) - baseAcc := auth.BaseAccount{ + baseAcc := &auth.BaseAccount{ Address: addr1, Coins: coins, } // Construct genesis state - err = setGenesisAccounts(gapp, baseAcc) + err = setGenesis(gapp, baseAcc) assert.Nil(t, err) // A checkTx context (true) ctxCheck := gapp.BaseApp.NewContext(true, abci.Header{}) @@ -259,17 +263,17 @@ func TestSendMsgMultipleOut(t *testing.T) { genCoins, err := sdk.ParseCoins("42foocoin") require.Nil(t, err) - acc1 := auth.BaseAccount{ + acc1 := &auth.BaseAccount{ Address: addr1, Coins: genCoins, } - acc2 := auth.BaseAccount{ + acc2 := &auth.BaseAccount{ Address: addr2, Coins: genCoins, } - err = setGenesisAccounts(gapp, acc1, acc2) + err = setGenesis(gapp, acc1, acc2) assert.Nil(t, err) // Simulate a Block @@ -287,22 +291,22 @@ func TestSengMsgMultipleInOut(t *testing.T) { genCoins, err := sdk.ParseCoins("42foocoin") require.Nil(t, err) - acc1 := auth.BaseAccount{ + acc1 := &auth.BaseAccount{ Address: addr1, Coins: genCoins, } - acc2 := auth.BaseAccount{ + acc2 := &auth.BaseAccount{ Address: addr2, Coins: genCoins, } - acc4 := auth.BaseAccount{ + acc4 := &auth.BaseAccount{ Address: addr4, Coins: genCoins, } - err = setGenesisAccounts(gapp, acc1, acc2, acc4) + err = setGenesis(gapp, acc1, acc2, acc4) assert.Nil(t, err) // CheckDeliver @@ -321,12 +325,12 @@ func TestSendMsgDependent(t *testing.T) { genCoins, err := sdk.ParseCoins("42foocoin") require.Nil(t, err) - acc1 := auth.BaseAccount{ + acc1 := &auth.BaseAccount{ Address: addr1, Coins: genCoins, } - err = setGenesisAccounts(gapp, acc1) + err = setGenesis(gapp, acc1) assert.Nil(t, err) // CheckDeliver @@ -349,12 +353,12 @@ func TestIBCMsgs(t *testing.T) { sourceChain := "source-chain" destChain := "dest-chain" - baseAcc := auth.BaseAccount{ + baseAcc := &auth.BaseAccount{ Address: addr1, Coins: coins, } - err := setGenesisAccounts(gapp, baseAcc) + err := setGenesis(gapp, baseAcc) assert.Nil(t, err) // A checkTx context (true) ctxCheck := gapp.BaseApp.NewContext(true, abci.Header{}) diff --git a/x/stake/handler.go b/x/stake/handler.go index af1ad291d..36b4509da 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -2,6 +2,7 @@ package stake import ( "bytes" + "encoding/json" sdk "github.com/cosmos/cosmos-sdk/types" abci "github.com/tendermint/abci/types" @@ -35,7 +36,7 @@ func NewHandler(k Keeper) sdk.Handler { } } -//_______________________________________________ +//_____________________________________________________________________ // NewEndBlocker generates sdk.EndBlocker // Performs tick functionality @@ -48,6 +49,19 @@ func NewEndBlocker(k Keeper) sdk.EndBlocker { //_____________________________________________________________________ +// InitGenesis - store genesis parameters +func InitGenesis(ctx sdk.Context, k Keeper, data json.RawMessage) error { + var state GenesisState + if err := json.Unmarshal(data, &state); err != nil { + return err + } + k.setPool(ctx, state.Pool) + k.setParams(ctx, state.Params) + return nil +} + +//_____________________________________________________________________ + // These functions assume everything has been authenticated, // now we just perform action and save diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index 1f0bc6415..82b33cf2c 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -12,6 +12,15 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +func TestInitGenesis(t *testing.T) { + ctx, _, keeper := createTestInput(t, false, 0) + encoded := GetGenesisJSON() + err := InitGenesis(ctx, keeper, encoded) + require.Nil(t, err) + require.Equal(t, keeper.GetPool(ctx), initialPool()) + require.Equal(t, keeper.GetParams(ctx), defaultParams()) +} + //______________________________________________________________________ func newTestMsgDeclareCandidacy(address sdk.Address, pubKey crypto.PubKey, amt int64) MsgDeclareCandidacy { diff --git a/x/stake/keeper.go b/x/stake/keeper.go index ae3dfb7c7..8b73e81db 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -2,7 +2,6 @@ package stake import ( "bytes" - "encoding/json" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" @@ -34,17 +33,6 @@ func NewKeeper(ctx sdk.Context, cdc *wire.Codec, key sdk.StoreKey, ck bank.CoinK return keeper } -// InitGenesis - store genesis parameters -func (k Keeper) InitGenesis(ctx sdk.Context, data json.RawMessage) error { - var state GenesisState - if err := json.Unmarshal(data, &state); err != nil { - return err - } - k.setPool(ctx, state.Pool) - k.setParams(ctx, state.Params) - return nil -} - //_________________________________________________________________________ // get a single candidate diff --git a/x/stake/keeper_test.go b/x/stake/keeper_test.go index 088bc5e30..e8d8e0594 100644 --- a/x/stake/keeper_test.go +++ b/x/stake/keeper_test.go @@ -2,7 +2,6 @@ package stake import ( "bytes" - "encoding/json" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -584,31 +583,3 @@ func TestPool(t *testing.T) { resPool = keeper.GetPool(ctx) assert.Equal(t, expPool, resPool) } - -func TestInitGenesis(t *testing.T) { - ctx, _, keeper := createTestInput(t, false, 0) - jsonStr := `{ - "params": { - "inflation_rate_change": {"num": 13, "denom": 100}, - "inflation_max": {"num": 20, "denom": 100}, - "inflation_min": {"num": 7, "denom": 100}, - "goal_bonded": {"num": 67, "denom": 100}, - "max_validators": 100, - "bond_denom": "fermion" - }, - "pool": { - "total_supply": 0, - "bonded_shares": {"num": 0, "denom": 1}, - "unbonded_shares": {"num": 0, "denom": 1}, - "bonded_pool": 0, - "unbonded_pool": 0, - "inflation_last_time": 0, - "inflation": {"num": 7, "denom": 100} - } -}` - encoded := json.RawMessage(jsonStr) - err := keeper.InitGenesis(ctx, encoded) - require.Nil(t, err) - require.Equal(t, keeper.GetPool(ctx), initialPool()) - require.Equal(t, keeper.GetParams(ctx), defaultParams()) -} diff --git a/x/stake/test_common.go b/x/stake/test_common.go index 6470abbc7..5b0bc97e0 100644 --- a/x/stake/test_common.go +++ b/x/stake/test_common.go @@ -2,6 +2,7 @@ package stake import ( "encoding/hex" + "encoding/json" "testing" "github.com/stretchr/testify/require" @@ -75,6 +76,30 @@ func initialPool() Pool { } } +// get raw genesis raw message for testing +func GetGenesisJSON() json.RawMessage { + jsonStr := `{ + "params": { + "inflation_rate_change": {"num": 13, "denom": 100}, + "inflation_max": {"num": 20, "denom": 100}, + "inflation_min": {"num": 7, "denom": 100}, + "goal_bonded": {"num": 67, "denom": 100}, + "max_validators": 100, + "bond_denom": "fermion" + }, + "pool": { + "total_supply": 0, + "bonded_shares": {"num": 0, "denom": 1}, + "unbonded_shares": {"num": 0, "denom": 1}, + "bonded_pool": 0, + "unbonded_pool": 0, + "inflation_last_time": 0, + "inflation": {"num": 7, "denom": 100} + } +}` + return json.RawMessage(jsonStr) +} + // XXX reference the common declaration of this function func subspace(prefix []byte) (start, end []byte) { end = make([]byte, len(prefix)) diff --git a/x/stake/types.go b/x/stake/types.go index 1154f7962..240f3fe2a 100644 --- a/x/stake/types.go +++ b/x/stake/types.go @@ -7,6 +7,14 @@ import ( crypto "github.com/tendermint/go-crypto" ) +// GenesisState - all staking state that must be provided at genesis +type GenesisState struct { + Pool Pool `json:"pool"` + Params Params `json:"params"` +} + +//_________________________________________________________________________ + // Params defines the high level settings for staking type Params struct { InflationRateChange sdk.Rat `json:"inflation_rate_change"` // maximum annual change in inflation rate @@ -31,13 +39,7 @@ type Pool struct { Inflation sdk.Rat `json:"inflation"` // current annual inflation rate } -// GenesisState - all staking state that must be provided at genesis -type GenesisState struct { - Pool Pool `json:"pool"` - Params Params `json:"params"` -} - -//_______________________________________________________________________________________________________ +//_________________________________________________________________________ // CandidateStatus - status of a validator-candidate type CandidateStatus byte @@ -65,6 +67,9 @@ type Candidate struct { Description Description `json:"description"` // Description terms for the candidate } +// Candidates - list of Candidates +type Candidates []Candidate + // NewCandidate - initialize a new candidate func NewCandidate(address sdk.Address, pubKey crypto.PubKey, description Description) Candidate { return Candidate{ @@ -151,11 +156,6 @@ func (v Validator) abciValidatorZero(cdc *wire.Codec) abci.Validator { //_________________________________________________________________________ -// Candidates - list of Candidates -type Candidates []Candidate - -//_________________________________________________________________________ - // DelegatorBond represents the bond with tokens held by an account. It is // owned by one delegator, and is associated with the voting power of one // pubKey. From c4a1c12119e7c91f573a7f78a731e780aaed51ed Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 7 Apr 2018 02:11:08 -0400 Subject: [PATCH 05/71] gaia app_test for declare candidacy --- cmd/gaia/app/app_test.go | 65 +++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/cmd/gaia/app/app_test.go b/cmd/gaia/app/app_test.go index a9cc4b739..544249a8a 100644 --- a/cmd/gaia/app/app_test.go +++ b/cmd/gaia/app/app_test.go @@ -129,7 +129,7 @@ func setGenesis(gapp *GaiaApp, accs ...*auth.BaseAccount) error { func TestMsgs(t *testing.T) { gapp := newGaiaApp() - assert.Nil(t, setGenesis(gapp)) + require.Nil(t, setGenesis(gapp)) msgs := []struct { msg sdk.Msg @@ -183,7 +183,7 @@ func TestSortGenesis(t *testing.T) { require.Nil(t, err) // Ensure we can send - assert.Nil(t, setGenesis(gapp)) // initialize the pool + require.Nil(t, setGenesis(gapp)) // initialize the pool SignCheckDeliver(t, gapp, sendMsg5, []int64{0}, true, priv1) } @@ -230,7 +230,8 @@ func TestSendMsgWithAccounts(t *testing.T) { // Construct genesis state err = setGenesis(gapp, baseAcc) - assert.Nil(t, err) + require.Nil(t, err) + // A checkTx context (true) ctxCheck := gapp.BaseApp.NewContext(true, abci.Header{}) res1 := gapp.accountMapper.GetAccount(ctxCheck, addr1) @@ -274,7 +275,7 @@ func TestSendMsgMultipleOut(t *testing.T) { } err = setGenesis(gapp, acc1, acc2) - assert.Nil(t, err) + require.Nil(t, err) // Simulate a Block SignCheckDeliver(t, gapp, sendMsg2, []int64{0}, true, priv1) @@ -295,12 +296,10 @@ func TestSengMsgMultipleInOut(t *testing.T) { Address: addr1, Coins: genCoins, } - acc2 := &auth.BaseAccount{ Address: addr2, Coins: genCoins, } - acc4 := &auth.BaseAccount{ Address: addr4, Coins: genCoins, @@ -331,7 +330,7 @@ func TestSendMsgDependent(t *testing.T) { } err = setGenesis(gapp, acc1) - assert.Nil(t, err) + require.Nil(t, err) // CheckDeliver SignCheckDeliver(t, gapp, sendMsg1, []int64{0}, true, priv1) @@ -359,7 +358,8 @@ func TestIBCMsgs(t *testing.T) { } err := setGenesis(gapp, baseAcc) - assert.Nil(t, err) + require.Nil(t, err) + // A checkTx context (true) ctxCheck := gapp.BaseApp.NewContext(true, abci.Header{}) res1 := gapp.accountMapper.GetAccount(ctxCheck, addr1) @@ -391,6 +391,49 @@ func TestIBCMsgs(t *testing.T) { SignCheckDeliver(t, gapp, receiveMsg, []int64{3}, false, priv1) } +func TestStakeMsgs(t *testing.T) { + gapp := newGaiaApp() + + genCoins, err := sdk.ParseCoins("42fermion") + require.Nil(t, err) + bondCoin, err := sdk.ParseCoin("10fermion") + require.Nil(t, err) + + acc1 := &auth.BaseAccount{ + Address: addr1, + Coins: genCoins, + } + acc2 := &auth.BaseAccount{ + Address: addr2, + Coins: genCoins, + } + + err = setGenesis(gapp, acc1, acc2) + require.Nil(t, err) + + // A checkTx context (true) + ctxCheck := gapp.BaseApp.NewContext(true, abci.Header{}) + res1 := gapp.accountMapper.GetAccount(ctxCheck, addr1) + res2 := gapp.accountMapper.GetAccount(ctxCheck, addr2) + require.Equal(t, acc1, res1) + require.Equal(t, acc2, res2) + + description := stake.NewDescription("foo_moniker", "", "", "") + declareCandidacyMsg := stake.NewMsgDeclareCandidacy( + addr1, priv1.PubKey(), bondCoin, description, + ) + + SignCheckDeliver(t, gapp, declareCandidacyMsg, []int64{0}, true, priv1) +} + +//____________________________________________________________________________________ + +func CheckBalance(t *testing.T, gapp *GaiaApp, addr sdk.Address, balExpected string) { + ctxDeliver := gapp.BaseApp.NewContext(false, abci.Header{}) + res2 := gapp.accountMapper.GetAccount(ctxDeliver, addr) + assert.Equal(t, balExpected, fmt.Sprintf("%v", res2.GetCoins())) +} + func genTx(msg sdk.Msg, seq []int64, priv ...crypto.PrivKeyEd25519) sdk.StdTx { sigs := make([]sdk.StdSignature, len(priv)) for i, p := range priv { @@ -428,9 +471,3 @@ func SignCheckDeliver(t *testing.T, gapp *GaiaApp, msg sdk.Msg, seq []int64, exp gapp.EndBlock(abci.RequestEndBlock{}) //gapp.Commit() } - -func CheckBalance(t *testing.T, gapp *GaiaApp, addr sdk.Address, balExpected string) { - ctxDeliver := gapp.BaseApp.NewContext(false, abci.Header{}) - res2 := gapp.accountMapper.GetAccount(ctxDeliver, addr) - assert.Equal(t, balExpected, fmt.Sprintf("%v", res2.GetCoins())) -} From abce3850ec69a9053b3d3003bab21843a211985e Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 7 Apr 2018 11:11:47 -0400 Subject: [PATCH 06/71] build fixes --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 4d21c61c5..78a5c9dcc 100644 --- a/Makefile +++ b/Makefile @@ -15,11 +15,11 @@ ci: get_tools get_vendor_deps build test_cover # This can be unified later, here for easy demos build: ifeq ($(OS),Windows_NT) - go build $(BUILD_FLAGS) -o build/gaiad.exe ./cmd/gaiad - go build $(BUILD_FLAGS) -o build/gaiacli.exe ./cmd/gaiacli + go build $(BUILD_FLAGS) -o build/gaiad.exe ./cmd/gaia/cmd/gaiad + go build $(BUILD_FLAGS) -o build/gaiacli.exe ./cmd/gaia/cmd/gaiacli else - go build $(BUILD_FLAGS) -o build/gaiad ./cmd/gaiad - go build $(BUILD_FLAGS) -o build/gaiacli ./cmd/gaiacli + go build $(BUILD_FLAGS) -o build/gaiad ./cmd/gaia/cmd/gaiad + go build $(BUILD_FLAGS) -o build/gaiacli ./cmd/gaia/cmd/gaiacli endif build_examples: From c90d62e03527462a83a374a740cabc1a87b33411 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 9 Apr 2018 23:08:00 -0400 Subject: [PATCH 07/71] rebase fixes --- cmd/gaia/app/app.go | 56 ++++++++------------ cmd/gaiacli/main.go | 88 ------------------------------- examples/basecoin/app/app_test.go | 3 +- 3 files changed, 22 insertions(+), 125 deletions(-) delete mode 100644 cmd/gaiacli/main.go diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 6cf67b0f2..49b5bc724 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -4,7 +4,6 @@ import ( "encoding/json" abci "github.com/tendermint/abci/types" - oldwire "github.com/tendermint/go-wire" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" "github.com/tendermint/tmlibs/log" @@ -52,10 +51,11 @@ func NewGaiaApp(logger log.Logger, dbs map[string]dbm.DB) *GaiaApp { } // define the accountMapper - app.accountMapper = auth.NewAccountMapperSealed( + app.accountMapper = auth.NewAccountMapper( + app.cdc, app.capKeyMainStore, // target store &auth.BaseAccount{}, // prototype - ) + ).Seal() // add handlers app.coinKeeper = bank.NewCoinKeeper(app.accountMapper) @@ -87,41 +87,27 @@ func NewGaiaApp(logger log.Logger, dbs map[string]dbm.DB) *GaiaApp { } // custom tx codec -// TODO: use new go-wire func MakeCodec() *wire.Codec { - const ( - msgTypeSend = 0x1 - msgTypeIssue = 0x2 - msgTypeIBCTransferMsg = 0x3 - msgTypeIBCReceiveMsg = 0x4 - msgDeclareCandidacy = 0x5 - msgEditCandidacy = 0x6 - msgDelegate = 0x7 - msgUnbond = 0x8 - ) - var _ = oldwire.RegisterInterface( - struct{ sdk.Msg }{}, - oldwire.ConcreteType{bank.SendMsg{}, msgTypeSend}, - oldwire.ConcreteType{bank.IssueMsg{}, msgTypeIssue}, - oldwire.ConcreteType{ibc.IBCTransferMsg{}, msgTypeIBCTransferMsg}, - oldwire.ConcreteType{ibc.IBCReceiveMsg{}, msgTypeIBCReceiveMsg}, - oldwire.ConcreteType{stake.MsgDeclareCandidacy{}, msgDeclareCandidacy}, - oldwire.ConcreteType{stake.MsgEditCandidacy{}, msgEditCandidacy}, - oldwire.ConcreteType{stake.MsgDelegate{}, msgDelegate}, - oldwire.ConcreteType{stake.MsgUnbond{}, msgUnbond}, - ) + var cdc = wire.NewCodec() - const accTypeApp = 0x1 - var _ = oldwire.RegisterInterface( - struct{ sdk.Account }{}, - oldwire.ConcreteType{&auth.BaseAccount{}, accTypeApp}, - ) - cdc := wire.NewCodec() + // Register Msgs + cdc.RegisterInterface((*sdk.Msg)(nil), nil) + cdc.RegisterConcrete(bank.SendMsg{}, "gaia/Send", nil) + cdc.RegisterConcrete(bank.IssueMsg{}, "gaia/Issue", nil) + cdc.RegisterConcrete(ibc.IBCTransferMsg{}, "gaia/IBCTransferMsg", nil) + cdc.RegisterConcrete(ibc.IBCReceiveMsg{}, "gaia/IBCReceiveMsg", nil) + cdc.RegisterConcrete(stake.MsgDeclareCandidacy{}, "gaia/MsgDeclareCandidacy", nil) + cdc.RegisterConcrete(stake.MsgEditCandidacy{}, "gaia/MsgEditCandidacy", nil) + cdc.RegisterConcrete(stake.MsgDelegate{}, "gaia/MsgDelegate", nil) + cdc.RegisterConcrete(stake.MsgUnbond{}, "gaia/MsgUnbond", nil) + + // Register AppAccount + cdc.RegisterInterface((*sdk.Account)(nil), nil) + cdc.RegisterConcrete(&auth.BaseAccount{}, "gaia/Account", nil) + + // Register crypto. + wire.RegisterCrypto(cdc) - // cdc.RegisterInterface((*sdk.Msg)(nil), nil) - // bank.RegisterWire(cdc) // Register bank.[SendMsg,IssueMsg] - // crypto.RegisterWire(cdc) // Register crypto.[PubKey,PrivKey,Signature] - // ibc.RegisterWire(cdc) // Register ibc.[IBCTransferMsg, IBCReceiveMsg] return cdc } diff --git a/cmd/gaiacli/main.go b/cmd/gaiacli/main.go deleted file mode 100644 index 1c71d7829..000000000 --- a/cmd/gaiacli/main.go +++ /dev/null @@ -1,88 +0,0 @@ -package main - -import ( - "os" - - "github.com/spf13/cobra" - - "github.com/tendermint/tmlibs/cli" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/keys" - "github.com/cosmos/cosmos-sdk/client/lcd" - "github.com/cosmos/cosmos-sdk/client/rpc" - "github.com/cosmos/cosmos-sdk/client/tx" - - "github.com/cosmos/cosmos-sdk/version" - authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands" - bankcmd "github.com/cosmos/cosmos-sdk/x/bank/commands" - ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/commands" - simplestakingcmd "github.com/cosmos/cosmos-sdk/x/simplestake/commands" - - "github.com/cosmos/cosmos-sdk/examples/basecoin/app" - "github.com/cosmos/cosmos-sdk/examples/basecoin/types" -) - -// TODO: distinguish from basecli - -// rootCmd is the entry point for this binary -var ( - rootCmd = &cobra.Command{ - Use: "gaiacli", - Short: "Gaia light-client", - } -) - -func main() { - // disable sorting - cobra.EnableCommandSorting = false - - // get the codec - cdc := app.MakeCodec() - - // TODO: setup keybase, viper object, etc. to be passed into - // the below functions and eliminate global vars, like we do - // with the cdc - - // add standard rpc, and tx commands - rpc.AddCommands(rootCmd) - rootCmd.AddCommand(client.LineBreak) - tx.AddCommands(rootCmd, cdc) - rootCmd.AddCommand(client.LineBreak) - - // add query/post commands (custom to binary) - rootCmd.AddCommand( - client.GetCommands( - authcmd.GetAccountCmd("main", cdc, types.GetAccountDecoder(cdc)), - )...) - rootCmd.AddCommand( - client.PostCommands( - bankcmd.SendTxCmd(cdc), - )...) - rootCmd.AddCommand( - client.PostCommands( - ibccmd.IBCTransferCmd(cdc), - )...) - rootCmd.AddCommand( - client.PostCommands( - ibccmd.IBCRelayCmd(cdc), - simplestakingcmd.BondTxCmd(cdc), - )...) - rootCmd.AddCommand( - client.PostCommands( - simplestakingcmd.UnbondTxCmd(cdc), - )...) - - // add proxy, version and key info - rootCmd.AddCommand( - client.LineBreak, - lcd.ServeCommand(cdc), - keys.Commands(), - client.LineBreak, - version.VersionCmd, - ) - - // prepare and add flags - executor := cli.PrepareMainCmd(rootCmd, "BC", os.ExpandEnv("$HOME/.gaiacli")) - executor.Execute() -} diff --git a/examples/basecoin/app/app_test.go b/examples/basecoin/app/app_test.go index 36461a8e3..bc1735dde 100644 --- a/examples/basecoin/app/app_test.go +++ b/examples/basecoin/app/app_test.go @@ -344,10 +344,9 @@ func TestQuizMsg(t *testing.T) { // Construct genesis state // Construct some genesis bytes to reflect basecoin/types/AppAccount - coins := sdk.Coins{} baseAcc := auth.BaseAccount{ Address: addr1, - Coins: coins, + Coins: nil, } acc1 := &types.AppAccount{baseAcc, "foobart"} From c63a5452064a8857b7c30d4b5179e15f0c06defe Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 10 Apr 2018 23:51:09 -0400 Subject: [PATCH 08/71] stake handler tests --- baseapp/baseapp.go | 7 ++-- cmd/gaia/app/app.go | 2 +- cmd/gaia/app/app_test.go | 80 +++++++++++++++++++++++++++++++++++++--- types/result.go | 2 +- x/stake/handler.go | 18 ++++----- x/stake/handler_test.go | 8 ++-- x/stake/keeper.go | 5 ++- x/stake/keeper_test.go | 24 ++++++------ 8 files changed, 107 insertions(+), 39 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 115748ca5..3eebb1eb4 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -322,9 +322,8 @@ func (app *BaseApp) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) { if result.IsOK() { app.valUpdates = append(app.valUpdates, result.ValidatorUpdates...) } else { - // Even though the Code is not OK, there will be some side - // effects, like those caused by fee deductions or sequence - // incrementations. + // Even though the Result.Code is not OK, there are still effects, + // namely fee deductions and sequence incrementing. } // Tell the blockchain engine (i.e. Tendermint). @@ -453,7 +452,7 @@ func (app *BaseApp) Commit() (res abci.ResponseCommit) { // Use the header from this latest block. app.setCheckState(header) - // Emtpy the Deliver state + // Empty the Deliver state app.deliverState = nil return abci.ResponseCommit{ diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 49b5bc724..0fa4f4181 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -76,7 +76,7 @@ func NewGaiaApp(logger log.Logger, dbs map[string]dbm.DB) *GaiaApp { app.MountStoreWithDB(app.capKeyStakeStore, sdk.StoreTypeIAVL, dbs["stake"]) // NOTE: Broken until #532 lands - //app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore, app.capKeyStakingStore) + //app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore, app.capKeyStakeStore) app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper)) err := app.LoadLatestVersion(app.capKeyMainStore) if err != nil { diff --git a/cmd/gaia/app/app_test.go b/cmd/gaia/app/app_test.go index 544249a8a..4ca1cd959 100644 --- a/cmd/gaia/app/app_test.go +++ b/cmd/gaia/app/app_test.go @@ -88,10 +88,10 @@ var ( func loggerAndDBs() (log.Logger, map[string]dbm.DB) { logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") dbs := map[string]dbm.DB{ - "main": dbm.NewMemDB(), - "acc": dbm.NewMemDB(), - "ibc": dbm.NewMemDB(), - "staking": dbm.NewMemDB(), + "main": dbm.NewMemDB(), + "acc": dbm.NewMemDB(), + "ibc": dbm.NewMemDB(), + "stake": dbm.NewMemDB(), } return logger, dbs } @@ -418,12 +418,59 @@ func TestStakeMsgs(t *testing.T) { require.Equal(t, acc1, res1) require.Equal(t, acc2, res2) + // Declare Candidacy + description := stake.NewDescription("foo_moniker", "", "", "") declareCandidacyMsg := stake.NewMsgDeclareCandidacy( addr1, priv1.PubKey(), bondCoin, description, ) - SignCheckDeliver(t, gapp, declareCandidacyMsg, []int64{0}, true, priv1) + + ctxDeliver := gapp.BaseApp.NewContext(false, abci.Header{}) + res1 = gapp.accountMapper.GetAccount(ctxDeliver, addr1) + require.Equal(t, genCoins.Minus(sdk.Coins{bondCoin}), res1.GetCoins()) + candidate, found := gapp.stakeKeeper.GetCandidate(ctxDeliver, addr1) + require.True(t, found) + require.Equal(t, candidate.Address, addr1) + + // Edit Candidacy + + description = stake.NewDescription("bar_moniker", "", "", "") + editCandidacyMsg := stake.NewMsgEditCandidacy( + addr1, description, + ) + SignDeliver(t, gapp, editCandidacyMsg, []int64{1}, true, priv1) + + candidate, found = gapp.stakeKeeper.GetCandidate(ctxDeliver, addr1) + require.True(t, found) + require.Equal(t, candidate.Description, description) + + // Delegate + + delegateMsg := stake.NewMsgDelegate( + addr2, addr1, bondCoin, + ) + SignDeliver(t, gapp, delegateMsg, []int64{0}, true, priv2) + + ctxDeliver = gapp.BaseApp.NewContext(false, abci.Header{}) + res2 = gapp.accountMapper.GetAccount(ctxDeliver, addr2) + require.Equal(t, genCoins.Minus(sdk.Coins{bondCoin}), res2.GetCoins()) + bond, found := gapp.stakeKeeper.GetDelegatorBond(ctxDeliver, addr2, addr1) + require.True(t, found) + require.Equal(t, bond.DelegatorAddr, addr2) + + // Unbond + + unbondMsg := stake.NewMsgUnbond( + addr2, addr1, "MAX", + ) + SignDeliver(t, gapp, unbondMsg, []int64{1}, true, priv2) + + ctxDeliver = gapp.BaseApp.NewContext(false, abci.Header{}) + res2 = gapp.accountMapper.GetAccount(ctxDeliver, addr2) + require.Equal(t, genCoins, res2.GetCoins()) + _, found = gapp.stakeKeeper.GetDelegatorBond(ctxDeliver, addr2, addr1) + require.False(t, found) } //____________________________________________________________________________________ @@ -452,6 +499,7 @@ func SignCheckDeliver(t *testing.T, gapp *GaiaApp, msg sdk.Msg, seq []int64, exp // Sign the tx tx := genTx(msg, seq, priv...) + // Run a Check res := gapp.Check(tx) if expPass { @@ -469,5 +517,27 @@ func SignCheckDeliver(t *testing.T, gapp *GaiaApp, msg sdk.Msg, seq []int64, exp require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) } gapp.EndBlock(abci.RequestEndBlock{}) + + // XXX fix code or add explaination as to why using commit breaks a bunch of these tests //gapp.Commit() } + +// XXX the only reason we are using Sign Deliver here is because the tests +// break on check tx the second time you use SignCheckDeliver in a test because +// the checktx state has not been updated likely because commit is not being +// called! +func SignDeliver(t *testing.T, gapp *GaiaApp, msg sdk.Msg, seq []int64, expPass bool, priv ...crypto.PrivKeyEd25519) { + + // Sign the tx + tx := genTx(msg, seq, priv...) + + // Simulate a Block + gapp.BeginBlock(abci.RequestBeginBlock{}) + res := gapp.Deliver(tx) + if expPass { + require.Equal(t, sdk.CodeOK, res.Code, res.Log) + } else { + require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + } + gapp.EndBlock(abci.RequestEndBlock{}) +} diff --git a/types/result.go b/types/result.go index 7b0c1a593..f4f7454e2 100644 --- a/types/result.go +++ b/types/result.go @@ -20,7 +20,7 @@ type Result struct { // GasWanted is the maximum units of work we allow this tx to perform. GasWanted int64 - // GasUsed is the amount of gas actually consumed. NOTE: not used. + // GasUsed is the amount of gas actually consumed. NOTE: unimplemented GasUsed int64 // Tx fee amount and denom. diff --git a/x/stake/handler.go b/x/stake/handler.go index 36b4509da..cf36cf10a 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -105,9 +105,6 @@ func handleMsgEditCandidacy(ctx sdk.Context, msg MsgEditCandidacy, k Keeper) sdk GasUsed: GasEditCandidacy, } } - if candidate.Status == Unbonded { //candidate has been withdrawn - return ErrBondNotNominated(k.codespace).Result() - } // XXX move to types // replace all editable fields (clients should autofill existing values) @@ -149,7 +146,7 @@ func delegate(ctx sdk.Context, k Keeper, delegatorAddr sdk.Address, bondAmt sdk.Coin, candidate Candidate) sdk.Error { // Get or create the delegator bond - bond, found := k.getDelegatorBond(ctx, delegatorAddr, candidate.Address) + bond, found := k.GetDelegatorBond(ctx, delegatorAddr, candidate.Address) if !found { bond = DelegatorBond{ DelegatorAddr: delegatorAddr, @@ -176,7 +173,7 @@ func delegate(ctx sdk.Context, k Keeper, delegatorAddr sdk.Address, func handleMsgUnbond(ctx sdk.Context, msg MsgUnbond, k Keeper) sdk.Result { // check if bond has any shares in it unbond - bond, found := k.getDelegatorBond(ctx, msg.DelegatorAddr, msg.CandidateAddr) + bond, found := k.GetDelegatorBond(ctx, msg.DelegatorAddr, msg.CandidateAddr) if !found { return ErrNoDelegatorForAddress(k.codespace).Result() } @@ -184,11 +181,7 @@ func handleMsgUnbond(ctx sdk.Context, msg MsgUnbond, k Keeper) sdk.Result { return ErrInsufficientFunds(k.codespace).Result() } - // test getting rational number from decimal provided - shares, err := sdk.NewRatFromDecimal(msg.Shares) - if err != nil { - return err.Result() - } + var shares sdk.Rat // test that there are enough shares to unbond if msg.Shares == "MAX" { @@ -196,6 +189,11 @@ func handleMsgUnbond(ctx sdk.Context, msg MsgUnbond, k Keeper) sdk.Result { return ErrNotEnoughBondShares(k.codespace, msg.Shares).Result() } } else { + var err sdk.Error + shares, err = sdk.NewRatFromDecimal(msg.Shares) + if err != nil { + return err.Result() + } if bond.Shares.LT(shares) { return ErrNotEnoughBondShares(k.codespace, msg.Shares).Result() } diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index 82b33cf2c..00ec07712 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -92,7 +92,7 @@ func TestIncrementsMsgDelegate(t *testing.T) { //Check that the accounts and the bond account have the appropriate values candidate, found := keeper.GetCandidate(ctx, candidateAddr) require.True(t, found) - bond, found := keeper.getDelegatorBond(ctx, delegatorAddr, candidateAddr) + bond, found := keeper.GetDelegatorBond(ctx, delegatorAddr, candidateAddr) require.True(t, found) expBond := int64(i+1) * bondAmount @@ -148,7 +148,7 @@ func TestIncrementsMsgUnbond(t *testing.T) { //Check that the accounts and the bond account have the appropriate values candidate, found = keeper.GetCandidate(ctx, candidateAddr) require.True(t, found) - bond, found := keeper.getDelegatorBond(ctx, delegatorAddr, candidateAddr) + bond, found := keeper.GetDelegatorBond(ctx, delegatorAddr, candidateAddr) require.True(t, found) expBond := initBond - int64(i+1)*unbondShares @@ -263,7 +263,7 @@ func TestMultipleMsgDelegate(t *testing.T) { require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) //Check that the account is bonded - bond, found := keeper.getDelegatorBond(ctx, delegatorAddr, candidateAddr) + bond, found := keeper.GetDelegatorBond(ctx, delegatorAddr, candidateAddr) require.True(t, found) require.NotNil(t, bond, "expected delegatee bond %d to exist", bond) } @@ -275,7 +275,7 @@ func TestMultipleMsgDelegate(t *testing.T) { require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) //Check that the account is unbonded - _, found := keeper.getDelegatorBond(ctx, delegatorAddr, candidateAddr) + _, found := keeper.GetDelegatorBond(ctx, delegatorAddr, candidateAddr) require.False(t, found) } } diff --git a/x/stake/keeper.go b/x/stake/keeper.go index 8b73e81db..c2b054eba 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -297,7 +297,8 @@ func (k Keeper) clearAccUpdateValidators(ctx sdk.Context) { //_____________________________________________________________________ -func (k Keeper) getDelegatorBond(ctx sdk.Context, +// load a delegator bong +func (k Keeper) GetDelegatorBond(ctx sdk.Context, delegatorAddr, candidateAddr sdk.Address) (bond DelegatorBond, found bool) { store := ctx.KVStore(k.storeKey) @@ -314,7 +315,7 @@ func (k Keeper) getDelegatorBond(ctx sdk.Context, } // load all bonds of a delegator -func (k Keeper) getDelegatorBonds(ctx sdk.Context, delegator sdk.Address, maxRetrieve int16) (bonds []DelegatorBond) { +func (k Keeper) GetDelegatorBonds(ctx sdk.Context, delegator sdk.Address, maxRetrieve int16) (bonds []DelegatorBond) { store := ctx.KVStore(k.storeKey) delegatorPrefixKey := GetDelegatorBondsKey(delegator, k.cdc) iterator := store.Iterator(subspace(delegatorPrefixKey)) //smallest to largest diff --git a/x/stake/keeper_test.go b/x/stake/keeper_test.go index e8d8e0594..9d6f69cc6 100644 --- a/x/stake/keeper_test.go +++ b/x/stake/keeper_test.go @@ -127,19 +127,19 @@ func TestBond(t *testing.T) { } // check the empty keeper first - _, found := keeper.getDelegatorBond(ctx, addrDels[0], addrVals[0]) + _, found := keeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0]) assert.False(t, found) // set and retrieve a record keeper.setDelegatorBond(ctx, bond1to1) - resBond, found := keeper.getDelegatorBond(ctx, addrDels[0], addrVals[0]) + resBond, found := keeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0]) assert.True(t, found) assert.True(t, bondsEqual(bond1to1, resBond)) // modify a records, save, and retrieve bond1to1.Shares = sdk.NewRat(99) keeper.setDelegatorBond(ctx, bond1to1) - resBond, found = keeper.getDelegatorBond(ctx, addrDels[0], addrVals[0]) + resBond, found = keeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0]) assert.True(t, found) assert.True(t, bondsEqual(bond1to1, resBond)) @@ -158,16 +158,16 @@ func TestBond(t *testing.T) { keeper.setDelegatorBond(ctx, bond2to3) // test all bond retrieve capabilities - resBonds := keeper.getDelegatorBonds(ctx, addrDels[0], 5) + resBonds := keeper.GetDelegatorBonds(ctx, addrDels[0], 5) require.Equal(t, 3, len(resBonds)) assert.True(t, bondsEqual(bond1to1, resBonds[0])) assert.True(t, bondsEqual(bond1to2, resBonds[1])) assert.True(t, bondsEqual(bond1to3, resBonds[2])) - resBonds = keeper.getDelegatorBonds(ctx, addrDels[0], 3) + resBonds = keeper.GetDelegatorBonds(ctx, addrDels[0], 3) require.Equal(t, 3, len(resBonds)) - resBonds = keeper.getDelegatorBonds(ctx, addrDels[0], 2) + resBonds = keeper.GetDelegatorBonds(ctx, addrDels[0], 2) require.Equal(t, 2, len(resBonds)) - resBonds = keeper.getDelegatorBonds(ctx, addrDels[1], 5) + resBonds = keeper.GetDelegatorBonds(ctx, addrDels[1], 5) require.Equal(t, 3, len(resBonds)) assert.True(t, bondsEqual(bond2to1, resBonds[0])) assert.True(t, bondsEqual(bond2to2, resBonds[1])) @@ -175,9 +175,9 @@ func TestBond(t *testing.T) { // delete a record keeper.removeDelegatorBond(ctx, bond2to3) - _, found = keeper.getDelegatorBond(ctx, addrDels[1], addrVals[2]) + _, found = keeper.GetDelegatorBond(ctx, addrDels[1], addrVals[2]) assert.False(t, found) - resBonds = keeper.getDelegatorBonds(ctx, addrDels[1], 5) + resBonds = keeper.GetDelegatorBonds(ctx, addrDels[1], 5) require.Equal(t, 2, len(resBonds)) assert.True(t, bondsEqual(bond2to1, resBonds[0])) assert.True(t, bondsEqual(bond2to2, resBonds[1])) @@ -185,11 +185,11 @@ func TestBond(t *testing.T) { // delete all the records from delegator 2 keeper.removeDelegatorBond(ctx, bond2to1) keeper.removeDelegatorBond(ctx, bond2to2) - _, found = keeper.getDelegatorBond(ctx, addrDels[1], addrVals[0]) + _, found = keeper.GetDelegatorBond(ctx, addrDels[1], addrVals[0]) assert.False(t, found) - _, found = keeper.getDelegatorBond(ctx, addrDels[1], addrVals[1]) + _, found = keeper.GetDelegatorBond(ctx, addrDels[1], addrVals[1]) assert.False(t, found) - resBonds = keeper.getDelegatorBonds(ctx, addrDels[1], 5) + resBonds = keeper.GetDelegatorBonds(ctx, addrDels[1], 5) require.Equal(t, 0, len(resBonds)) } From 068ca5e3e6318e109248bd797892ef8320bab7a8 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 11 Apr 2018 11:58:11 -0400 Subject: [PATCH 09/71] fix gaia init genesis creation int int --- cmd/gaia/app/app.go | 22 ++++++++++++++++++++++ cmd/gaia/cmd/gaiad/main.go | 12 ++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 0fa4f4181..792a6bbd9 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -179,3 +179,25 @@ func (ga *GenesisAccount) ToAccount() (acc *auth.BaseAccount) { Coins: ga.Coins.Sort(), } } + +// DefaultGenAppState expects two args: an account address +// and a coin denomination, and gives lots of coins to that address. +func DefaultGenAppState(args []string, addr sdk.Address, coinDenom string) (json.RawMessage, error) { + + accAuth := auth.NewBaseAccountWithAddress(addr) + accAuth.Coins = sdk.Coins{{"fermion", 100000}} + acc := NewGenesisAccount(&accAuth) + genaccs := []GenesisAccount{acc} + + genesisState := GenesisState{ + Accounts: genaccs, + StakeData: stake.GetGenesisJSON(), + } + + stateBytes, err := json.MarshalIndent(genesisState, "", "\t") + if err != nil { + return nil, err + } + + return stateBytes, nil +} diff --git a/cmd/gaia/cmd/gaiad/main.go b/cmd/gaia/cmd/gaiad/main.go index f966c446a..b84a4e20d 100644 --- a/cmd/gaia/cmd/gaiad/main.go +++ b/cmd/gaia/cmd/gaiad/main.go @@ -40,22 +40,22 @@ func generateApp(rootDir string, logger log.Logger) (abci.Application, error) { //if err != nil { //return nil, err //} - //dbStaking, err := dbm.NewGoLevelDB("gaia-staking", dataDir) + //dbStake, err := dbm.NewGoLevelDB("gaia-stake", dataDir) //if err != nil { //return nil, err //} //dbs := map[string]dbm.DB{ - //"main": dbMain, - //"acc": dbAcc, - //"ibc": dbIBC, - //"staking": dbStaking, + //"main": dbMain, + //"acc": dbAcc, + //"ibc": dbIBC, + //"stake": dbStake, //} //bapp := app.NewGaiaApp(logger, dbs) return bapp, nil } func main() { - server.AddCommands(rootCmd, server.DefaultGenAppState, generateApp, context) + server.AddCommands(rootCmd, app.DefaultGenAppState, generateApp, context) // prepare and add flags rootDir := os.ExpandEnv("$HOME/.gaiad") From 996cafe97223c6bda8e24f6e19e2837d4d393245 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 11 Apr 2018 13:27:36 -0400 Subject: [PATCH 10/71] register wire, stake changelog, stake genesis update --- CHANGELOG.md | 5 +++++ cmd/gaia/app/app.go | 18 +++++++----------- cmd/gaia/app/app_test.go | 2 +- x/bank/wire.go | 5 ++--- x/ibc/wire.go | 4 ++-- x/stake/handler.go | 12 +++--------- x/stake/handler_test.go | 9 --------- x/stake/test_common.go | 27 +++++---------------------- x/stake/wire.go | 9 +++++---- 9 files changed, 30 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 873824c48..2cfbe82dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,12 @@ BREAKING CHANGES * All module keepers now require a codespace, see basecoin or democoin for usage BUG FIXES +* Gaia now uses stake, ported from github.com/cosmos/gaia +FEATURES: + +* Add CacheContext +* Gaia stake commands include, DeclareCandidacy, EditCandidacy, Delegate, Unbond * MountStoreWithDB without providing a custom store works. ## 0.14.1 (April 9, 2018) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 792a6bbd9..eeb64a7a7 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -92,14 +92,10 @@ func MakeCodec() *wire.Codec { // Register Msgs cdc.RegisterInterface((*sdk.Msg)(nil), nil) - cdc.RegisterConcrete(bank.SendMsg{}, "gaia/Send", nil) - cdc.RegisterConcrete(bank.IssueMsg{}, "gaia/Issue", nil) - cdc.RegisterConcrete(ibc.IBCTransferMsg{}, "gaia/IBCTransferMsg", nil) - cdc.RegisterConcrete(ibc.IBCReceiveMsg{}, "gaia/IBCReceiveMsg", nil) - cdc.RegisterConcrete(stake.MsgDeclareCandidacy{}, "gaia/MsgDeclareCandidacy", nil) - cdc.RegisterConcrete(stake.MsgEditCandidacy{}, "gaia/MsgEditCandidacy", nil) - cdc.RegisterConcrete(stake.MsgDelegate{}, "gaia/MsgDelegate", nil) - cdc.RegisterConcrete(stake.MsgUnbond{}, "gaia/MsgUnbond", nil) + + ibc.RegisterWire(cdc) + bank.RegisterWire(cdc) + stake.RegisterWire(cdc) // Register AppAccount cdc.RegisterInterface((*sdk.Account)(nil), nil) @@ -155,8 +151,8 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci // State to Unmarshal type GenesisState struct { - Accounts []GenesisAccount `json:"accounts"` - StakeData json.RawMessage `json:"stake"` + Accounts []GenesisAccount `json:"accounts"` + StakeData stake.GenesisState `json:"stake"` } // GenesisAccount doesn't need pubkey or sequence @@ -191,7 +187,7 @@ func DefaultGenAppState(args []string, addr sdk.Address, coinDenom string) (json genesisState := GenesisState{ Accounts: genaccs, - StakeData: stake.GetGenesisJSON(), + StakeData: stake.GetDefaultGenesisState(), } stateBytes, err := json.MarshalIndent(genesisState, "", "\t") diff --git a/cmd/gaia/app/app_test.go b/cmd/gaia/app/app_test.go index 4ca1cd959..ea10cebc5 100644 --- a/cmd/gaia/app/app_test.go +++ b/cmd/gaia/app/app_test.go @@ -109,7 +109,7 @@ func setGenesis(gapp *GaiaApp, accs ...*auth.BaseAccount) error { genesisState := GenesisState{ Accounts: genaccs, - StakeData: stake.GetGenesisJSON(), + StakeData: stake.GetDefaultGenesisState(), } stateBytes, err := json.MarshalIndent(genesisState, "", "\t") diff --git a/x/bank/wire.go b/x/bank/wire.go index 846103a52..c53f06564 100644 --- a/x/bank/wire.go +++ b/x/bank/wire.go @@ -6,7 +6,6 @@ import ( // Register concrete types on wire codec func RegisterWire(cdc *wire.Codec) { - // TODO include option to always include prefix bytes. - //cdc.RegisterConcrete(SendMsg{}, "github.com/cosmos/cosmos-sdk/bank/SendMsg", nil) - //cdc.RegisterConcrete(IssueMsg{}, "github.com/cosmos/cosmos-sdk/bank/IssueMsg", nil) + cdc.RegisterConcrete(SendMsg{}, "cosmos-sdk/Send", nil) + cdc.RegisterConcrete(IssueMsg{}, "cosmos-sdk/Issue", nil) } diff --git a/x/ibc/wire.go b/x/ibc/wire.go index 91e6d88bb..f5644acc5 100644 --- a/x/ibc/wire.go +++ b/x/ibc/wire.go @@ -6,6 +6,6 @@ import ( // Register concrete types on wire codec func RegisterWire(cdc *wire.Codec) { - //cdc.RegisterConcrete(IBCTransferMsg{}, "github.com/cosmos/cosmos-sdk/x/ibc/IBCTransferMsg", nil) - //cdc.RegisterConcrete(IBCReceiveMsg{}, "github.com/cosmos/cosmos-sdk/x/ibc/IBCReceiveMsg", nil) + cdc.RegisterConcrete(IBCTransferMsg{}, "cosmos-sdk/IBCTransferMsg", nil) + cdc.RegisterConcrete(IBCReceiveMsg{}, "cosmos-sdk/IBCReceiveMsg", nil) } diff --git a/x/stake/handler.go b/x/stake/handler.go index cf36cf10a..84eeca3c4 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -2,7 +2,6 @@ package stake import ( "bytes" - "encoding/json" sdk "github.com/cosmos/cosmos-sdk/types" abci "github.com/tendermint/abci/types" @@ -50,14 +49,9 @@ func NewEndBlocker(k Keeper) sdk.EndBlocker { //_____________________________________________________________________ // InitGenesis - store genesis parameters -func InitGenesis(ctx sdk.Context, k Keeper, data json.RawMessage) error { - var state GenesisState - if err := json.Unmarshal(data, &state); err != nil { - return err - } - k.setPool(ctx, state.Pool) - k.setParams(ctx, state.Params) - return nil +func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) { + k.setPool(ctx, data.Pool) + k.setParams(ctx, data.Params) } //_____________________________________________________________________ diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index 00ec07712..538c664e9 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -12,15 +12,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func TestInitGenesis(t *testing.T) { - ctx, _, keeper := createTestInput(t, false, 0) - encoded := GetGenesisJSON() - err := InitGenesis(ctx, keeper, encoded) - require.Nil(t, err) - require.Equal(t, keeper.GetPool(ctx), initialPool()) - require.Equal(t, keeper.GetParams(ctx), defaultParams()) -} - //______________________________________________________________________ func newTestMsgDeclareCandidacy(address sdk.Address, pubKey crypto.PubKey, amt int64) MsgDeclareCandidacy { diff --git a/x/stake/test_common.go b/x/stake/test_common.go index 5b0bc97e0..75781777a 100644 --- a/x/stake/test_common.go +++ b/x/stake/test_common.go @@ -2,7 +2,6 @@ package stake import ( "encoding/hex" - "encoding/json" "testing" "github.com/stretchr/testify/require" @@ -77,27 +76,11 @@ func initialPool() Pool { } // get raw genesis raw message for testing -func GetGenesisJSON() json.RawMessage { - jsonStr := `{ - "params": { - "inflation_rate_change": {"num": 13, "denom": 100}, - "inflation_max": {"num": 20, "denom": 100}, - "inflation_min": {"num": 7, "denom": 100}, - "goal_bonded": {"num": 67, "denom": 100}, - "max_validators": 100, - "bond_denom": "fermion" - }, - "pool": { - "total_supply": 0, - "bonded_shares": {"num": 0, "denom": 1}, - "unbonded_shares": {"num": 0, "denom": 1}, - "bonded_pool": 0, - "unbonded_pool": 0, - "inflation_last_time": 0, - "inflation": {"num": 7, "denom": 100} - } -}` - return json.RawMessage(jsonStr) +func GetDefaultGenesisState() GenesisState { + return GenesisState{ + Pool: initialPool(), + Params: defaultParams(), + } } // XXX reference the common declaration of this function diff --git a/x/stake/wire.go b/x/stake/wire.go index f444ce14e..e99c621fa 100644 --- a/x/stake/wire.go +++ b/x/stake/wire.go @@ -4,9 +4,10 @@ import ( "github.com/cosmos/cosmos-sdk/wire" ) -// TODO complete when go-amino is ported +// Register concrete types on wire codec func RegisterWire(cdc *wire.Codec) { - // TODO include option to always include prefix bytes. - //cdc.RegisterConcrete(SendMsg{}, "cosmos-sdk/SendMsg", nil) - //cdc.RegisterConcrete(IssueMsg{}, "cosmos-sdk/IssueMsg", nil) + cdc.RegisterConcrete(MsgDeclareCandidacy{}, "cosmos-sdk/MsgDeclareCandidacy", nil) + cdc.RegisterConcrete(MsgEditCandidacy{}, "cosmos-sdk/MsgEditCandidacy", nil) + cdc.RegisterConcrete(MsgDelegate{}, "cosmos-sdk/MsgDelegate", nil) + cdc.RegisterConcrete(MsgUnbond{}, "cosmos-sdk/MsgUnbond", nil) } From 8ab77e2ab5cea35f144103ef1c343d9183be450a Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 12 Apr 2018 22:51:14 -0400 Subject: [PATCH 11/71] started gaia go-bash cli testing --- cmd/gaia/cmd/app_test.go | 42 ++++++++++++++++++++++++++++++++++ tests/gobash.go | 49 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 cmd/gaia/cmd/app_test.go create mode 100644 tests/gobash.go diff --git a/cmd/gaia/cmd/app_test.go b/cmd/gaia/cmd/app_test.go new file mode 100644 index 000000000..98cf2a0d2 --- /dev/null +++ b/cmd/gaia/cmd/app_test.go @@ -0,0 +1,42 @@ +package common + +import ( + "encoding/json" + "strings" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/tests" +) + +func TestGaiaCLI(t *testing.T) { + + _, out := tests.ExecuteT(t, "gaiad init") + var initRes map[string]interface{} + outCut := "{" + strings.SplitN(out, "{", 2)[1] + err := json.Unmarshal([]byte(outCut), &initRes) + require.NoError(t, err, "out %v outCut %v err %v", out, outCut, err) + masterKey := (initRes["secret"]).(string) + _ = masterKey + + //wc1, _ := tests.GoExecuteT(t, "gaiacli keys add foo --recover") + //time.Sleep(time.Second) + //_, err = wc1.Write([]byte("1234567890\n")) + //time.Sleep(time.Second) + //_, err = wc1.Write([]byte(masterKey + "\n")) + //time.Sleep(time.Second) + //out = <-outChan + //wc1.Close() + //fmt.Println(out) + + //_, out = tests.ExecuteT(t, "gaiacli keys show foo") + //fooAddr := strings.TrimLeft(out, "foo\t") + + //wc2, _ := tests.GoExecuteT(t, "gaiad start") + //defer wc2.Close() + //time.Sleep(time.Second) + + //_, out = tests.ExecuteT(t, fmt.Sprintf("gaiacli account %v", fooAddr)) + //fmt.Println(fooAddr) +} diff --git a/tests/gobash.go b/tests/gobash.go new file mode 100644 index 000000000..edef7ccd5 --- /dev/null +++ b/tests/gobash.go @@ -0,0 +1,49 @@ +package tests + +import ( + "io" + "os/exec" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func getCmd(t *testing.T, command string) *exec.Cmd { + + //split command into command and args + split := strings.Split(command, " ") + require.True(t, len(split) > 0, "no command provided") + + var cmd *exec.Cmd + if len(split) == 1 { + cmd = exec.Command(split[0]) + } else { + cmd = exec.Command(split[0], split[1:]...) + } + return cmd +} + +// Execute the command, return standard output and error +func ExecuteT(t *testing.T, command string) (pipe io.WriteCloser, out string) { + cmd := getCmd(t, command) + pipe, err := cmd.StdinPipe() + require.NoError(t, err) + bz, err := cmd.CombinedOutput() + require.NoError(t, err) + out = strings.Trim(string(bz), "\n") //trim any new lines + return pipe, out +} + +// Asynchronously execute the command, return standard output and error +func GoExecuteT(t *testing.T, command string) (pipe io.WriteCloser, outChan chan string) { + cmd := getCmd(t, command) + pipe, err := cmd.StdinPipe() + require.NoError(t, err) + go func() { + bz, err := cmd.CombinedOutput() + require.NoError(t, err) + outChan <- strings.Trim(string(bz), "\n") //trim any new lines + }() + return pipe, outChan +} From 3ab032e1c671e885b9d2d48260b9518b9216b131 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 13 Apr 2018 16:08:06 -0400 Subject: [PATCH 12/71] cli testing --- cmd/gaia/cmd/app_test.go | 42 -------------------- cmd/gaia/cmd/cli_test.go | 83 ++++++++++++++++++++++++++++++++++++++++ tests/gobash.go | 25 ++++++------ 3 files changed, 97 insertions(+), 53 deletions(-) delete mode 100644 cmd/gaia/cmd/app_test.go create mode 100644 cmd/gaia/cmd/cli_test.go diff --git a/cmd/gaia/cmd/app_test.go b/cmd/gaia/cmd/app_test.go deleted file mode 100644 index 98cf2a0d2..000000000 --- a/cmd/gaia/cmd/app_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package common - -import ( - "encoding/json" - "strings" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/tests" -) - -func TestGaiaCLI(t *testing.T) { - - _, out := tests.ExecuteT(t, "gaiad init") - var initRes map[string]interface{} - outCut := "{" + strings.SplitN(out, "{", 2)[1] - err := json.Unmarshal([]byte(outCut), &initRes) - require.NoError(t, err, "out %v outCut %v err %v", out, outCut, err) - masterKey := (initRes["secret"]).(string) - _ = masterKey - - //wc1, _ := tests.GoExecuteT(t, "gaiacli keys add foo --recover") - //time.Sleep(time.Second) - //_, err = wc1.Write([]byte("1234567890\n")) - //time.Sleep(time.Second) - //_, err = wc1.Write([]byte(masterKey + "\n")) - //time.Sleep(time.Second) - //out = <-outChan - //wc1.Close() - //fmt.Println(out) - - //_, out = tests.ExecuteT(t, "gaiacli keys show foo") - //fooAddr := strings.TrimLeft(out, "foo\t") - - //wc2, _ := tests.GoExecuteT(t, "gaiad start") - //defer wc2.Close() - //time.Sleep(time.Second) - - //_, out = tests.ExecuteT(t, fmt.Sprintf("gaiacli account %v", fooAddr)) - //fmt.Println(fooAddr) -} diff --git a/cmd/gaia/cmd/cli_test.go b/cmd/gaia/cmd/cli_test.go new file mode 100644 index 000000000..db5e272c1 --- /dev/null +++ b/cmd/gaia/cmd/cli_test.go @@ -0,0 +1,83 @@ +package common + +import ( + "encoding/json" + "fmt" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/tests" +) + +func TestGaiaCLI(t *testing.T) { + + // clear genesis/keys + _ = tests.ExecuteT(t, "gaiad unsafe_reset_all") + _, wc0, _ := tests.GoExecuteT(t, "gaiacli keys delete foo") + defer wc0.Close() + _, err := wc0.Write([]byte("1234567890\n")) + require.NoError(t, err) + _, wc1, _ := tests.GoExecuteT(t, "gaiacli keys delete bar") + defer wc1.Close() + _, err = wc1.Write([]byte("1234567890\n")) + require.NoError(t, err) + time.Sleep(time.Second) + + // init genesis get master key + out := tests.ExecuteT(t, "gaiad init") + var initRes map[string]interface{} + outCut := "{" + strings.SplitN(out, "{", 2)[1] + err = json.Unmarshal([]byte(outCut), &initRes) + require.NoError(t, err, "out %v outCut %v err %v", out, outCut, err) + masterKey := (initRes["secret"]).(string) + chainID := (initRes["chain_id"]).(string) + + // start gaiad server + _, wc2, _ := tests.GoExecuteT(t, "gaiad start") + defer wc2.Close() + time.Sleep(time.Second) + + // add the master key + _, wc3, _ := tests.GoExecuteT(t, "gaiacli keys add foo --recover") + defer wc3.Close() + _, err = wc3.Write([]byte("1234567890\n")) + require.NoError(t, err) + _, err = wc3.Write([]byte(masterKey + "\n")) + require.NoError(t, err) + time.Sleep(time.Second) + + // add a secondary key + _, wc4, _ := tests.GoExecuteT(t, "gaiacli keys add bar") + time.Sleep(time.Second * 5) + _, err = wc4.Write([]byte("1234567890\n")) + require.NoError(t, err) + time.Sleep(time.Second * 5) + + // get addresses + out = tests.ExecuteT(t, "gaiacli keys show foo") + fooAddr := strings.TrimLeft(out, "foo\t") + out = tests.ExecuteT(t, "gaiacli keys show bar") + barAddr := strings.TrimLeft(out, "bar\t") + fmt.Printf("debug barAddr: %v\n", barAddr) + + // send money from foo to bar + cmdStr := fmt.Sprintf("gaiacli send --sequence=0 --chain-id=%v --amount=10fermion --to=%v --name=foo", chainID, barAddr) + _, wc5, rc5 := tests.GoExecuteT(t, cmdStr) + _, err = wc5.Write([]byte("1234567890\n")) + require.NoError(t, err) + fmt.Printf("debug outCh: %v\n", out) + time.Sleep(time.Second) + bz := make([]byte, 1000000) + rc5.Read(bz) + fmt.Printf("debug ex: %v\n", string(bz)) + + // verify money sent to bar + time.Sleep(time.Second) + out = tests.ExecuteT(t, fmt.Sprintf("gaiacli account %v", fooAddr)) + fmt.Printf("debug out: %v\n", out) + out = tests.ExecuteT(t, fmt.Sprintf("gaiacli account %v", barAddr)) + require.Fail(t, "debug out: %v\n", out) +} diff --git a/tests/gobash.go b/tests/gobash.go index edef7ccd5..8095a7d90 100644 --- a/tests/gobash.go +++ b/tests/gobash.go @@ -2,6 +2,7 @@ package tests import ( "io" + "os" "os/exec" "strings" "testing" @@ -25,25 +26,27 @@ func getCmd(t *testing.T, command string) *exec.Cmd { } // Execute the command, return standard output and error -func ExecuteT(t *testing.T, command string) (pipe io.WriteCloser, out string) { +func ExecuteT(t *testing.T, command string) (out string) { cmd := getCmd(t, command) - pipe, err := cmd.StdinPipe() - require.NoError(t, err) bz, err := cmd.CombinedOutput() - require.NoError(t, err) + require.NoError(t, err, string(bz)) out = strings.Trim(string(bz), "\n") //trim any new lines - return pipe, out + return out } // Asynchronously execute the command, return standard output and error -func GoExecuteT(t *testing.T, command string) (pipe io.WriteCloser, outChan chan string) { +func GoExecuteT(t *testing.T, command string) (proc *os.Process, pipeIn io.WriteCloser, pipeOut io.ReadCloser) { cmd := getCmd(t, command) - pipe, err := cmd.StdinPipe() + pipeIn, err := cmd.StdinPipe() require.NoError(t, err) + pipeOut, err = cmd.StdoutPipe() + require.NoError(t, err) + go func() { - bz, err := cmd.CombinedOutput() - require.NoError(t, err) - outChan <- strings.Trim(string(bz), "\n") //trim any new lines + cmd.Start() + //bz, _ := cmd.CombinedOutput() + //require.NoError(t, err, string(bz)) + //outChan <- strings.Trim(string(bz), "\n") //trim any new lines }() - return pipe, outChan + return nil, pipeIn, pipeOut } From ebb2faabe07576584fd416ae2af6d6ee14947409 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 13 Apr 2018 19:45:26 -0400 Subject: [PATCH 13/71] go-bash working --- cmd/gaia/cmd/cli_test.go | 92 +++++++++++++++++++++++----------------- tests/gobash.go | 10 +++-- 2 files changed, 58 insertions(+), 44 deletions(-) diff --git a/cmd/gaia/cmd/cli_test.go b/cmd/gaia/cmd/cli_test.go index db5e272c1..6d3e9db11 100644 --- a/cmd/gaia/cmd/cli_test.go +++ b/cmd/gaia/cmd/cli_test.go @@ -3,81 +3,93 @@ package common import ( "encoding/json" "fmt" + "io" "strings" "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/tests" + "github.com/cosmos/cosmos-sdk/x/auth" ) +func password(t *testing.T, wc io.WriteCloser) { + _, err := wc.Write([]byte("1234567890\n")) + require.NoError(t, err) +} + func TestGaiaCLI(t *testing.T) { // clear genesis/keys - _ = tests.ExecuteT(t, "gaiad unsafe_reset_all") - _, wc0, _ := tests.GoExecuteT(t, "gaiacli keys delete foo") - defer wc0.Close() - _, err := wc0.Write([]byte("1234567890\n")) - require.NoError(t, err) - _, wc1, _ := tests.GoExecuteT(t, "gaiacli keys delete bar") - defer wc1.Close() - _, err = wc1.Write([]byte("1234567890\n")) - require.NoError(t, err) - time.Sleep(time.Second) + tests.ExecuteT(t, "gaiad unsafe_reset_all") + cmd, wc0, _ := tests.GoExecuteT(t, "gaiacli keys delete foo") + password(t, wc0) + cmd.Wait() + cmd, wc1, _ := tests.GoExecuteT(t, "gaiacli keys delete bar") + password(t, wc1) + cmd.Wait() // init genesis get master key out := tests.ExecuteT(t, "gaiad init") var initRes map[string]interface{} - outCut := "{" + strings.SplitN(out, "{", 2)[1] - err = json.Unmarshal([]byte(outCut), &initRes) + outCut := "{" + strings.SplitN(out, "{", 2)[1] // weird I'm sorry + err := json.Unmarshal([]byte(outCut), &initRes) require.NoError(t, err, "out %v outCut %v err %v", out, outCut, err) masterKey := (initRes["secret"]).(string) chainID := (initRes["chain_id"]).(string) + servAddr := server.FreeTCPAddr(t) + gaiacliFlags := fmt.Sprintf("--node=%v --chain-id=%v", servAddr, chainID) + // start gaiad server - _, wc2, _ := tests.GoExecuteT(t, "gaiad start") - defer wc2.Close() - time.Sleep(time.Second) + cmd, _, _ = tests.GoExecuteT(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr)) + defer cmd.Process.Kill() // add the master key - _, wc3, _ := tests.GoExecuteT(t, "gaiacli keys add foo --recover") - defer wc3.Close() - _, err = wc3.Write([]byte("1234567890\n")) - require.NoError(t, err) + cmd, wc3, _ := tests.GoExecuteT(t, "gaiacli keys add foo --recover") + password(t, wc3) _, err = wc3.Write([]byte(masterKey + "\n")) require.NoError(t, err) - time.Sleep(time.Second) + cmd.Wait() // add a secondary key - _, wc4, _ := tests.GoExecuteT(t, "gaiacli keys add bar") - time.Sleep(time.Second * 5) - _, err = wc4.Write([]byte("1234567890\n")) - require.NoError(t, err) - time.Sleep(time.Second * 5) + cmd, wc4, _ := tests.GoExecuteT(t, "gaiacli keys add bar") + password(t, wc4) + cmd.Wait() // get addresses out = tests.ExecuteT(t, "gaiacli keys show foo") fooAddr := strings.TrimLeft(out, "foo\t") out = tests.ExecuteT(t, "gaiacli keys show bar") barAddr := strings.TrimLeft(out, "bar\t") - fmt.Printf("debug barAddr: %v\n", barAddr) // send money from foo to bar - cmdStr := fmt.Sprintf("gaiacli send --sequence=0 --chain-id=%v --amount=10fermion --to=%v --name=foo", chainID, barAddr) - _, wc5, rc5 := tests.GoExecuteT(t, cmdStr) - _, err = wc5.Write([]byte("1234567890\n")) - require.NoError(t, err) - fmt.Printf("debug outCh: %v\n", out) - time.Sleep(time.Second) - bz := make([]byte, 1000000) - rc5.Read(bz) - fmt.Printf("debug ex: %v\n", string(bz)) + cmdStr := fmt.Sprintf("gaiacli send %v --sequence=0 --amount=10fermion --to=%v --name=foo", gaiacliFlags, barAddr) + cmd, wc5, _ := tests.GoExecuteT(t, cmdStr) + password(t, wc5) + cmd.Wait() + time.Sleep(time.Second * 3) // waiting for some blocks to pass // verify money sent to bar - time.Sleep(time.Second) - out = tests.ExecuteT(t, fmt.Sprintf("gaiacli account %v", fooAddr)) - fmt.Printf("debug out: %v\n", out) - out = tests.ExecuteT(t, fmt.Sprintf("gaiacli account %v", barAddr)) - require.Fail(t, "debug out: %v\n", out) + out = tests.ExecuteT(t, fmt.Sprintf("gaiacli account %v %v", barAddr, gaiacliFlags)) + barAcc := unmarshalBaseAccount(t, out) + assert.Equal(t, int64(10), barAcc.GetCoins().AmountOf("fermion")) + + out = tests.ExecuteT(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, gaiacliFlags)) + fooAcc := unmarshalBaseAccount(t, out) + assert.Equal(t, int64(99990), fooAcc.GetCoins().AmountOf("fermion")) +} + +func unmarshalBaseAccount(t *testing.T, raw string) auth.BaseAccount { + var initRes map[string]json.RawMessage + err := json.Unmarshal([]byte(raw), &initRes) + require.NoError(t, err, "raw %v, err %v", raw, err) + value := initRes["value"] + var acc auth.BaseAccount + _ = json.Unmarshal(value, &acc) //XXX pubkey can't be decoded go amino issue + require.NoError(t, err, "value %v, err %v", string(value), err) + return acc } diff --git a/tests/gobash.go b/tests/gobash.go index 8095a7d90..5a177db94 100644 --- a/tests/gobash.go +++ b/tests/gobash.go @@ -2,10 +2,10 @@ package tests import ( "io" - "os" "os/exec" "strings" "testing" + "time" "github.com/stretchr/testify/require" ) @@ -31,12 +31,13 @@ func ExecuteT(t *testing.T, command string) (out string) { bz, err := cmd.CombinedOutput() require.NoError(t, err, string(bz)) out = strings.Trim(string(bz), "\n") //trim any new lines + time.Sleep(time.Second) return out } // Asynchronously execute the command, return standard output and error -func GoExecuteT(t *testing.T, command string) (proc *os.Process, pipeIn io.WriteCloser, pipeOut io.ReadCloser) { - cmd := getCmd(t, command) +func GoExecuteT(t *testing.T, command string) (cmd *exec.Cmd, pipeIn io.WriteCloser, pipeOut io.ReadCloser) { + cmd = getCmd(t, command) pipeIn, err := cmd.StdinPipe() require.NoError(t, err) pipeOut, err = cmd.StdoutPipe() @@ -48,5 +49,6 @@ func GoExecuteT(t *testing.T, command string) (proc *os.Process, pipeIn io.Write //require.NoError(t, err, string(bz)) //outChan <- strings.Trim(string(bz), "\n") //trim any new lines }() - return nil, pipeIn, pipeOut + time.Sleep(time.Second) + return cmd, pipeIn, pipeOut } From 59f86b42516d3102459886608968f3a8b6a1ce92 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 14 Apr 2018 03:16:49 -0400 Subject: [PATCH 14/71] interim borken --- cmd/gaia/cmd/cli_test.go | 106 ++++++++++++++++++++------------------- tests/gobash.go | 8 +-- 2 files changed, 56 insertions(+), 58 deletions(-) diff --git a/cmd/gaia/cmd/cli_test.go b/cmd/gaia/cmd/cli_test.go index 6d3e9db11..d2e86d7f7 100644 --- a/cmd/gaia/cmd/cli_test.go +++ b/cmd/gaia/cmd/cli_test.go @@ -3,7 +3,6 @@ package common import ( "encoding/json" "fmt" - "io" "strings" "testing" "time" @@ -16,77 +15,82 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth" ) -func password(t *testing.T, wc io.WriteCloser) { - _, err := wc.Write([]byte("1234567890\n")) - require.NoError(t, err) -} - func TestGaiaCLI(t *testing.T) { - // clear genesis/keys tests.ExecuteT(t, "gaiad unsafe_reset_all") - cmd, wc0, _ := tests.GoExecuteT(t, "gaiacli keys delete foo") - password(t, wc0) - cmd.Wait() - cmd, wc1, _ := tests.GoExecuteT(t, "gaiacli keys delete bar") - password(t, wc1) - cmd.Wait() - - // init genesis get master key - out := tests.ExecuteT(t, "gaiad init") - var initRes map[string]interface{} - outCut := "{" + strings.SplitN(out, "{", 2)[1] // weird I'm sorry - err := json.Unmarshal([]byte(outCut), &initRes) - require.NoError(t, err, "out %v outCut %v err %v", out, outCut, err) - masterKey := (initRes["secret"]).(string) - chainID := (initRes["chain_id"]).(string) + pass := "1234567890" + executeWrite(t, "gaiacli keys delete foo", pass) + executeWrite(t, "gaiacli keys delete bar", pass) + masterKey, chainID := executeInit(t, "gaiad init") + // get a free port, also setup some common flags servAddr := server.FreeTCPAddr(t) - gaiacliFlags := fmt.Sprintf("--node=%v --chain-id=%v", servAddr, chainID) + flags := fmt.Sprintf("--node=%v --chain-id=%v", servAddr, chainID) // start gaiad server - cmd, _, _ = tests.GoExecuteT(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr)) + cmd, _, _ := tests.GoExecuteT(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr)) defer cmd.Process.Kill() + time.Sleep(time.Second) // waiting for some blocks to pass - // add the master key + //executeWrite(t, "gaiacli keys add foo --recover", pass, masterKey) cmd, wc3, _ := tests.GoExecuteT(t, "gaiacli keys add foo --recover") - password(t, wc3) + time.Sleep(time.Second) // waiting for some blocks to pass + _, err := wc3.Write([]byte("1234567890\n")) + require.NoError(t, err) _, err = wc3.Write([]byte(masterKey + "\n")) require.NoError(t, err) cmd.Wait() + time.Sleep(time.Second * 5) // waiting for some blocks to pass + fooAddr := executeGetAddr(t, "gaiacli keys show foo") + panic(fmt.Sprintf("debug fooAddr: %v\n", fooAddr)) - // add a secondary key - cmd, wc4, _ := tests.GoExecuteT(t, "gaiacli keys add bar") - password(t, wc4) - cmd.Wait() - - // get addresses - out = tests.ExecuteT(t, "gaiacli keys show foo") - fooAddr := strings.TrimLeft(out, "foo\t") - out = tests.ExecuteT(t, "gaiacli keys show bar") - barAddr := strings.TrimLeft(out, "bar\t") - - // send money from foo to bar - cmdStr := fmt.Sprintf("gaiacli send %v --sequence=0 --amount=10fermion --to=%v --name=foo", gaiacliFlags, barAddr) - cmd, wc5, _ := tests.GoExecuteT(t, cmdStr) - password(t, wc5) - cmd.Wait() + executeWrite(t, "gaiacli keys add bar", pass) + barAddr := executeGetAddr(t, "gaiacli keys show bar") + executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10fermion --to=%v --name=foo", flags, barAddr), pass) time.Sleep(time.Second * 3) // waiting for some blocks to pass - // verify money sent to bar - out = tests.ExecuteT(t, fmt.Sprintf("gaiacli account %v %v", barAddr, gaiacliFlags)) - barAcc := unmarshalBaseAccount(t, out) + barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barAddr, flags)) assert.Equal(t, int64(10), barAcc.GetCoins().AmountOf("fermion")) - - out = tests.ExecuteT(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, gaiacliFlags)) - fooAcc := unmarshalBaseAccount(t, out) + fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) assert.Equal(t, int64(99990), fooAcc.GetCoins().AmountOf("fermion")) + + // declare candidacy + //executeWrite(t, "gaiacli declare-candidacy -", pass) } -func unmarshalBaseAccount(t *testing.T, raw string) auth.BaseAccount { +func executeWrite(t *testing.T, cmdStr string, writes ...string) { + cmd, wc, _ := tests.GoExecuteT(t, cmdStr) + for _, write := range writes { + _, err := wc.Write([]byte(write + "\n")) + require.NoError(t, err) + } + cmd.Wait() +} + +func executeInit(t *testing.T, cmdStr string) (masterKey, chainID string) { + tests.GoExecuteT(t, cmdStr) + out := tests.ExecuteT(t, cmdStr) + outCut := "{" + strings.SplitN(out, "{", 2)[1] // weird I'm sorry + var initRes map[string]json.RawMessage - err := json.Unmarshal([]byte(raw), &initRes) - require.NoError(t, err, "raw %v, err %v", raw, err) + err := json.Unmarshal([]byte(outCut), &initRes) + require.NoError(t, err, "out %v outCut %v err %v", out, outCut, err) + masterKey = string(initRes["secret"]) + chainID = string(initRes["chain_id"]) + return +} + +func executeGetAddr(t *testing.T, cmdStr string) (addr string) { + out := tests.ExecuteT(t, cmdStr) + name := strings.SplitN(cmdStr, " show ", 2)[1] + return strings.TrimLeft(out, name+"\t") +} + +func executeGetAccount(t *testing.T, cmdStr string) auth.BaseAccount { + out := tests.ExecuteT(t, cmdStr) + var initRes map[string]json.RawMessage + err := json.Unmarshal([]byte(out), &initRes) + require.NoError(t, err, "out %v, err %v", out, err) value := initRes["value"] var acc auth.BaseAccount _ = json.Unmarshal(value, &acc) //XXX pubkey can't be decoded go amino issue diff --git a/tests/gobash.go b/tests/gobash.go index 5a177db94..12b3da085 100644 --- a/tests/gobash.go +++ b/tests/gobash.go @@ -42,13 +42,7 @@ func GoExecuteT(t *testing.T, command string) (cmd *exec.Cmd, pipeIn io.WriteClo require.NoError(t, err) pipeOut, err = cmd.StdoutPipe() require.NoError(t, err) - - go func() { - cmd.Start() - //bz, _ := cmd.CombinedOutput() - //require.NoError(t, err, string(bz)) - //outChan <- strings.Trim(string(bz), "\n") //trim any new lines - }() + go cmd.Start() time.Sleep(time.Second) return cmd, pipeIn, pipeOut } From 158e9dd12d2e5b81a0dc88bd7bd525e9786b9915 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 14 Apr 2018 13:06:54 -0400 Subject: [PATCH 15/71] fixed cli tests --- cmd/gaia/cmd/cli_test.go | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/cmd/gaia/cmd/cli_test.go b/cmd/gaia/cmd/cli_test.go index d2e86d7f7..eb31aaad1 100644 --- a/cmd/gaia/cmd/cli_test.go +++ b/cmd/gaia/cmd/cli_test.go @@ -30,21 +30,11 @@ func TestGaiaCLI(t *testing.T) { // start gaiad server cmd, _, _ := tests.GoExecuteT(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr)) defer cmd.Process.Kill() - time.Sleep(time.Second) // waiting for some blocks to pass - - //executeWrite(t, "gaiacli keys add foo --recover", pass, masterKey) - cmd, wc3, _ := tests.GoExecuteT(t, "gaiacli keys add foo --recover") - time.Sleep(time.Second) // waiting for some blocks to pass - _, err := wc3.Write([]byte("1234567890\n")) - require.NoError(t, err) - _, err = wc3.Write([]byte(masterKey + "\n")) - require.NoError(t, err) - cmd.Wait() - time.Sleep(time.Second * 5) // waiting for some blocks to pass - fooAddr := executeGetAddr(t, "gaiacli keys show foo") - panic(fmt.Sprintf("debug fooAddr: %v\n", fooAddr)) + executeWrite(t, "gaiacli keys add foo --recover", pass, masterKey) executeWrite(t, "gaiacli keys add bar", pass) + + fooAddr := executeGetAddr(t, "gaiacli keys show foo") barAddr := executeGetAddr(t, "gaiacli keys show bar") executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10fermion --to=%v --name=foo", flags, barAddr), pass) time.Sleep(time.Second * 3) // waiting for some blocks to pass @@ -68,15 +58,16 @@ func executeWrite(t *testing.T, cmdStr string, writes ...string) { } func executeInit(t *testing.T, cmdStr string) (masterKey, chainID string) { - tests.GoExecuteT(t, cmdStr) out := tests.ExecuteT(t, cmdStr) outCut := "{" + strings.SplitN(out, "{", 2)[1] // weird I'm sorry var initRes map[string]json.RawMessage err := json.Unmarshal([]byte(outCut), &initRes) - require.NoError(t, err, "out %v outCut %v err %v", out, outCut, err) - masterKey = string(initRes["secret"]) - chainID = string(initRes["chain_id"]) + require.NoError(t, err) + err = json.Unmarshal(initRes["secret"], &masterKey) + require.NoError(t, err) + err = json.Unmarshal(initRes["chain_id"], &chainID) + require.NoError(t, err) return } From e584d5acacc96108a1f028e69810946295a9aa10 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 14 Apr 2018 16:52:58 -0400 Subject: [PATCH 16/71] ci build -> install pubkey issue ... rebase fixes ... --- Makefile | 2 +- client/keys/wire.go | 6 ++++ cmd/gaia/app/app.go | 14 +++----- cmd/gaia/app/app_test.go | 19 ++++------- cmd/gaia/cmd/cli_test.go | 68 ++++++++++++++++++++++++++++++-------- cmd/gaia/cmd/gaiad/main.go | 2 +- x/stake/commands/tx.go | 4 ++- x/stake/types.go | 26 ++++++++++++--- 8 files changed, 98 insertions(+), 43 deletions(-) diff --git a/Makefile b/Makefile index 78a5c9dcc..daa0361fc 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ all: check_tools get_vendor_deps build build_examples test ######################################## ### CI -ci: get_tools get_vendor_deps build test_cover +ci: get_tools get_vendor_deps install test_cover ######################################## ### Build diff --git a/client/keys/wire.go b/client/keys/wire.go index 225e60ae7..a163f995a 100644 --- a/client/keys/wire.go +++ b/client/keys/wire.go @@ -11,6 +11,12 @@ func init() { wire.RegisterCrypto(cdc) } +// marshal keys func MarshalJSON(o interface{}) ([]byte, error) { return cdc.MarshalJSON(o) } + +// unmarshal json +func UnmarshalJSON(bz []byte, ptr interface{}) error { + return cdc.UnmarshalJSON(bz, ptr) +} diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index eeb64a7a7..0c9ef8b55 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -39,10 +39,10 @@ type GaiaApp struct { stakeKeeper stake.Keeper } -func NewGaiaApp(logger log.Logger, dbs map[string]dbm.DB) *GaiaApp { +func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp { // create your application object var app = &GaiaApp{ - BaseApp: bam.NewBaseApp(appName, logger, dbs["main"]), + BaseApp: bam.NewBaseApp(appName, logger, db), cdc: MakeCodec(), capKeyMainStore: sdk.NewKVStoreKey("main"), capKeyAccountStore: sdk.NewKVStoreKey("acc"), @@ -70,13 +70,7 @@ func NewGaiaApp(logger log.Logger, dbs map[string]dbm.DB) *GaiaApp { app.SetTxDecoder(app.txDecoder) app.SetInitChainer(app.initChainer) app.SetEndBlocker(stake.NewEndBlocker(app.stakeKeeper)) - app.MountStoreWithDB(app.capKeyMainStore, sdk.StoreTypeIAVL, dbs["main"]) - app.MountStoreWithDB(app.capKeyAccountStore, sdk.StoreTypeIAVL, dbs["acc"]) - app.MountStoreWithDB(app.capKeyIBCStore, sdk.StoreTypeIAVL, dbs["ibc"]) - app.MountStoreWithDB(app.capKeyStakeStore, sdk.StoreTypeIAVL, dbs["stake"]) - - // NOTE: Broken until #532 lands - //app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore, app.capKeyStakeStore) + app.MountStoresIAVL(app.capKeyMainStore, app.capKeyAccountStore, app.capKeyIBCStore, app.capKeyStakeStore) app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper)) err := app.LoadLatestVersion(app.capKeyMainStore) if err != nil { @@ -116,7 +110,7 @@ func (app *GaiaApp) txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) { } // StdTx.Msg is an interface. The concrete types - // are registered by MakeTxCodec in bank.RegisterWire. + // are registered by MakeTxCodec err := app.cdc.UnmarshalBinary(txBytes, &tx) if err != nil { return nil, sdk.ErrTxDecode("").TraceCause(err, "") diff --git a/cmd/gaia/app/app_test.go b/cmd/gaia/app/app_test.go index ea10cebc5..5c8450138 100644 --- a/cmd/gaia/app/app_test.go +++ b/cmd/gaia/app/app_test.go @@ -85,20 +85,15 @@ var ( } ) -func loggerAndDBs() (log.Logger, map[string]dbm.DB) { +func loggerAndDB() (log.Logger, dbm.DB) { logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") - dbs := map[string]dbm.DB{ - "main": dbm.NewMemDB(), - "acc": dbm.NewMemDB(), - "ibc": dbm.NewMemDB(), - "stake": dbm.NewMemDB(), - } - return logger, dbs + db := dbm.NewMemDB() + return logger, db } func newGaiaApp() *GaiaApp { - logger, dbs := loggerAndDBs() - return NewGaiaApp(logger, dbs) + logger, db := loggerAndDB() + return NewGaiaApp(logger, db) } func setGenesis(gapp *GaiaApp, accs ...*auth.BaseAccount) error { @@ -144,7 +139,7 @@ func TestMsgs(t *testing.T) { } func TestSortGenesis(t *testing.T) { - logger, dbs := loggerAndDBs() + logger, dbs := loggerAndDB() gapp := NewGaiaApp(logger, dbs) // Note the order: the coins are unsorted! @@ -188,7 +183,7 @@ func TestSortGenesis(t *testing.T) { } func TestGenesis(t *testing.T) { - logger, dbs := loggerAndDBs() + logger, dbs := loggerAndDB() gapp := NewGaiaApp(logger, dbs) // Construct some genesis bytes to reflect GaiaAccount diff --git a/cmd/gaia/cmd/cli_test.go b/cmd/gaia/cmd/cli_test.go index eb31aaad1..c537ae0a5 100644 --- a/cmd/gaia/cmd/cli_test.go +++ b/cmd/gaia/cmd/cli_test.go @@ -1,6 +1,7 @@ package common import ( + "encoding/hex" "encoding/json" "fmt" "strings" @@ -10,17 +11,20 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/tests" "github.com/cosmos/cosmos-sdk/x/auth" + crypto "github.com/tendermint/go-crypto" + crkeys "github.com/tendermint/go-crypto/keys" ) func TestGaiaCLI(t *testing.T) { tests.ExecuteT(t, "gaiad unsafe_reset_all") pass := "1234567890" - executeWrite(t, "gaiacli keys delete foo", pass) - executeWrite(t, "gaiacli keys delete bar", pass) + executeWrite(t, false, "gaiacli keys delete foo", pass) + executeWrite(t, false, "gaiacli keys delete bar", pass) masterKey, chainID := executeInit(t, "gaiad init") // get a free port, also setup some common flags @@ -31,25 +35,55 @@ func TestGaiaCLI(t *testing.T) { cmd, _, _ := tests.GoExecuteT(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr)) defer cmd.Process.Kill() - executeWrite(t, "gaiacli keys add foo --recover", pass, masterKey) - executeWrite(t, "gaiacli keys add bar", pass) + executeWrite(t, false, "gaiacli keys add foo --recover", pass, masterKey) + executeWrite(t, false, "gaiacli keys add bar", pass) - fooAddr := executeGetAddr(t, "gaiacli keys show foo") - barAddr := executeGetAddr(t, "gaiacli keys show bar") - executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10fermion --to=%v --name=foo", flags, barAddr), pass) + fooAddr, fooPubKey := executeGetAddr(t, "gaiacli keys show foo --output=json") + barAddr, _ := executeGetAddr(t, "gaiacli keys show bar --output=json") + + fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) + assert.Equal(t, int64(100000), fooAcc.GetCoins().AmountOf("fermion")) + + executeWrite(t, false, fmt.Sprintf("gaiacli send %v --amount=10fermion --to=%v --name=foo", flags, barAddr), pass) time.Sleep(time.Second * 3) // waiting for some blocks to pass barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barAddr, flags)) assert.Equal(t, int64(10), barAcc.GetCoins().AmountOf("fermion")) - fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) + fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) assert.Equal(t, int64(99990), fooAcc.GetCoins().AmountOf("fermion")) // declare candidacy - //executeWrite(t, "gaiacli declare-candidacy -", pass) + //--address-candidate string hex address of the validator/candidate + //--amount string Amount of coins to bond (default "1fermion") + //--chain-id string Chain ID of tendermint node + //--fee string Fee to pay along with transaction + //--keybase-sig string optional keybase signature + //--moniker string validator-candidate name + //--name string Name of private key with which to sign + //--node string : to tendermint rpc interface for this chain (default "tcp://localhost:46657") + //--pubkey string PubKey of the validator-candidate + //--sequence int Sequence number to sign the tx + //--website string optional website + _ = fooPubKey + //declStr := fmt.Sprintf("gaiacli declare-candidacy %v", flags) + //declStr += fmt.Sprintf(" --name=%v", "foo") + //declStr += fmt.Sprintf(" --address-candidate=%v", fooAddr) + //declStr += fmt.Sprintf(" --pubkey=%v", fooPubKey) + //declStr += fmt.Sprintf(" --amount=%v", "3fermion") + //declStr += fmt.Sprintf(" --moniker=%v", "foo-vally") + //fmt.Printf("debug declStr: %v\n", declStr) + //executeWrite(t, true, declStr, pass) } -func executeWrite(t *testing.T, cmdStr string, writes ...string) { - cmd, wc, _ := tests.GoExecuteT(t, cmdStr) +func executeWrite(t *testing.T, print bool, cmdStr string, writes ...string) { + cmd, wc, rc := tests.GoExecuteT(t, cmdStr) + + if print { + bz := make([]byte, 100000) + rc.Read(bz) + fmt.Printf("debug read: %v\n", string(bz)) + } + for _, write := range writes { _, err := wc.Write([]byte(write + "\n")) require.NoError(t, err) @@ -71,10 +105,16 @@ func executeInit(t *testing.T, cmdStr string) (masterKey, chainID string) { return } -func executeGetAddr(t *testing.T, cmdStr string) (addr string) { +func executeGetAddr(t *testing.T, cmdStr string) (addr, pubKey string) { out := tests.ExecuteT(t, cmdStr) - name := strings.SplitN(cmdStr, " show ", 2)[1] - return strings.TrimLeft(out, name+"\t") + var info crkeys.Info + keys.UnmarshalJSON([]byte(out), &info) + pubKey = hex.EncodeToString(info.PubKey.(crypto.PubKeyEd25519).Bytes()) + pubKey = strings.TrimLeft(pubKey, "1624de6220") + fmt.Printf("debug pubKey: %v\n", pubKey) + addr = info.PubKey.Address().String() + fmt.Printf("debug addr: %v\n", addr) + return } func executeGetAccount(t *testing.T, cmdStr string) auth.BaseAccount { diff --git a/cmd/gaia/cmd/gaiad/main.go b/cmd/gaia/cmd/gaiad/main.go index b84a4e20d..91ea778f7 100644 --- a/cmd/gaia/cmd/gaiad/main.go +++ b/cmd/gaia/cmd/gaiad/main.go @@ -31,7 +31,7 @@ func generateApp(rootDir string, logger log.Logger) (abci.Application, error) { if err != nil { return nil, err } - bapp := app.NewBasecoinApp(logger, db) + bapp := app.NewGaiaApp(logger, db) //dbAcc, err := dbm.NewGoLevelDB("gaia-acc", dataDir) //if err != nil { //return nil, err diff --git a/x/stake/commands/tx.go b/x/stake/commands/tx.go index 679e59b15..76220aeb6 100644 --- a/x/stake/commands/tx.go +++ b/x/stake/commands/tx.go @@ -269,9 +269,11 @@ func GetPubKey(pubKeyStr string) (pk crypto.PubKey, err error) { return } if len(pubKeyStr) != 64 { //if len(pkBytes) != 32 { - err = fmt.Errorf("pubkey must be Ed25519 hex encoded string which is 64 characters long") + err = fmt.Errorf("pubkey must be Ed25519 hex encoded string which is 64 characters, this pubkey is %v characters", len(pubKeyStr)) return } + + // TODO: bech32 ... var pkBytes []byte pkBytes, err = hex.DecodeString(pubKeyStr) if err != nil { diff --git a/x/stake/types.go b/x/stake/types.go index 240f3fe2a..14978ce35 100644 --- a/x/stake/types.go +++ b/x/stake/types.go @@ -1,6 +1,8 @@ package stake import ( + "encoding/hex" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" abci "github.com/tendermint/abci/types" @@ -131,12 +133,20 @@ type Validator struct { // abci validator from stake validator type func (v Validator) abciValidator(cdc *wire.Codec) abci.Validator { - pkBytes, err := cdc.MarshalBinary(v.PubKey) + //pkBytes, err := cdc.MarshalBinary(v.PubKey) + //if err != nil { + //panic(err) + //} + //return abci.Validator{ + //PubKey: pkBytes, + //Power: v.Power.Evaluate(), + //} + TypeDistinguisher, err := hex.DecodeString("1624de6220") if err != nil { panic(err) } return abci.Validator{ - PubKey: pkBytes, + PubKey: append(TypeDistinguisher, v.PubKey.Bytes()...), Power: v.Power.Evaluate(), } } @@ -144,12 +154,20 @@ func (v Validator) abciValidator(cdc *wire.Codec) abci.Validator { // abci validator from stake validator type // with zero power used for validator updates func (v Validator) abciValidatorZero(cdc *wire.Codec) abci.Validator { - pkBytes, err := cdc.MarshalBinary(v.PubKey) + //pkBytes, err := cdc.MarshalBinary(v.PubKey) + //if err != nil { + //panic(err) + //} + //return abci.Validator{ + //PubKey: pkBytes, + //Power: 0, + //} + TypeDistinguisher, err := hex.DecodeString("1624de6220") if err != nil { panic(err) } return abci.Validator{ - PubKey: pkBytes, + PubKey: append(TypeDistinguisher, v.PubKey.Bytes()...), Power: 0, } } From 265670297cf5864cd34893366f4310949c27a58b Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 16 Apr 2018 16:47:28 -0400 Subject: [PATCH 17/71] fix PK encodings --- cmd/gaia/cmd/cli_test.go | 42 ++++++++++++++++++++-------------------- x/stake/keeper_test.go | 20 +++++-------------- x/stake/types.go | 30 ++-------------------------- 3 files changed, 28 insertions(+), 64 deletions(-) diff --git a/cmd/gaia/cmd/cli_test.go b/cmd/gaia/cmd/cli_test.go index c537ae0a5..a2bf5a3ca 100644 --- a/cmd/gaia/cmd/cli_test.go +++ b/cmd/gaia/cmd/cli_test.go @@ -23,8 +23,8 @@ func TestGaiaCLI(t *testing.T) { tests.ExecuteT(t, "gaiad unsafe_reset_all") pass := "1234567890" - executeWrite(t, false, "gaiacli keys delete foo", pass) - executeWrite(t, false, "gaiacli keys delete bar", pass) + executeWrite(t, "gaiacli keys delete foo", pass) + executeWrite(t, "gaiacli keys delete bar", pass) masterKey, chainID := executeInit(t, "gaiad init") // get a free port, also setup some common flags @@ -35,8 +35,8 @@ func TestGaiaCLI(t *testing.T) { cmd, _, _ := tests.GoExecuteT(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr)) defer cmd.Process.Kill() - executeWrite(t, false, "gaiacli keys add foo --recover", pass, masterKey) - executeWrite(t, false, "gaiacli keys add bar", pass) + executeWrite(t, "gaiacli keys add foo --recover", pass, masterKey) + executeWrite(t, "gaiacli keys add bar", pass) fooAddr, fooPubKey := executeGetAddr(t, "gaiacli keys show foo --output=json") barAddr, _ := executeGetAddr(t, "gaiacli keys show bar --output=json") @@ -44,7 +44,7 @@ func TestGaiaCLI(t *testing.T) { fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) assert.Equal(t, int64(100000), fooAcc.GetCoins().AmountOf("fermion")) - executeWrite(t, false, fmt.Sprintf("gaiacli send %v --amount=10fermion --to=%v --name=foo", flags, barAddr), pass) + executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10fermion --to=%v --name=foo", flags, barAddr), pass) time.Sleep(time.Second * 3) // waiting for some blocks to pass barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barAddr, flags)) @@ -64,25 +64,25 @@ func TestGaiaCLI(t *testing.T) { //--pubkey string PubKey of the validator-candidate //--sequence int Sequence number to sign the tx //--website string optional website - _ = fooPubKey - //declStr := fmt.Sprintf("gaiacli declare-candidacy %v", flags) - //declStr += fmt.Sprintf(" --name=%v", "foo") - //declStr += fmt.Sprintf(" --address-candidate=%v", fooAddr) - //declStr += fmt.Sprintf(" --pubkey=%v", fooPubKey) - //declStr += fmt.Sprintf(" --amount=%v", "3fermion") - //declStr += fmt.Sprintf(" --moniker=%v", "foo-vally") - //fmt.Printf("debug declStr: %v\n", declStr) - //executeWrite(t, true, declStr, pass) + //_ = fooPubKey + declStr := fmt.Sprintf("gaiacli declare-candidacy %v", flags) + declStr += fmt.Sprintf(" --name=%v", "foo") + declStr += fmt.Sprintf(" --address-candidate=%v", fooAddr) + declStr += fmt.Sprintf(" --pubkey=%v", fooPubKey) + declStr += fmt.Sprintf(" --amount=%v", "3fermion") + declStr += fmt.Sprintf(" --moniker=%v", "foo-vally") + fmt.Printf("debug declStr: %v\n", declStr) + executeWrite(t, declStr, pass) } -func executeWrite(t *testing.T, print bool, cmdStr string, writes ...string) { - cmd, wc, rc := tests.GoExecuteT(t, cmdStr) +func executeWrite(t *testing.T, cmdStr string, writes ...string) { + cmd, wc, _ := tests.GoExecuteT(t, cmdStr) - if print { - bz := make([]byte, 100000) - rc.Read(bz) - fmt.Printf("debug read: %v\n", string(bz)) - } + //if print { + //bz := make([]byte, 100000) + //rc.Read(bz) + //fmt.Printf("debug read: %v\n", string(bz)) + //} for _, write := range writes { _, err := wc.Write([]byte(write + "\n")) diff --git a/x/stake/keeper_test.go b/x/stake/keeper_test.go index 9d6f69cc6..e01df1aae 100644 --- a/x/stake/keeper_test.go +++ b/x/stake/keeper_test.go @@ -5,7 +5,6 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" - crypto "github.com/tendermint/go-crypto" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -315,15 +314,6 @@ func TestGetAccUpdateValidators(t *testing.T) { } } - // to compare pubkeys between abci pubkey and crypto.PubKey - wirePK := func(pk crypto.PubKey) []byte { - pkBytes, err := keeper.cdc.MarshalBinary(pk) - if err != nil { - panic(err) - } - return pkBytes - } - // test from nothing to something // candidate set: {} -> {c1, c3} // validator set: {} -> {c1, c3} @@ -478,7 +468,7 @@ func TestGetAccUpdateValidators(t *testing.T) { acc = keeper.getAccUpdateValidators(ctx) require.Equal(t, 2, len(acc), "%v", acc) - assert.Equal(t, wirePK(candidatesIn[0].PubKey), acc[0].PubKey) + assert.Equal(t, candidatesIn[0].PubKey.Bytes(), acc[0].PubKey) assert.Equal(t, int64(0), acc[0].Power) assert.Equal(t, vals[0].abciValidator(keeper.cdc), acc[1]) @@ -503,10 +493,10 @@ func TestGetAccUpdateValidators(t *testing.T) { require.Equal(t, 0, len(candidates)) acc = keeper.getAccUpdateValidators(ctx) require.Equal(t, 4, len(acc)) - assert.Equal(t, wirePK(candidatesIn[1].PubKey), acc[0].PubKey) - assert.Equal(t, wirePK(candidatesIn[2].PubKey), acc[1].PubKey) - assert.Equal(t, wirePK(candidatesIn[3].PubKey), acc[2].PubKey) - assert.Equal(t, wirePK(candidatesIn[4].PubKey), acc[3].PubKey) + assert.Equal(t, candidatesIn[1].PubKey.Bytes(), acc[0].PubKey) + assert.Equal(t, candidatesIn[2].PubKey.Bytes(), acc[1].PubKey) + assert.Equal(t, candidatesIn[3].PubKey.Bytes(), acc[2].PubKey) + assert.Equal(t, candidatesIn[4].PubKey.Bytes(), acc[3].PubKey) assert.Equal(t, int64(0), acc[0].Power) assert.Equal(t, int64(0), acc[1].Power) assert.Equal(t, int64(0), acc[2].Power) diff --git a/x/stake/types.go b/x/stake/types.go index 14978ce35..b0dbc0b1f 100644 --- a/x/stake/types.go +++ b/x/stake/types.go @@ -1,8 +1,6 @@ package stake import ( - "encoding/hex" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" abci "github.com/tendermint/abci/types" @@ -133,20 +131,8 @@ type Validator struct { // abci validator from stake validator type func (v Validator) abciValidator(cdc *wire.Codec) abci.Validator { - //pkBytes, err := cdc.MarshalBinary(v.PubKey) - //if err != nil { - //panic(err) - //} - //return abci.Validator{ - //PubKey: pkBytes, - //Power: v.Power.Evaluate(), - //} - TypeDistinguisher, err := hex.DecodeString("1624de6220") - if err != nil { - panic(err) - } return abci.Validator{ - PubKey: append(TypeDistinguisher, v.PubKey.Bytes()...), + PubKey: v.PubKey.Bytes(), Power: v.Power.Evaluate(), } } @@ -154,20 +140,8 @@ func (v Validator) abciValidator(cdc *wire.Codec) abci.Validator { // abci validator from stake validator type // with zero power used for validator updates func (v Validator) abciValidatorZero(cdc *wire.Codec) abci.Validator { - //pkBytes, err := cdc.MarshalBinary(v.PubKey) - //if err != nil { - //panic(err) - //} - //return abci.Validator{ - //PubKey: pkBytes, - //Power: 0, - //} - TypeDistinguisher, err := hex.DecodeString("1624de6220") - if err != nil { - panic(err) - } return abci.Validator{ - PubKey: append(TypeDistinguisher, v.PubKey.Bytes()...), + PubKey: v.PubKey.Bytes(), Power: 0, } } From 09fe4c0262cd9a8160e6dd31ee107411e98e507a Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 16 Apr 2018 19:17:09 -0400 Subject: [PATCH 18/71] fix stake query keys --- cmd/gaia/cmd/cli_test.go | 72 +++++++++++++++++++++++++++----------- cmd/gaia/cmd/gaiad/main.go | 19 ---------- x/stake/commands/query.go | 16 +++------ x/stake/commands/tx.go | 8 ++--- 4 files changed, 61 insertions(+), 54 deletions(-) diff --git a/cmd/gaia/cmd/cli_test.go b/cmd/gaia/cmd/cli_test.go index a2bf5a3ca..225c2bd07 100644 --- a/cmd/gaia/cmd/cli_test.go +++ b/cmd/gaia/cmd/cli_test.go @@ -19,12 +19,45 @@ import ( crkeys "github.com/tendermint/go-crypto/keys" ) -func TestGaiaCLI(t *testing.T) { +//func TestGaiaCLISend(t *testing.T) { + +//tests.ExecuteT(t, "gaiad unsafe_reset_all") +//pass := "1234567890" +//executeWrite(t, "gaiacli keys delete foo", pass) +//executeWrite(t, "gaiacli keys delete bar", pass) +//masterKey, chainID := executeInit(t, "gaiad init") + +//// get a free port, also setup some common flags +//servAddr := server.FreeTCPAddr(t) +//flags := fmt.Sprintf("--node=%v --chain-id=%v", servAddr, chainID) + +//// start gaiad server +//cmd, _, _ := tests.GoExecuteT(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr)) +//defer cmd.Process.Kill() + +//executeWrite(t, "gaiacli keys add foo --recover", pass, masterKey) +//executeWrite(t, "gaiacli keys add bar", pass) + +//fooAddr, _ := executeGetAddr(t, "gaiacli keys show foo --output=json") +//barAddr, _ := executeGetAddr(t, "gaiacli keys show bar --output=json") + +//fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) +//assert.Equal(t, int64(100000), fooAcc.GetCoins().AmountOf("fermion")) + +//executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10fermion --to=%v --name=foo", flags, barAddr), pass) +//time.Sleep(time.Second * 3) // waiting for some blocks to pass + +//barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barAddr, flags)) +//assert.Equal(t, int64(10), barAcc.GetCoins().AmountOf("fermion")) +//fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) +//assert.Equal(t, int64(99990), fooAcc.GetCoins().AmountOf("fermion")) +//} + +func TestGaiaCLIDeclareCandidacy(t *testing.T) { tests.ExecuteT(t, "gaiad unsafe_reset_all") pass := "1234567890" executeWrite(t, "gaiacli keys delete foo", pass) - executeWrite(t, "gaiacli keys delete bar", pass) masterKey, chainID := executeInit(t, "gaiad init") // get a free port, also setup some common flags @@ -36,22 +69,10 @@ func TestGaiaCLI(t *testing.T) { defer cmd.Process.Kill() executeWrite(t, "gaiacli keys add foo --recover", pass, masterKey) - executeWrite(t, "gaiacli keys add bar", pass) - fooAddr, fooPubKey := executeGetAddr(t, "gaiacli keys show foo --output=json") - barAddr, _ := executeGetAddr(t, "gaiacli keys show bar --output=json") - fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) assert.Equal(t, int64(100000), fooAcc.GetCoins().AmountOf("fermion")) - executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10fermion --to=%v --name=foo", flags, barAddr), pass) - time.Sleep(time.Second * 3) // waiting for some blocks to pass - - barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barAddr, flags)) - assert.Equal(t, int64(10), barAcc.GetCoins().AmountOf("fermion")) - fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) - assert.Equal(t, int64(99990), fooAcc.GetCoins().AmountOf("fermion")) - // declare candidacy //--address-candidate string hex address of the validator/candidate //--amount string Amount of coins to bond (default "1fermion") @@ -73,17 +94,14 @@ func TestGaiaCLI(t *testing.T) { declStr += fmt.Sprintf(" --moniker=%v", "foo-vally") fmt.Printf("debug declStr: %v\n", declStr) executeWrite(t, declStr, pass) + fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) + time.Sleep(time.Second * 3) // waiting for some blocks to pass + assert.Equal(t, int64(99997), fooAcc.GetCoins().AmountOf("fermion")) } func executeWrite(t *testing.T, cmdStr string, writes ...string) { cmd, wc, _ := tests.GoExecuteT(t, cmdStr) - //if print { - //bz := make([]byte, 100000) - //rc.Read(bz) - //fmt.Printf("debug read: %v\n", string(bz)) - //} - for _, write := range writes { _, err := wc.Write([]byte(write + "\n")) require.NoError(t, err) @@ -91,6 +109,20 @@ func executeWrite(t *testing.T, cmdStr string, writes ...string) { cmd.Wait() } +func executeWritePrint(t *testing.T, cmdStr string, writes ...string) { + cmd, wc, rc := tests.GoExecuteT(t, cmdStr) + + for _, write := range writes { + _, err := wc.Write([]byte(write + "\n")) + require.NoError(t, err) + } + cmd.Wait() + + bz := make([]byte, 100000) + rc.Read(bz) + fmt.Printf("debug read: %v\n", string(bz)) +} + func executeInit(t *testing.T, cmdStr string) (masterKey, chainID string) { out := tests.ExecuteT(t, cmdStr) outCut := "{" + strings.SplitN(out, "{", 2)[1] // weird I'm sorry diff --git a/cmd/gaia/cmd/gaiad/main.go b/cmd/gaia/cmd/gaiad/main.go index 91ea778f7..199a06152 100644 --- a/cmd/gaia/cmd/gaiad/main.go +++ b/cmd/gaia/cmd/gaiad/main.go @@ -32,25 +32,6 @@ func generateApp(rootDir string, logger log.Logger) (abci.Application, error) { return nil, err } bapp := app.NewGaiaApp(logger, db) - //dbAcc, err := dbm.NewGoLevelDB("gaia-acc", dataDir) - //if err != nil { - //return nil, err - //} - //dbIBC, err := dbm.NewGoLevelDB("gaia-ibc", dataDir) - //if err != nil { - //return nil, err - //} - //dbStake, err := dbm.NewGoLevelDB("gaia-stake", dataDir) - //if err != nil { - //return nil, err - //} - //dbs := map[string]dbm.DB{ - //"main": dbMain, - //"acc": dbAcc, - //"ibc": dbIBC, - //"stake": dbStake, - //} - //bapp := app.NewGaiaApp(logger, dbs) return bapp, nil } diff --git a/x/stake/commands/query.go b/x/stake/commands/query.go index 38e16f333..187de702c 100644 --- a/x/stake/commands/query.go +++ b/x/stake/commands/query.go @@ -16,12 +16,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/stake" ) -// XXX remove dependancy -func PrefixedKey(app string, key []byte) []byte { - prefix := append([]byte(app), byte(0)) - return append(prefix, key...) -} - //nolint var ( fsValAddr = flag.NewFlagSet("", flag.ContinueOnError) @@ -44,7 +38,7 @@ func GetCmdQueryCandidates(storeName string, cdc *wire.Codec) *cobra.Command { Short: "Query for the set of validator-candidates pubkeys", RunE: func(cmd *cobra.Command, args []string) error { - key := PrefixedKey(stake.MsgType, stake.CandidatesKey) + key := stake.CandidatesKey ctx := context.NewCoreContextFromViper() res, err := ctx.Query(key, storeName) @@ -54,7 +48,7 @@ func GetCmdQueryCandidates(storeName string, cdc *wire.Codec) *cobra.Command { // parse out the candidates candidates := new(stake.Candidates) - err = cdc.UnmarshalJSON(res, candidates) + err = cdc.UnmarshalBinary(res, candidates) if err != nil { return err } @@ -85,7 +79,7 @@ func GetCmdQueryCandidate(storeName string, cdc *wire.Codec) *cobra.Command { return err } - key := PrefixedKey(stake.MsgType, stake.GetCandidateKey(addr)) + key := stake.GetCandidateKey(addr) ctx := context.NewCoreContextFromViper() @@ -133,7 +127,7 @@ func GetCmdQueryDelegatorBond(storeName string, cdc *wire.Codec) *cobra.Command } delegator := crypto.Address(bz) - key := PrefixedKey(stake.MsgType, stake.GetDelegatorBondKey(delegator, addr, cdc)) + key := stake.GetDelegatorBondKey(delegator, addr, cdc) ctx := context.NewCoreContextFromViper() @@ -177,7 +171,7 @@ func GetCmdQueryDelegatorBonds(storeName string, cdc *wire.Codec) *cobra.Command } delegator := crypto.Address(bz) - key := PrefixedKey(stake.MsgType, stake.GetDelegatorBondsKey(delegator, cdc)) + key := stake.GetDelegatorBondsKey(delegator, cdc) ctx := context.NewCoreContextFromViper() diff --git a/x/stake/commands/tx.go b/x/stake/commands/tx.go index 76220aeb6..bc8f93e8f 100644 --- a/x/stake/commands/tx.go +++ b/x/stake/commands/tx.go @@ -268,10 +268,10 @@ func GetPubKey(pubKeyStr string) (pk crypto.PubKey, err error) { err = fmt.Errorf("must use --pubkey flag") return } - if len(pubKeyStr) != 64 { //if len(pkBytes) != 32 { - err = fmt.Errorf("pubkey must be Ed25519 hex encoded string which is 64 characters, this pubkey is %v characters", len(pubKeyStr)) - return - } + //if len(pubKeyStr) != 64 { //if len(pkBytes) != 32 { + //err = fmt.Errorf("pubkey must be Ed25519 hex encoded string which is 64 characters, this pubkey is %v characters", len(pubKeyStr)) + //return + //} // TODO: bech32 ... var pkBytes []byte From d344de3b629e11cf423c988cd06b8c069f97ba03 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 16 Apr 2018 19:49:00 -0400 Subject: [PATCH 19/71] stake test candidate query --- cmd/gaia/cmd/cli_test.go | 69 +++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/cmd/gaia/cmd/cli_test.go b/cmd/gaia/cmd/cli_test.go index 225c2bd07..8011d7a69 100644 --- a/cmd/gaia/cmd/cli_test.go +++ b/cmd/gaia/cmd/cli_test.go @@ -12,46 +12,48 @@ import ( "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/client/keys" + "github.com/cosmos/cosmos-sdk/cmd/gaia/app" "github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/tests" "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/stake" crypto "github.com/tendermint/go-crypto" crkeys "github.com/tendermint/go-crypto/keys" ) -//func TestGaiaCLISend(t *testing.T) { +func TestGaiaCLISend(t *testing.T) { -//tests.ExecuteT(t, "gaiad unsafe_reset_all") -//pass := "1234567890" -//executeWrite(t, "gaiacli keys delete foo", pass) -//executeWrite(t, "gaiacli keys delete bar", pass) -//masterKey, chainID := executeInit(t, "gaiad init") + tests.ExecuteT(t, "gaiad unsafe_reset_all") + pass := "1234567890" + executeWrite(t, "gaiacli keys delete foo", pass) + executeWrite(t, "gaiacli keys delete bar", pass) + masterKey, chainID := executeInit(t, "gaiad init") -//// get a free port, also setup some common flags -//servAddr := server.FreeTCPAddr(t) -//flags := fmt.Sprintf("--node=%v --chain-id=%v", servAddr, chainID) + // get a free port, also setup some common flags + servAddr := server.FreeTCPAddr(t) + flags := fmt.Sprintf("--node=%v --chain-id=%v", servAddr, chainID) -//// start gaiad server -//cmd, _, _ := tests.GoExecuteT(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr)) -//defer cmd.Process.Kill() + // start gaiad server + cmd, _, _ := tests.GoExecuteT(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr)) + defer cmd.Process.Kill() -//executeWrite(t, "gaiacli keys add foo --recover", pass, masterKey) -//executeWrite(t, "gaiacli keys add bar", pass) + executeWrite(t, "gaiacli keys add foo --recover", pass, masterKey) + executeWrite(t, "gaiacli keys add bar", pass) -//fooAddr, _ := executeGetAddr(t, "gaiacli keys show foo --output=json") -//barAddr, _ := executeGetAddr(t, "gaiacli keys show bar --output=json") + fooAddr, _ := executeGetAddr(t, "gaiacli keys show foo --output=json") + barAddr, _ := executeGetAddr(t, "gaiacli keys show bar --output=json") -//fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) -//assert.Equal(t, int64(100000), fooAcc.GetCoins().AmountOf("fermion")) + fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) + assert.Equal(t, int64(100000), fooAcc.GetCoins().AmountOf("fermion")) -//executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10fermion --to=%v --name=foo", flags, barAddr), pass) -//time.Sleep(time.Second * 3) // waiting for some blocks to pass + executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10fermion --to=%v --name=foo", flags, barAddr), pass) + time.Sleep(time.Second * 3) // waiting for some blocks to pass -//barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barAddr, flags)) -//assert.Equal(t, int64(10), barAcc.GetCoins().AmountOf("fermion")) -//fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) -//assert.Equal(t, int64(99990), fooAcc.GetCoins().AmountOf("fermion")) -//} + barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barAddr, flags)) + assert.Equal(t, int64(10), barAcc.GetCoins().AmountOf("fermion")) + fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) + assert.Equal(t, int64(99990), fooAcc.GetCoins().AmountOf("fermion")) +} func TestGaiaCLIDeclareCandidacy(t *testing.T) { @@ -94,9 +96,11 @@ func TestGaiaCLIDeclareCandidacy(t *testing.T) { declStr += fmt.Sprintf(" --moniker=%v", "foo-vally") fmt.Printf("debug declStr: %v\n", declStr) executeWrite(t, declStr, pass) - fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) time.Sleep(time.Second * 3) // waiting for some blocks to pass + fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) assert.Equal(t, int64(99997), fooAcc.GetCoins().AmountOf("fermion")) + candidate := executeGetCandidate(t, fmt.Sprintf("gaiacli candidate %v --address=%v", flags, fooAddr)) + assert.Equal(t, candidate.Address.String(), fooAddr) } func executeWrite(t *testing.T, cmdStr string, writes ...string) { @@ -142,7 +146,11 @@ func executeGetAddr(t *testing.T, cmdStr string) (addr, pubKey string) { var info crkeys.Info keys.UnmarshalJSON([]byte(out), &info) pubKey = hex.EncodeToString(info.PubKey.(crypto.PubKeyEd25519).Bytes()) + + // TODO this is really wierd, also error that not 64 characters! pubKey = strings.TrimLeft(pubKey, "1624de6220") + pubKey = fmt.Sprintf("%064v", pubKey) + fmt.Printf("debug pubKey: %v\n", pubKey) addr = info.PubKey.Address().String() fmt.Printf("debug addr: %v\n", addr) @@ -160,3 +168,12 @@ func executeGetAccount(t *testing.T, cmdStr string) auth.BaseAccount { require.NoError(t, err, "value %v, err %v", string(value), err) return acc } + +func executeGetCandidate(t *testing.T, cmdStr string) stake.Candidate { + out := tests.ExecuteT(t, cmdStr) + var candidate stake.Candidate + cdc := app.MakeCodec() + err := cdc.UnmarshalJSON([]byte(out), &candidate) + require.NoError(t, err, "out %v, err %v", out, err) + return candidate +} From 45723733bcb58525e172ce47a4208ae77dcddfac Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 17 Apr 2018 13:38:14 -0400 Subject: [PATCH 20/71] fix staking flags --- x/stake/commands/tx.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/x/stake/commands/tx.go b/x/stake/commands/tx.go index bc8f93e8f..55e009db0 100644 --- a/x/stake/commands/tx.go +++ b/x/stake/commands/tx.go @@ -49,6 +49,7 @@ func init() { fsCandidate.String(FlagIdentity, "", "optional keybase signature") fsCandidate.String(FlagWebsite, "", "optional website") fsCandidate.String(FlagAddressCandidate, "", "hex address of the validator/candidate") + fsDelegator.String(FlagAddressCandidate, "", "hex address of the delegator") fsDelegator.String(FlagAddressDelegator, "", "hex address of the delegator") } @@ -155,7 +156,6 @@ func GetCmdEditCandidacy(cdc *wire.Codec) *cobra.Command { }, } - cmd.Flags().AddFlagSet(fsPk) cmd.Flags().AddFlagSet(fsCandidate) return cmd } @@ -198,7 +198,6 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { }, } - cmd.Flags().AddFlagSet(fsPk) cmd.Flags().AddFlagSet(fsAmount) cmd.Flags().AddFlagSet(fsDelegator) return cmd @@ -252,7 +251,6 @@ func GetCmdUnbond(cdc *wire.Codec) *cobra.Command { }, } - cmd.Flags().AddFlagSet(fsPk) cmd.Flags().AddFlagSet(fsShares) cmd.Flags().AddFlagSet(fsDelegator) return cmd @@ -268,10 +266,10 @@ func GetPubKey(pubKeyStr string) (pk crypto.PubKey, err error) { err = fmt.Errorf("must use --pubkey flag") return } - //if len(pubKeyStr) != 64 { //if len(pkBytes) != 32 { - //err = fmt.Errorf("pubkey must be Ed25519 hex encoded string which is 64 characters, this pubkey is %v characters", len(pubKeyStr)) - //return - //} + if len(pubKeyStr) != 64 { //if len(pkBytes) != 32 { + err = fmt.Errorf("pubkey must be Ed25519 hex encoded string which is 64 characters, this pubkey is %v characters", len(pubKeyStr)) + return + } // TODO: bech32 ... var pkBytes []byte From c80b9674cddbaa5c62e8c3c6b61f749fdc190ac3 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 18 Apr 2018 00:33:33 -0400 Subject: [PATCH 21/71] stake CLI various fixes, confirmed working --- cmd/gaia/cmd/cli_test.go | 43 +++++----- cmd/gaia/cmd/gaiacli/main.go | 4 +- server/init.go | 2 +- tests/gobash.go | 10 ++- x/stake/commands/flags.go | 41 +++++++++ x/stake/commands/query.go | 160 ++++++++++++++++------------------- x/stake/commands/tx.go | 52 +----------- x/stake/types.go | 2 +- 8 files changed, 153 insertions(+), 161 deletions(-) create mode 100644 x/stake/commands/flags.go diff --git a/cmd/gaia/cmd/cli_test.go b/cmd/gaia/cmd/cli_test.go index 8011d7a69..b1af5f7b7 100644 --- a/cmd/gaia/cmd/cli_test.go +++ b/cmd/gaia/cmd/cli_test.go @@ -23,7 +23,7 @@ import ( func TestGaiaCLISend(t *testing.T) { - tests.ExecuteT(t, "gaiad unsafe_reset_all") + tests.ExecuteT(t, "gaiad unsafe_reset_all", 1) pass := "1234567890" executeWrite(t, "gaiacli keys delete foo", pass) executeWrite(t, "gaiacli keys delete bar", pass) @@ -57,7 +57,7 @@ func TestGaiaCLISend(t *testing.T) { func TestGaiaCLIDeclareCandidacy(t *testing.T) { - tests.ExecuteT(t, "gaiad unsafe_reset_all") + tests.ExecuteT(t, "gaiad unsafe_reset_all", 1) pass := "1234567890" executeWrite(t, "gaiacli keys delete foo", pass) masterKey, chainID := executeInit(t, "gaiad init") @@ -76,18 +76,6 @@ func TestGaiaCLIDeclareCandidacy(t *testing.T) { assert.Equal(t, int64(100000), fooAcc.GetCoins().AmountOf("fermion")) // declare candidacy - //--address-candidate string hex address of the validator/candidate - //--amount string Amount of coins to bond (default "1fermion") - //--chain-id string Chain ID of tendermint node - //--fee string Fee to pay along with transaction - //--keybase-sig string optional keybase signature - //--moniker string validator-candidate name - //--name string Name of private key with which to sign - //--node string : to tendermint rpc interface for this chain (default "tcp://localhost:46657") - //--pubkey string PubKey of the validator-candidate - //--sequence int Sequence number to sign the tx - //--website string optional website - //_ = fooPubKey declStr := fmt.Sprintf("gaiacli declare-candidacy %v", flags) declStr += fmt.Sprintf(" --name=%v", "foo") declStr += fmt.Sprintf(" --address-candidate=%v", fooAddr) @@ -99,8 +87,25 @@ func TestGaiaCLIDeclareCandidacy(t *testing.T) { time.Sleep(time.Second * 3) // waiting for some blocks to pass fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) assert.Equal(t, int64(99997), fooAcc.GetCoins().AmountOf("fermion")) - candidate := executeGetCandidate(t, fmt.Sprintf("gaiacli candidate %v --address=%v", flags, fooAddr)) + candidate := executeGetCandidate(t, fmt.Sprintf("gaiacli candidate %v --address-candidate=%v", flags, fooAddr)) assert.Equal(t, candidate.Address.String(), fooAddr) + assert.Equal(t, int64(3), candidate.Assets.Evaluate()) + + // TODO figure out why this times out with connection refused errors in go-bash + // unbond a single share + //unbondStr := fmt.Sprintf("gaiacli unbond %v", flags) + //unbondStr += fmt.Sprintf(" --name=%v", "foo") + //unbondStr += fmt.Sprintf(" --address-candidate=%v", fooAddr) + //unbondStr += fmt.Sprintf(" --address-delegator=%v", fooAddr) + //unbondStr += fmt.Sprintf(" --shares=%v", "1") + //unbondStr += fmt.Sprintf(" --sequence=%v", "1") + //fmt.Printf("debug unbondStr: %v\n", unbondStr) + //executeWrite(t, unbondStr, pass) + //time.Sleep(time.Second * 3) // waiting for some blocks to pass + //fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) + //assert.Equal(t, int64(99998), fooAcc.GetCoins().AmountOf("fermion")) + //candidate = executeGetCandidate(t, fmt.Sprintf("gaiacli candidate %v --address-candidate=%v", flags, fooAddr)) + //assert.Equal(t, int64(2), candidate.Assets.Evaluate()) } func executeWrite(t *testing.T, cmdStr string, writes ...string) { @@ -128,7 +133,7 @@ func executeWritePrint(t *testing.T, cmdStr string, writes ...string) { } func executeInit(t *testing.T, cmdStr string) (masterKey, chainID string) { - out := tests.ExecuteT(t, cmdStr) + out := tests.ExecuteT(t, cmdStr, 1) outCut := "{" + strings.SplitN(out, "{", 2)[1] // weird I'm sorry var initRes map[string]json.RawMessage @@ -142,7 +147,7 @@ func executeInit(t *testing.T, cmdStr string) (masterKey, chainID string) { } func executeGetAddr(t *testing.T, cmdStr string) (addr, pubKey string) { - out := tests.ExecuteT(t, cmdStr) + out := tests.ExecuteT(t, cmdStr, 2) var info crkeys.Info keys.UnmarshalJSON([]byte(out), &info) pubKey = hex.EncodeToString(info.PubKey.(crypto.PubKeyEd25519).Bytes()) @@ -158,7 +163,7 @@ func executeGetAddr(t *testing.T, cmdStr string) (addr, pubKey string) { } func executeGetAccount(t *testing.T, cmdStr string) auth.BaseAccount { - out := tests.ExecuteT(t, cmdStr) + out := tests.ExecuteT(t, cmdStr, 2) var initRes map[string]json.RawMessage err := json.Unmarshal([]byte(out), &initRes) require.NoError(t, err, "out %v, err %v", out, err) @@ -170,7 +175,7 @@ func executeGetAccount(t *testing.T, cmdStr string) auth.BaseAccount { } func executeGetCandidate(t *testing.T, cmdStr string) stake.Candidate { - out := tests.ExecuteT(t, cmdStr) + out := tests.ExecuteT(t, cmdStr, 2) var candidate stake.Candidate cdc := app.MakeCodec() err := cdc.UnmarshalJSON([]byte(out), &candidate) diff --git a/cmd/gaia/cmd/gaiacli/main.go b/cmd/gaia/cmd/gaiacli/main.go index c5c3190c3..1e5528308 100644 --- a/cmd/gaia/cmd/gaiacli/main.go +++ b/cmd/gaia/cmd/gaiacli/main.go @@ -48,10 +48,10 @@ func main() { rootCmd.AddCommand( client.GetCommands( authcmd.GetAccountCmd("main", cdc, authcmd.GetAccountDecoder(cdc)), - stakecmd.GetCmdQueryCandidates("stake", cdc), stakecmd.GetCmdQueryCandidate("stake", cdc), + //stakecmd.GetCmdQueryCandidates("stake", cdc), stakecmd.GetCmdQueryDelegatorBond("stake", cdc), - stakecmd.GetCmdQueryDelegatorBonds("stake", cdc), + //stakecmd.GetCmdQueryDelegatorBonds("stake", cdc), )...) rootCmd.AddCommand( client.PostCommands( diff --git a/server/init.go b/server/init.go index 8c82d2796..f2578cb19 100644 --- a/server/init.go +++ b/server/init.go @@ -70,7 +70,7 @@ func (c initCmd) run(cmd *cobra.Command, args []string) error { return nil } - // generate secrete and address + // generate secret and address addr, secret, err := GenerateCoinKey() if err != nil { return err diff --git a/tests/gobash.go b/tests/gobash.go index 12b3da085..c106c1f3f 100644 --- a/tests/gobash.go +++ b/tests/gobash.go @@ -1,6 +1,7 @@ package tests import ( + "fmt" "io" "os/exec" "strings" @@ -25,10 +26,15 @@ func getCmd(t *testing.T, command string) *exec.Cmd { return cmd } -// Execute the command, return standard output and error -func ExecuteT(t *testing.T, command string) (out string) { +// Execute the command, return standard output and error, try a few times if requested +func ExecuteT(t *testing.T, command string, trials int) (out string) { cmd := getCmd(t, command) bz, err := cmd.CombinedOutput() + if err != nil && trials > 1 { + fmt.Printf("trial %v, retrying: %v\n", trials, command) + time.Sleep(time.Second * 10) + return ExecuteT(t, command, trials-1) + } require.NoError(t, err, string(bz)) out = strings.Trim(string(bz), "\n") //trim any new lines time.Sleep(time.Second) diff --git a/x/stake/commands/flags.go b/x/stake/commands/flags.go new file mode 100644 index 000000000..e5b97d62c --- /dev/null +++ b/x/stake/commands/flags.go @@ -0,0 +1,41 @@ +package commands + +import ( + flag "github.com/spf13/pflag" +) + +// nolint +const ( + FlagAddressDelegator = "address-delegator" + FlagAddressCandidate = "address-candidate" + FlagPubKey = "pubkey" + FlagAmount = "amount" + FlagShares = "shares" + + FlagMoniker = "moniker" + FlagIdentity = "keybase-sig" + FlagWebsite = "website" + FlagDetails = "details" +) + +// common flagsets to add to various functions +var ( + fsPk = flag.NewFlagSet("", flag.ContinueOnError) + fsAmount = flag.NewFlagSet("", flag.ContinueOnError) + fsShares = flag.NewFlagSet("", flag.ContinueOnError) + fsDescription = flag.NewFlagSet("", flag.ContinueOnError) + fsCandidate = flag.NewFlagSet("", flag.ContinueOnError) + fsDelegator = flag.NewFlagSet("", flag.ContinueOnError) +) + +func init() { + fsPk.String(FlagPubKey, "", "PubKey of the validator-candidate") + fsAmount.String(FlagAmount, "1fermion", "Amount of coins to bond") + fsShares.String(FlagShares, "", "Amount of shares to unbond, either in decimal or keyword MAX (ex. 1.23456789, 99, MAX)") + fsDescription.String(FlagMoniker, "", "validator-candidate name") + fsDescription.String(FlagIdentity, "", "optional keybase signature") + fsDescription.String(FlagWebsite, "", "optional website") + fsDescription.String(FlagDetails, "", "optional details") + fsCandidate.String(FlagAddressCandidate, "", "hex address of the validator/candidate") + fsDelegator.String(FlagAddressDelegator, "", "hex address of the delegator") +} diff --git a/x/stake/commands/query.go b/x/stake/commands/query.go index 187de702c..3bc2cffa7 100644 --- a/x/stake/commands/query.go +++ b/x/stake/commands/query.go @@ -5,7 +5,6 @@ import ( "fmt" "github.com/spf13/cobra" - flag "github.com/spf13/pflag" "github.com/spf13/viper" crypto "github.com/tendermint/go-crypto" @@ -16,56 +15,41 @@ import ( "github.com/cosmos/cosmos-sdk/x/stake" ) -//nolint -var ( - fsValAddr = flag.NewFlagSet("", flag.ContinueOnError) - fsDelAddr = flag.NewFlagSet("", flag.ContinueOnError) - FlagValidatorAddr = "address" - FlagDelegatorAddr = "delegator-address" -) +//// create command to query for all candidates +//func GetCmdQueryCandidates(storeName string, cdc *wire.Codec) *cobra.Command { +//cmd := &cobra.Command{ +//Use: "candidates", +//Short: "Query for the set of validator-candidates pubkeys", +//RunE: func(cmd *cobra.Command, args []string) error { -func init() { - //Add Flags - fsValAddr.String(FlagValidatorAddr, "", "Address of the validator/candidate") - fsDelAddr.String(FlagDelegatorAddr, "", "Delegator hex address") +//key := stake.CandidatesKey -} +//ctx := context.NewCoreContextFromViper() +//res, err := ctx.Query(key, storeName) +//if err != nil { +//return err +//} -// create command to query for all candidates -func GetCmdQueryCandidates(storeName string, cdc *wire.Codec) *cobra.Command { - cmd := &cobra.Command{ - Use: "candidates", - Short: "Query for the set of validator-candidates pubkeys", - RunE: func(cmd *cobra.Command, args []string) error { +//// parse out the candidates +//candidates := new(stake.Candidates) +//err = cdc.UnmarshalBinary(res, candidates) +//if err != nil { +//return err +//} +//output, err := wire.MarshalJSONIndent(cdc, candidates) +//if err != nil { +//return err +//} +//fmt.Println(string(output)) +//return nil - key := stake.CandidatesKey +//// TODO output with proofs / machine parseable etc. +//}, +//} - ctx := context.NewCoreContextFromViper() - res, err := ctx.Query(key, storeName) - if err != nil { - return err - } - - // parse out the candidates - candidates := new(stake.Candidates) - err = cdc.UnmarshalBinary(res, candidates) - if err != nil { - return err - } - output, err := wire.MarshalJSONIndent(cdc, candidates) - if err != nil { - return err - } - fmt.Println(string(output)) - return nil - - // TODO output with proofs / machine parseable etc. - }, - } - - cmd.Flags().AddFlagSet(fsDelAddr) - return cmd -} +//cmd.Flags().AddFlagSet(fsDelegator) +//return cmd +//} // get the command to query a candidate func GetCmdQueryCandidate(storeName string, cdc *wire.Codec) *cobra.Command { @@ -74,7 +58,7 @@ func GetCmdQueryCandidate(storeName string, cdc *wire.Codec) *cobra.Command { Short: "Query a validator-candidate account", RunE: func(cmd *cobra.Command, args []string) error { - addr, err := sdk.GetAddress(viper.GetString(FlagValidatorAddr)) + addr, err := sdk.GetAddress(viper.GetString(FlagAddressCandidate)) if err != nil { return err } @@ -105,7 +89,7 @@ func GetCmdQueryCandidate(storeName string, cdc *wire.Codec) *cobra.Command { }, } - cmd.Flags().AddFlagSet(fsValAddr) + cmd.Flags().AddFlagSet(fsCandidate) return cmd } @@ -116,12 +100,12 @@ func GetCmdQueryDelegatorBond(storeName string, cdc *wire.Codec) *cobra.Command Short: "Query a delegators bond based on address and candidate pubkey", RunE: func(cmd *cobra.Command, args []string) error { - addr, err := sdk.GetAddress(viper.GetString(FlagValidatorAddr)) + addr, err := sdk.GetAddress(viper.GetString(FlagAddressCandidate)) if err != nil { return err } - bz, err := hex.DecodeString(viper.GetString(FlagDelegatorAddr)) + bz, err := hex.DecodeString(viper.GetString(FlagAddressDelegator)) if err != nil { return err } @@ -137,7 +121,7 @@ func GetCmdQueryDelegatorBond(storeName string, cdc *wire.Codec) *cobra.Command } // parse out the bond - var bond stake.DelegatorBond + bond := new(stake.DelegatorBond) err = cdc.UnmarshalBinary(res, bond) if err != nil { return err @@ -153,49 +137,49 @@ func GetCmdQueryDelegatorBond(storeName string, cdc *wire.Codec) *cobra.Command }, } - cmd.Flags().AddFlagSet(fsValAddr) - cmd.Flags().AddFlagSet(fsDelAddr) + cmd.Flags().AddFlagSet(fsCandidate) + cmd.Flags().AddFlagSet(fsDelegator) return cmd } -// get the command to query all the candidates bonded to a delegator -func GetCmdQueryDelegatorBonds(storeName string, cdc *wire.Codec) *cobra.Command { - cmd := &cobra.Command{ - Use: "delegator-candidates", - Short: "Query all delegators candidates' pubkeys based on address", - RunE: func(cmd *cobra.Command, args []string) error { +//// get the command to query all the candidates bonded to a delegator +//func GetCmdQueryDelegatorBonds(storeName string, cdc *wire.Codec) *cobra.Command { +//cmd := &cobra.Command{ +//Use: "delegator-candidates", +//Short: "Query all delegators bond's candidate-addresses based on delegator-address", +//RunE: func(cmd *cobra.Command, args []string) error { - bz, err := hex.DecodeString(viper.GetString(FlagDelegatorAddr)) - if err != nil { - return err - } - delegator := crypto.Address(bz) +//bz, err := hex.DecodeString(viper.GetString(FlagAddressDelegator)) +//if err != nil { +//return err +//} +//delegator := crypto.Address(bz) - key := stake.GetDelegatorBondsKey(delegator, cdc) +//key := stake.GetDelegatorBondsKey(delegator, cdc) - ctx := context.NewCoreContextFromViper() +//ctx := context.NewCoreContextFromViper() - res, err := ctx.Query(key, storeName) - if err != nil { - return err - } +//res, err := ctx.Query(key, storeName) +//if err != nil { +//return err +//} - // parse out the candidates list - var candidates []crypto.PubKey - err = cdc.UnmarshalBinary(res, candidates) - if err != nil { - return err - } - output, err := wire.MarshalJSONIndent(cdc, candidates) - if err != nil { - return err - } - fmt.Println(string(output)) - return nil +//// parse out the candidates list +//var candidates []crypto.PubKey +//err = cdc.UnmarshalBinary(res, candidates) +//if err != nil { +//return err +//} +//output, err := wire.MarshalJSONIndent(cdc, candidates) +//if err != nil { +//return err +//} +//fmt.Println(string(output)) +//return nil - // TODO output with proofs / machine parseable etc. - }, - } - cmd.Flags().AddFlagSet(fsDelAddr) - return cmd -} +//// TODO output with proofs / machine parseable etc. +//}, +//} +//cmd.Flags().AddFlagSet(fsDelegator) +//return cmd +//} diff --git a/x/stake/commands/tx.go b/x/stake/commands/tx.go index 55e009db0..4a1983743 100644 --- a/x/stake/commands/tx.go +++ b/x/stake/commands/tx.go @@ -5,12 +5,10 @@ import ( "fmt" "github.com/spf13/cobra" - flag "github.com/spf13/pflag" "github.com/spf13/viper" crypto "github.com/tendermint/go-crypto" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" @@ -18,52 +16,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/stake" ) -// nolint -const ( - FlagAddressDelegator = "address-delegator" - FlagAddressCandidate = "address-candidate" - FlagPubKey = "pubkey" - FlagAmount = "amount" - FlagShares = "shares" - - FlagMoniker = "moniker" - FlagIdentity = "keybase-sig" - FlagWebsite = "website" - FlagDetails = "details" -) - -// common flagsets to add to various functions -var ( - fsPk = flag.NewFlagSet("", flag.ContinueOnError) - fsAmount = flag.NewFlagSet("", flag.ContinueOnError) - fsShares = flag.NewFlagSet("", flag.ContinueOnError) - fsCandidate = flag.NewFlagSet("", flag.ContinueOnError) - fsDelegator = flag.NewFlagSet("", flag.ContinueOnError) -) - -func init() { - fsPk.String(FlagPubKey, "", "PubKey of the validator-candidate") - fsAmount.String(FlagAmount, "1fermion", "Amount of coins to bond") - fsShares.String(FlagShares, "", "Amount of shares to unbond, either in decimal or keyword MAX (ex. 1.23456789, 99, MAX)") - fsCandidate.String(FlagMoniker, "", "validator-candidate name") - fsCandidate.String(FlagIdentity, "", "optional keybase signature") - fsCandidate.String(FlagWebsite, "", "optional website") - fsCandidate.String(FlagAddressCandidate, "", "hex address of the validator/candidate") - fsDelegator.String(FlagAddressCandidate, "", "hex address of the delegator") - fsDelegator.String(FlagAddressDelegator, "", "hex address of the delegator") -} - -//TODO refactor to common functionality -func getNamePassword() (name, passphrase string, err error) { - name = viper.GetString(client.FlagName) - buf := client.BufferStdin() - prompt := fmt.Sprintf("Password to sign with '%s':", name) - passphrase, err = client.GetPassword(prompt, buf) - return -} - -//_________________________________________________________________________________________ - // create declare candidacy command func GetCmdDeclareCandidacy(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ @@ -114,6 +66,7 @@ func GetCmdDeclareCandidacy(cdc *wire.Codec) *cobra.Command { cmd.Flags().AddFlagSet(fsPk) cmd.Flags().AddFlagSet(fsAmount) + cmd.Flags().AddFlagSet(fsDescription) cmd.Flags().AddFlagSet(fsCandidate) return cmd } @@ -156,6 +109,7 @@ func GetCmdEditCandidacy(cdc *wire.Codec) *cobra.Command { }, } + cmd.Flags().AddFlagSet(fsDescription) cmd.Flags().AddFlagSet(fsCandidate) return cmd } @@ -200,6 +154,7 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { cmd.Flags().AddFlagSet(fsAmount) cmd.Flags().AddFlagSet(fsDelegator) + cmd.Flags().AddFlagSet(fsCandidate) return cmd } @@ -253,6 +208,7 @@ func GetCmdUnbond(cdc *wire.Codec) *cobra.Command { cmd.Flags().AddFlagSet(fsShares) cmd.Flags().AddFlagSet(fsDelegator) + cmd.Flags().AddFlagSet(fsCandidate) return cmd } diff --git a/x/stake/types.go b/x/stake/types.go index b0dbc0b1f..9f7d97ae5 100644 --- a/x/stake/types.go +++ b/x/stake/types.go @@ -153,7 +153,7 @@ func (v Validator) abciValidatorZero(cdc *wire.Codec) abci.Validator { // pubKey. // TODO better way of managing space type DelegatorBond struct { - DelegatorAddr sdk.Address `json:"delegatoraddr"` + DelegatorAddr sdk.Address `json:"delegator_addr"` CandidateAddr sdk.Address `json:"candidate_addr"` Shares sdk.Rat `json:"shares"` } From 2994af56c9589711c192cf7ef8a4811567c84771 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 18 Apr 2018 12:36:55 -0400 Subject: [PATCH 22/71] gaia new error codetype --- cmd/gaia/app/app.go | 15 +++++++--- cmd/gaia/app/app_test.go | 64 ++++++++++++++-------------------------- x/stake/keeper.go | 2 +- x/stake/test_common.go | 2 +- 4 files changed, 35 insertions(+), 48 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 0c9ef8b55..57a5d672c 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -37,6 +37,9 @@ type GaiaApp struct { coinKeeper bank.CoinKeeper ibcMapper ibc.IBCMapper stakeKeeper stake.Keeper + + // Handle fees + feeHandler sdk.FeeHandler } func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp { @@ -59,19 +62,23 @@ func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp { // add handlers app.coinKeeper = bank.NewCoinKeeper(app.accountMapper) - app.ibcMapper = ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore) - app.stakeKeeper = stake.NewKeeper(app.cdc, app.capKeyStakeStore, app.coinKeeper) + app.ibcMapper = ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore, app.RegisterCodespace(ibc.DefaultCodespace)) + app.stakeKeeper = stake.NewKeeper(app.cdc, app.capKeyStakeStore, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace)) + app.Router(). AddRoute("bank", bank.NewHandler(app.coinKeeper)). AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.coinKeeper)). AddRoute("stake", stake.NewHandler(app.stakeKeeper)) + // Define the feeHandler. + app.feeHandler = auth.BurnFeeHandler + // initialize BaseApp app.SetTxDecoder(app.txDecoder) app.SetInitChainer(app.initChainer) app.SetEndBlocker(stake.NewEndBlocker(app.stakeKeeper)) app.MountStoresIAVL(app.capKeyMainStore, app.capKeyAccountStore, app.capKeyIBCStore, app.capKeyStakeStore) - app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper)) + app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeHandler)) err := app.LoadLatestVersion(app.capKeyMainStore) if err != nil { cmn.Exit(err.Error()) @@ -113,7 +120,7 @@ func (app *GaiaApp) txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) { // are registered by MakeTxCodec err := app.cdc.UnmarshalBinary(txBytes, &tx) if err != nil { - return nil, sdk.ErrTxDecode("").TraceCause(err, "") + return nil, sdk.ErrTxDecode("").Trace(err.Error()) } return tx, nil } diff --git a/cmd/gaia/app/app_test.go b/cmd/gaia/app/app_test.go index 5c8450138..bd339c75a 100644 --- a/cmd/gaia/app/app_test.go +++ b/cmd/gaia/app/app_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/examples/basecoin/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/bank" @@ -138,48 +139,27 @@ func TestMsgs(t *testing.T) { } } -func TestSortGenesis(t *testing.T) { - logger, dbs := loggerAndDB() - gapp := NewGaiaApp(logger, dbs) +func setGenesisAccounts(gapp *GaiaApp, accs ...auth.BaseAccount) error { + genaccs := make([]*types.GenesisAccount, len(accs)) + for i, acc := range accs { + genaccs[i] = types.NewGenesisAccount(&types.AppAccount{acc, accName}) + } - // Note the order: the coins are unsorted! - coinDenom1, coinDenom2 := "foocoin", "barcoin" + genesisState := types.GenesisState{ + Accounts: genaccs, + } - str := `{ - "accounts": [{ - "address": "%s", - "coins": [ - { - "denom": "%s", - "amount": 10 - }, - { - "denom": "%s", - "amount": 20 - } - ] - }] - }` - genState := fmt.Sprintf(str, addr1.String(), coinDenom1, coinDenom2) + stateBytes, err := json.MarshalIndent(genesisState, "", "\t") + if err != nil { + return err + } // Initialize the chain vals := []abci.Validator{} - gapp.InitChain(abci.RequestInitChain{vals, []byte(genState)}) + gapp.InitChain(abci.RequestInitChain{vals, stateBytes}) gapp.Commit() - // Unsorted coins means invalid - err := sendMsg5.ValidateBasic() - require.Equal(t, sdk.CodeInvalidCoins, err.ABCICode(), err.ABCILog()) - - // Sort coins, should be valid - sendMsg5.Inputs[0].Coins.Sort() - sendMsg5.Outputs[0].Coins.Sort() - err = sendMsg5.ValidateBasic() - require.Nil(t, err) - - // Ensure we can send - require.Nil(t, setGenesis(gapp)) // initialize the pool - SignCheckDeliver(t, gapp, sendMsg5, []int64{0}, true, priv1) + return nil } func TestGenesis(t *testing.T) { @@ -247,7 +227,7 @@ func TestSendMsgWithAccounts(t *testing.T) { tx.Signatures[0].Sequence = 1 res := gapp.Deliver(tx) - assert.Equal(t, sdk.CodeUnauthorized, res.Code, res.Log) + assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log) // resigning the tx with the bumped sequence should work SignCheckDeliver(t, gapp, sendMsg1, []int64{1}, true, priv1) @@ -498,18 +478,18 @@ func SignCheckDeliver(t *testing.T, gapp *GaiaApp, msg sdk.Msg, seq []int64, exp // Run a Check res := gapp.Check(tx) if expPass { - require.Equal(t, sdk.CodeOK, res.Code, res.Log) + require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) } else { - require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log) } // Simulate a Block gapp.BeginBlock(abci.RequestBeginBlock{}) res = gapp.Deliver(tx) if expPass { - require.Equal(t, sdk.CodeOK, res.Code, res.Log) + require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) } else { - require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log) } gapp.EndBlock(abci.RequestEndBlock{}) @@ -530,9 +510,9 @@ func SignDeliver(t *testing.T, gapp *GaiaApp, msg sdk.Msg, seq []int64, expPass gapp.BeginBlock(abci.RequestBeginBlock{}) res := gapp.Deliver(tx) if expPass { - require.Equal(t, sdk.CodeOK, res.Code, res.Log) + require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) } else { - require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log) } gapp.EndBlock(abci.RequestEndBlock{}) } diff --git a/x/stake/keeper.go b/x/stake/keeper.go index c2b054eba..751b84017 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -23,7 +23,7 @@ type Keeper struct { codespace sdk.CodespaceType } -func NewKeeper(ctx sdk.Context, cdc *wire.Codec, key sdk.StoreKey, ck bank.CoinKeeper, codespace sdk.CodespaceType) Keeper { +func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.CoinKeeper, codespace sdk.CodespaceType) Keeper { keeper := Keeper{ storeKey: key, cdc: cdc, diff --git a/x/stake/test_common.go b/x/stake/test_common.go index 75781777a..1de86c912 100644 --- a/x/stake/test_common.go +++ b/x/stake/test_common.go @@ -140,7 +140,7 @@ func createTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context &auth.BaseAccount{}, // prototype ).Seal() ck := bank.NewCoinKeeper(accountMapper) - keeper := NewKeeper(ctx, cdc, keyStake, ck, DefaultCodespace) + keeper := NewKeeper(cdc, keyStake, ck, DefaultCodespace) keeper.setPool(ctx, initialPool()) keeper.setParams(ctx, defaultParams()) From 8c59ced191c96e51355aca0a79b20488f341b429 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 18 Apr 2018 12:39:59 -0400 Subject: [PATCH 23/71] changelog --- CHANGELOG.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cfbe82dd..d31ce6cbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,13 @@ FEATURES: * Add CacheContext * Add auto sequencing to client * Add FeeHandler to ante handler +* Gaia stake commands include, DeclareCandidacy, EditCandidacy, Delegate, Unbond +* MountStoreWithDB without providing a custom store works. BREAKING CHANGES * Remove go-wire, use go-amino +* Gaia simple-staking bond and unbond functions replaced * [store] Add `SubspaceIterator` and `ReverseSubspaceIterator` to `KVStore` interface * [basecoin] NewBasecoinApp takes a `dbm.DB` and uses namespaced DBs for substores * All module keepers now require a codespace, see basecoin or democoin for usage @@ -18,12 +21,6 @@ BREAKING CHANGES BUG FIXES * Gaia now uses stake, ported from github.com/cosmos/gaia -FEATURES: - -* Add CacheContext -* Gaia stake commands include, DeclareCandidacy, EditCandidacy, Delegate, Unbond -* MountStoreWithDB without providing a custom store works. - ## 0.14.1 (April 9, 2018) BUG FIXES From be93b760e779c21925dd4d76d0b081d9797ec1a6 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 18 Apr 2018 13:23:47 -0400 Subject: [PATCH 24/71] circle make install int --- .circleci/config.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6754ebc05..c6cb56a1e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,7 +31,7 @@ jobs: name: binaries command: | export PATH="$GOBIN:$PATH" - make build + make install - persist_to_workspace: root: /tmp/workspace paths: @@ -59,6 +59,8 @@ jobs: - run: name: Run tests command: | + export PATH="$GOBIN:$PATH" + make install for pkg in $(go list github.com/cosmos/cosmos-sdk/... | grep -v /vendor/ | circleci tests split --split-by=timings); do id=$(basename "$pkg") From 6f65867154f73051a53be6b8cc0cdd59282782e6 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 18 Apr 2018 14:06:49 -0400 Subject: [PATCH 25/71] comment out go-bash race condition --- .circleci/config.yml | 2 +- cmd/gaia/{cmd => cli_test}/cli_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename cmd/gaia/{cmd => cli_test}/cli_test.go (99%) diff --git a/.circleci/config.yml b/.circleci/config.yml index c6cb56a1e..47cb5661d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -61,7 +61,7 @@ jobs: command: | export PATH="$GOBIN:$PATH" make install - for pkg in $(go list github.com/cosmos/cosmos-sdk/... | grep -v /vendor/ | circleci tests split --split-by=timings); do + for pkg in $(go list github.com/cosmos/cosmos-sdk/... | grep -v /vendor/ | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test | circleci tests split --split-by=timings); do id=$(basename "$pkg") go test -timeout 5m -race -coverprofile=/tmp/workspace/profiles/$id.out -covermode=atomic "$pkg" diff --git a/cmd/gaia/cmd/cli_test.go b/cmd/gaia/cli_test/cli_test.go similarity index 99% rename from cmd/gaia/cmd/cli_test.go rename to cmd/gaia/cli_test/cli_test.go index b1af5f7b7..4b4a17dcd 100644 --- a/cmd/gaia/cmd/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -1,4 +1,4 @@ -package common +package clitest import ( "encoding/hex" From d36efcd4171ab8c747e9672e87a06a9f6b9ecd97 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 18 Apr 2018 14:21:07 -0400 Subject: [PATCH 26/71] unbond in gaia cli test --- cmd/gaia/cli_test/cli_test.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 4b4a17dcd..0d9a89578 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -93,19 +93,19 @@ func TestGaiaCLIDeclareCandidacy(t *testing.T) { // TODO figure out why this times out with connection refused errors in go-bash // unbond a single share - //unbondStr := fmt.Sprintf("gaiacli unbond %v", flags) - //unbondStr += fmt.Sprintf(" --name=%v", "foo") - //unbondStr += fmt.Sprintf(" --address-candidate=%v", fooAddr) - //unbondStr += fmt.Sprintf(" --address-delegator=%v", fooAddr) - //unbondStr += fmt.Sprintf(" --shares=%v", "1") - //unbondStr += fmt.Sprintf(" --sequence=%v", "1") - //fmt.Printf("debug unbondStr: %v\n", unbondStr) - //executeWrite(t, unbondStr, pass) - //time.Sleep(time.Second * 3) // waiting for some blocks to pass - //fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) - //assert.Equal(t, int64(99998), fooAcc.GetCoins().AmountOf("fermion")) - //candidate = executeGetCandidate(t, fmt.Sprintf("gaiacli candidate %v --address-candidate=%v", flags, fooAddr)) - //assert.Equal(t, int64(2), candidate.Assets.Evaluate()) + unbondStr := fmt.Sprintf("gaiacli unbond %v", flags) + unbondStr += fmt.Sprintf(" --name=%v", "foo") + unbondStr += fmt.Sprintf(" --address-candidate=%v", fooAddr) + unbondStr += fmt.Sprintf(" --address-delegator=%v", fooAddr) + unbondStr += fmt.Sprintf(" --shares=%v", "1") + unbondStr += fmt.Sprintf(" --sequence=%v", "1") + fmt.Printf("debug unbondStr: %v\n", unbondStr) + executeWrite(t, unbondStr, pass) + time.Sleep(time.Second * 3) // waiting for some blocks to pass + fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) + assert.Equal(t, int64(99998), fooAcc.GetCoins().AmountOf("fermion")) + candidate = executeGetCandidate(t, fmt.Sprintf("gaiacli candidate %v --address-candidate=%v", flags, fooAddr)) + assert.Equal(t, int64(2), candidate.Assets.Evaluate()) } func executeWrite(t *testing.T, cmdStr string, writes ...string) { From 0e8c3e4a5b3a806b0c3a200570a57e7258eb1239 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 18 Apr 2018 14:32:40 -0400 Subject: [PATCH 27/71] remove gaia basecoin reference --- cmd/gaia/app/app_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/gaia/app/app_test.go b/cmd/gaia/app/app_test.go index bd339c75a..b3350b503 100644 --- a/cmd/gaia/app/app_test.go +++ b/cmd/gaia/app/app_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/examples/basecoin/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/bank" @@ -139,14 +138,15 @@ func TestMsgs(t *testing.T) { } } -func setGenesisAccounts(gapp *GaiaApp, accs ...auth.BaseAccount) error { - genaccs := make([]*types.GenesisAccount, len(accs)) +func setGenesisAccounts(gapp *GaiaApp, accs ...*auth.BaseAccount) error { + genaccs := make([]GenesisAccount, len(accs)) for i, acc := range accs { - genaccs[i] = types.NewGenesisAccount(&types.AppAccount{acc, accName}) + genaccs[i] = NewGenesisAccount(acc) } - genesisState := types.GenesisState{ - Accounts: genaccs, + genesisState := GenesisState{ + Accounts: genaccs, + StakeData: stake.GetDefaultGenesisState(), } stateBytes, err := json.MarshalIndent(genesisState, "", "\t") From 1f9184a24b91185a90240312389c980c94ddb188 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 18 Apr 2018 15:39:32 -0400 Subject: [PATCH 28/71] basic go-linting // moved corecontext --- baseapp/baseapp.go | 3 +-- baseapp/baseapp_test.go | 2 +- client/{core/core.go => context/helpers.go} | 10 +++++----- client/{core/context.go => context/types.go} | 3 ++- client/context/viper.go | 8 ++++---- client/lcd/helpers.go | 5 ++--- client/lcd/lcd_test.go | 4 ++-- 7 files changed, 17 insertions(+), 18 deletions(-) rename client/{core/core.go => context/helpers.go} (95%) rename client/{core/context.go => context/types.go} (96%) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 3eebb1eb4..827408b20 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -114,7 +114,6 @@ func (app *BaseApp) SetEndBlocker(endBlocker sdk.EndBlocker) { func (app *BaseApp) SetAnteHandler(ah sdk.AnteHandler) { app.anteHandler = ah } - func (app *BaseApp) Router() Router { return app.router } // load latest application version @@ -337,7 +336,7 @@ func (app *BaseApp) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) { } } -// Mostly for testing +// nolint- Mostly for testing func (app *BaseApp) Check(tx sdk.Tx) (result sdk.Result) { return app.runTx(true, nil, tx) } diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index 78fd50464..f70521009 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -240,7 +240,7 @@ func TestDeliverTx(t *testing.T) { height := int64((counter / txPerHeight) + 1) assert.Equal(t, height, thisHeader.Height) - counter += 1 + counter++ return sdk.Result{} }) diff --git a/client/core/core.go b/client/context/helpers.go similarity index 95% rename from client/core/core.go rename to client/context/helpers.go index 2a1b2736a..509ec09dc 100644 --- a/client/core/core.go +++ b/client/context/helpers.go @@ -1,4 +1,4 @@ -package core +package context import ( "fmt" @@ -141,17 +141,17 @@ func (ctx CoreContext) SignBuildBroadcast(name string, msg sdk.Msg, cdc *wire.Co } // get the next sequence for the account address -func (c CoreContext) NextSequence(address []byte) (int64, error) { - if c.Decoder == nil { +func (ctx CoreContext) NextSequence(address []byte) (int64, error) { + if ctx.Decoder == nil { return 0, errors.New("AccountDecoder required but not provided") } - res, err := c.Query(address, c.AccountStore) + res, err := ctx.Query(address, ctx.AccountStore) if err != nil { return 0, err } - account, err := c.Decoder(res) + account, err := ctx.Decoder(res) if err != nil { panic(err) } diff --git a/client/core/context.go b/client/context/types.go similarity index 96% rename from client/core/context.go rename to client/context/types.go index fac60b553..e580027d6 100644 --- a/client/core/context.go +++ b/client/context/types.go @@ -1,4 +1,4 @@ -package core +package context import ( rpcclient "github.com/tendermint/tendermint/rpc/client" @@ -6,6 +6,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +// typical context created in sdk modules for transactions/queries type CoreContext struct { ChainID string Height int64 diff --git a/client/context/viper.go b/client/context/viper.go index c3b0369d9..7e82f7ad9 100644 --- a/client/context/viper.go +++ b/client/context/viper.go @@ -2,6 +2,7 @@ package context import ( "fmt" + "github.com/spf13/viper" tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" @@ -9,11 +10,10 @@ import ( tmtypes "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/core" ) // NewCoreContextFromViper - return a new context with parameters from the command line -func NewCoreContextFromViper() core.CoreContext { +func NewCoreContextFromViper() CoreContext { nodeURI := viper.GetString(client.FlagNode) var rpc rpcclient.Client if nodeURI != "" { @@ -27,7 +27,7 @@ func NewCoreContextFromViper() core.CoreContext { chainID = def } } - return core.CoreContext{ + return CoreContext{ ChainID: chainID, Height: viper.GetInt64(client.FlagHeight), TrustNode: viper.GetBool(client.FlagTrustNode), @@ -54,7 +54,7 @@ func defaultChainID() (string, error) { } // EnsureSequence - automatically set sequence number if none provided -func EnsureSequence(ctx core.CoreContext) (core.CoreContext, error) { +func EnsureSequence(ctx CoreContext) (CoreContext, error) { if viper.IsSet(client.FlagSequence) { return ctx, nil } diff --git a/client/lcd/helpers.go b/client/lcd/helpers.go index 64814a5fc..a64d44dfa 100644 --- a/client/lcd/helpers.go +++ b/client/lcd/helpers.go @@ -28,10 +28,9 @@ func waitForRPC() { _, err := client.Call("status", map[string]interface{}{}, result) if err == nil { return - } else { - fmt.Println("error", err) - time.Sleep(time.Millisecond) } + fmt.Println("error", err) + time.Sleep(time.Millisecond) } } diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index e84ff8e9b..0b5c6b064 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -42,9 +42,9 @@ var ( coinAmount = int64(10000000) // XXX bad globals + name = "test" + password = "0123456789" port string // XXX: but it's the int ... - name string = "test" - password string = "0123456789" seed string sendAddr string ) From d28efaac2784f3d13538bee75f1bc4ce29036899 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 19 Apr 2018 00:49:24 -0400 Subject: [PATCH 29/71] many renames / golint compliance --- client/context/helpers.go | 9 +- client/keys/add.go | 4 + client/keys/delete.go | 3 + client/keys/list.go | 4 +- client/keys/root.go | 1 + client/keys/show.go | 2 + client/keys/update.go | 3 + client/lcd/root.go | 2 +- client/rpc/block.go | 3 + client/rpc/root.go | 5 +- client/rpc/status.go | 2 + client/rpc/validators.go | 16 +- client/tx/broadcast.go | 2 + client/tx/query.go | 51 +++--- client/tx/root.go | 13 +- client/tx/search.go | 40 +++-- client/tx/sign.go | 3 + cmd/gaia/app/app.go | 36 ++--- cmd/gaia/app/app_test.go | 16 +- cmd/gaia/cmd/gaiacli/main.go | 1 - docs/guide.md | 18 +-- examples/basecoin/app/app.go | 12 +- examples/basecoin/app/app_test.go | 18 +-- examples/democoin/app/app.go | 22 +-- examples/democoin/app/app_test.go | 22 +-- examples/democoin/types/account.go | 4 +- examples/democoin/x/cool/commands/tx.go | 20 +-- examples/democoin/x/cool/errors.go | 1 + examples/democoin/x/cool/handler.go | 16 +- examples/democoin/x/cool/keeper.go | 6 +- examples/democoin/x/cool/types.go | 52 +++--- examples/democoin/x/pow/commands/tx.go | 13 +- examples/democoin/x/pow/errors.go | 31 ++-- examples/democoin/x/pow/handler.go | 7 +- examples/democoin/x/pow/handler_test.go | 10 +- examples/democoin/x/pow/keeper.go | 69 ++++---- examples/democoin/x/pow/keeper_test.go | 6 +- examples/democoin/x/pow/mine.go | 5 +- examples/democoin/x/pow/types.go | 29 ++-- examples/democoin/x/pow/types_test.go | 44 +++--- examples/kvstore/main.go | 7 +- server/init.go | 4 +- server/tm_cmds.go | 6 +- server/util.go | 2 + store/cachekvstore.go | 6 +- store/cachekvstore_test.go | 16 +- store/cachemergeiterator.go | 3 +- store/dbstoreadapter.go | 2 +- store/firstlast.go | 4 +- store/iavlstore.go | 1 + store/iavlstore_test.go | 24 +-- store/rootmultistore.go | 3 +- store/types.go | 1 + types/errors.go | 2 + version/command.go | 6 +- wire/wire.go | 3 + x/auth/commands/account.go | 1 + x/auth/context.go | 2 + x/auth/mapper.go | 15 +- x/auth/rest/query.go | 17 +- x/auth/rest/root.go | 11 -- x/bank/commands/sendtx.go | 87 +++++------ x/bank/errors.go | 2 +- x/bank/handler.go | 20 +-- x/bank/keeper.go | 200 ++++++++++++------------ x/bank/keeper_test.go | 8 +- x/bank/msgs.go | 65 +++----- x/bank/msgs_test.go | 107 +++++-------- x/bank/rest/root.go | 14 -- x/bank/rest/sendtx.go | 8 +- x/bank/wire.go | 4 +- x/ibc/commands/ibctx.go | 65 ++++---- x/ibc/commands/relay.go | 9 +- x/ibc/errors.go | 6 +- x/ibc/handler.go | 6 +- x/ibc/ibc_test.go | 12 +- x/ibc/mapper.go | 23 +-- x/ibc/rest/root.go | 14 -- x/ibc/rest/transfer.go | 9 +- x/ibc/types.go | 44 +++--- x/ibc/types_test.go | 3 +- x/simplestake/commands/commands.go | 113 ++++++------- x/simplestake/errors.go | 5 +- x/simplestake/handler.go | 12 +- x/simplestake/keeper.go | 7 +- x/simplestake/keeper_test.go | 4 +- x/simplestake/msgs.go | 66 +++----- x/simplestake/msgs_test.go | 8 +- x/stake/commands/tx.go | 32 +--- x/stake/keeper.go | 4 +- x/stake/msg.go | 15 -- x/stake/test_common.go | 6 +- 92 files changed, 792 insertions(+), 943 deletions(-) delete mode 100644 x/auth/rest/root.go delete mode 100644 x/bank/rest/root.go delete mode 100644 x/ibc/rest/root.go diff --git a/client/context/helpers.go b/client/context/helpers.go index 509ec09dc..ded70cb5c 100644 --- a/client/context/helpers.go +++ b/client/context/helpers.go @@ -126,7 +126,14 @@ func (ctx CoreContext) SignAndBuild(name, passphrase string, msg sdk.Msg, cdc *w } // sign and build the transaction from the msg -func (ctx CoreContext) SignBuildBroadcast(name string, msg sdk.Msg, cdc *wire.Codec) (*ctypes.ResultBroadcastTxCommit, error) { +func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msg sdk.Msg, cdc *wire.Codec) (res *ctypes.ResultBroadcastTxCommit, err error) { + + // default to next sequence number if none provided + ctx, err = EnsureSequence(ctx) + if err != nil { + return nil, err + } + passphrase, err := ctx.GetPassphraseFromStdin(name) if err != nil { return nil, err diff --git a/client/keys/add.go b/client/keys/add.go index d68983028..da368a3a6 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -135,14 +135,17 @@ func printCreate(info keys.Info, seed string) { } } +///////////////////////////// // REST +// new key request REST body type NewKeyBody struct { Name string `json:"name"` Password string `json:"password"` Seed string `json:"seed"` } +// add new key REST handler func AddNewKeyRequestHandler(w http.ResponseWriter, r *http.Request) { var kb keys.Keybase var m NewKeyBody @@ -208,6 +211,7 @@ func getSeed(algo keys.CryptoAlgo) string { return seed } +// Seed REST request handler func SeedRequestHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) algoType := vars["type"] diff --git a/client/keys/delete.go b/client/keys/delete.go index b0327771b..cd2016bd2 100644 --- a/client/keys/delete.go +++ b/client/keys/delete.go @@ -48,12 +48,15 @@ func runDeleteCmd(cmd *cobra.Command, args []string) error { return nil } +//////////////////////// // REST +// delete key request REST body type DeleteKeyBody struct { Password string `json:"password"` } +// delete key REST handler func DeleteKeyRequestHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) name := vars["name"] diff --git a/client/keys/list.go b/client/keys/list.go index 97ccf8a90..26e06d9da 100644 --- a/client/keys/list.go +++ b/client/keys/list.go @@ -31,8 +31,10 @@ func runListCmd(cmd *cobra.Command, args []string) error { return err } -//REST +///////////////////////// +// REST +// query key list REST handler func QueryKeysRequestHandler(w http.ResponseWriter, r *http.Request) { kb, err := GetKeyBase() if err != nil { diff --git a/client/keys/root.go b/client/keys/root.go index 48b50d5e9..c8f6aea69 100644 --- a/client/keys/root.go +++ b/client/keys/root.go @@ -29,6 +29,7 @@ func Commands() *cobra.Command { return cmd } +// resgister REST routes func RegisterRoutes(r *mux.Router) { r.HandleFunc("/keys", QueryKeysRequestHandler).Methods("GET") r.HandleFunc("/keys", AddNewKeyRequestHandler).Methods("POST") diff --git a/client/keys/show.go b/client/keys/show.go index bb60b5bc0..76966cd19 100644 --- a/client/keys/show.go +++ b/client/keys/show.go @@ -42,8 +42,10 @@ func runShowCmd(cmd *cobra.Command, args []string) error { return err } +/////////////////////////// // REST +// get key REST handler func GetKeyRequestHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) name := vars["name"] diff --git a/client/keys/update.go b/client/keys/update.go index d95be78bf..c0edc5fe6 100644 --- a/client/keys/update.go +++ b/client/keys/update.go @@ -53,13 +53,16 @@ func runUpdateCmd(cmd *cobra.Command, args []string) error { return nil } +/////////////////////// // REST +// update key request REST body type UpdateKeyBody struct { NewPassword string `json:"new_password"` OldPassword string `json:"old_password"` } +// update key REST handler func UpdateKeyRequestHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) name := vars["name"] diff --git a/client/lcd/root.go b/client/lcd/root.go index 9464081e0..81eca333e 100644 --- a/client/lcd/root.go +++ b/client/lcd/root.go @@ -66,7 +66,7 @@ func startRESTServerFn(cdc *wire.Codec) func(cmd *cobra.Command, args []string) func createHandler(cdc *wire.Codec) http.Handler { r := mux.NewRouter() - r.HandleFunc("/version", version.VersionRequestHandler).Methods("GET") + r.HandleFunc("/version", version.RequestHandler).Methods("GET") kb, err := keys.GetKeyBase() //XXX if err != nil { diff --git a/client/rpc/block.go b/client/rpc/block.go index 8df26edda..200dc668e 100644 --- a/client/rpc/block.go +++ b/client/rpc/block.go @@ -55,6 +55,7 @@ func getBlock(height *int64) ([]byte, error) { return output, nil } +// get the current blockchain height func GetChainHeight() (int64, error) { node, err := context.NewCoreContextFromViper().GetNode() if err != nil { @@ -94,6 +95,7 @@ func printBlock(cmd *cobra.Command, args []string) error { // REST +// REST handler to get a block func BlockRequestHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) height, err := strconv.ParseInt(vars["height"], 10, 64) @@ -117,6 +119,7 @@ func BlockRequestHandler(w http.ResponseWriter, r *http.Request) { w.Write(output) } +// REST handler to get the latest block func LatestBlockRequestHandler(w http.ResponseWriter, r *http.Request) { height, err := GetChainHeight() if err != nil { diff --git a/client/rpc/root.go b/client/rpc/root.go index 8b04c044f..43e9097f0 100644 --- a/client/rpc/root.go +++ b/client/rpc/root.go @@ -44,11 +44,12 @@ func initClientCommand() *cobra.Command { return cmd } +// Register REST endpoints func RegisterRoutes(r *mux.Router) { r.HandleFunc("/node_info", NodeInfoRequestHandler).Methods("GET") r.HandleFunc("/syncing", NodeSyncingRequestHandler).Methods("GET") r.HandleFunc("/blocks/latest", LatestBlockRequestHandler).Methods("GET") r.HandleFunc("/blocks/{height}", BlockRequestHandler).Methods("GET") - r.HandleFunc("/validatorsets/latest", LatestValidatorsetRequestHandler).Methods("GET") - r.HandleFunc("/validatorsets/{height}", ValidatorsetRequestHandler).Methods("GET") + r.HandleFunc("/validatorsets/latest", LatestValidatorSetRequestHandler).Methods("GET") + r.HandleFunc("/validatorsets/{height}", ValidatorSetRequestHandler).Methods("GET") } diff --git a/client/rpc/status.go b/client/rpc/status.go index 83fc01c56..3b143d9c5 100644 --- a/client/rpc/status.go +++ b/client/rpc/status.go @@ -51,6 +51,7 @@ func printNodeStatus(cmd *cobra.Command, args []string) error { // REST +// REST handler for node info func NodeInfoRequestHandler(w http.ResponseWriter, r *http.Request) { status, err := getNodeStatus() if err != nil { @@ -69,6 +70,7 @@ func NodeInfoRequestHandler(w http.ResponseWriter, r *http.Request) { w.Write(output) } +// REST handler for node syncing func NodeSyncingRequestHandler(w http.ResponseWriter, r *http.Request) { status, err := getNodeStatus() if err != nil { diff --git a/client/rpc/validators.go b/client/rpc/validators.go index cdaf3be93..6937e4a89 100644 --- a/client/rpc/validators.go +++ b/client/rpc/validators.go @@ -12,6 +12,8 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" ) +// TODO these next two functions feel kinda hacky based on their placement + func validatorCommand() *cobra.Command { cmd := &cobra.Command{ Use: "validatorset ", @@ -24,7 +26,7 @@ func validatorCommand() *cobra.Command { return cmd } -func GetValidators(height *int64) ([]byte, error) { +func getValidators(height *int64) ([]byte, error) { // get the node node, err := context.NewCoreContextFromViper().GetNode() if err != nil { @@ -59,7 +61,7 @@ func printValidators(cmd *cobra.Command, args []string) error { } } - output, err := GetValidators(height) + output, err := getValidators(height) if err != nil { return err } @@ -70,7 +72,8 @@ func printValidators(cmd *cobra.Command, args []string) error { // REST -func ValidatorsetRequestHandler(w http.ResponseWriter, r *http.Request) { +// Validator Set at a height REST handler +func ValidatorSetRequestHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) height, err := strconv.ParseInt(vars["height"], 10, 64) if err != nil { @@ -84,7 +87,7 @@ func ValidatorsetRequestHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte("ERROR: Requested block height is bigger then the chain length.")) return } - output, err := GetValidators(&height) + output, err := getValidators(&height) if err != nil { w.WriteHeader(500) w.Write([]byte(err.Error())) @@ -93,14 +96,15 @@ func ValidatorsetRequestHandler(w http.ResponseWriter, r *http.Request) { w.Write(output) } -func LatestValidatorsetRequestHandler(w http.ResponseWriter, r *http.Request) { +// Latest Validator Set REST handler +func LatestValidatorSetRequestHandler(w http.ResponseWriter, r *http.Request) { height, err := GetChainHeight() if err != nil { w.WriteHeader(500) w.Write([]byte(err.Error())) return } - output, err := GetValidators(&height) + output, err := getValidators(&height) if err != nil { w.WriteHeader(500) w.Write([]byte(err.Error())) diff --git a/client/tx/broadcast.go b/client/tx/broadcast.go index 998e2b0f1..9e9eaae70 100644 --- a/client/tx/broadcast.go +++ b/client/tx/broadcast.go @@ -7,10 +7,12 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" ) +// Tx Broadcast Body type BroadcastTxBody struct { TxBytes string `json="tx"` } +// BroadcastTx REST Handler func BroadcastTxRequestHandler(w http.ResponseWriter, r *http.Request) { var m BroadcastTxBody diff --git a/client/tx/query.go b/client/tx/query.go index 63ab2ff04..cc252bacc 100644 --- a/client/tx/query.go +++ b/client/tx/query.go @@ -21,19 +21,37 @@ import ( ) // Get the default command for a tx query -func QueryTxCmd(cmdr commander) *cobra.Command { +func QueryTxCmd(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "tx [hash]", Short: "Matches this txhash over all committed blocks", - RunE: cmdr.queryAndPrintTx, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) != 1 || len(args[0]) == 0 { + return errors.New("You must provide a tx hash") + } + + // find the key to look up the account + hashHexStr := args[0] + trustNode := viper.GetBool(client.FlagTrustNode) + + output, err := queryTx(cdc, hashHexStr, trustNode) + if err != nil { + return err + } + fmt.Println(string(output)) + + return nil + }, } + cmd.Flags().StringP(client.FlagNode, "n", "tcp://localhost:46657", "Node to connect to") + // TODO: change this to false when we can cmd.Flags().Bool(client.FlagTrustNode, true, "Don't verify proofs for responses") return cmd } -func (c commander) queryTx(hashHexStr string, trustNode bool) ([]byte, error) { +func queryTx(cdc *wire.Codec, hashHexStr string, trustNode bool) ([]byte, error) { hash, err := hex.DecodeString(hashHexStr) if err != nil { return nil, err @@ -49,7 +67,7 @@ func (c commander) queryTx(hashHexStr string, trustNode bool) ([]byte, error) { if err != nil { return nil, err } - info, err := formatTxResult(c.cdc, res) + info, err := formatTxResult(cdc, res) if err != nil { return nil, err } @@ -88,31 +106,10 @@ func parseTx(cdc *wire.Codec, txBytes []byte) (sdk.Tx, error) { return tx, nil } -// CMD - -// command to query for a transaction -func (c commander) queryAndPrintTx(cmd *cobra.Command, args []string) error { - if len(args) != 1 || len(args[0]) == 0 { - return errors.New("You must provide a tx hash") - } - - // find the key to look up the account - hashHexStr := args[0] - trustNode := viper.GetBool(client.FlagTrustNode) - - output, err := c.queryTx(hashHexStr, trustNode) - if err != nil { - return err - } - fmt.Println(string(output)) - - return nil -} - // REST +// transaction query REST handler func QueryTxRequestHandler(cdc *wire.Codec) func(http.ResponseWriter, *http.Request) { - c := commander{cdc} return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) hashHexStr := vars["hash"] @@ -122,7 +119,7 @@ func QueryTxRequestHandler(cdc *wire.Codec) func(http.ResponseWriter, *http.Requ trustNode = true } - output, err := c.queryTx(hashHexStr, trustNode) + output, err := queryTx(cdc, hashHexStr, trustNode) if err != nil { w.WriteHeader(500) w.Write([]byte(err.Error())) diff --git a/client/tx/root.go b/client/tx/root.go index f7d2cf945..2a87113b3 100644 --- a/client/tx/root.go +++ b/client/tx/root.go @@ -7,23 +7,18 @@ import ( "github.com/cosmos/cosmos-sdk/wire" ) -// type used to pass around the provided cdc -type commander struct { - cdc *wire.Codec -} - // AddCommands adds a number of tx-query related subcommands func AddCommands(cmd *cobra.Command, cdc *wire.Codec) { - cmdr := commander{cdc} cmd.AddCommand( - SearchTxCmd(cmdr), - QueryTxCmd(cmdr), + SearchTxCmd(cdc), + QueryTxCmd(cdc), ) } +// register REST routes func RegisterRoutes(r *mux.Router, cdc *wire.Codec) { - // r.HandleFunc("/txs", SearchTxRequestHandler(cdc)).Methods("GET") r.HandleFunc("/txs/{hash}", QueryTxRequestHandler(cdc)).Methods("GET") + // r.HandleFunc("/txs", SearchTxRequestHandler(cdc)).Methods("GET") // r.HandleFunc("/txs/sign", SignTxRequstHandler).Methods("POST") // r.HandleFunc("/txs/broadcast", BroadcastTxRequestHandler).Methods("POST") } diff --git a/client/tx/search.go b/client/tx/search.go index df3be5077..1687d3bbd 100644 --- a/client/tx/search.go +++ b/client/tx/search.go @@ -22,13 +22,24 @@ const ( ) // default client command to search through tagged transactions -func SearchTxCmd(cmdr commander) *cobra.Command { +func SearchTxCmd(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "txs", Short: "Search for all transactions that match the given tags", - RunE: cmdr.searchAndPrintTx, + RunE: func(cmd *cobra.Command, args []string) error { + tags := viper.GetStringSlice(flagTags) + + output, err := searchTx(cdc, tags) + if err != nil { + return err + } + fmt.Println(string(output)) + return nil + }, } + cmd.Flags().StringP(client.FlagNode, "n", "tcp://localhost:46657", "Node to connect to") + // TODO: change this to false once proofs built in cmd.Flags().Bool(client.FlagTrustNode, true, "Don't verify proofs for responses") cmd.Flags().StringSlice(flagTags, nil, "Tags that must match (may provide multiple)") @@ -36,7 +47,7 @@ func SearchTxCmd(cmdr commander) *cobra.Command { return cmd } -func (c commander) searchTx(tags []string) ([]byte, error) { +func searchTx(cdc *wire.Codec, tags []string) ([]byte, error) { if len(tags) == 0 { return nil, errors.New("Must declare at least one tag to search") } @@ -55,12 +66,12 @@ func (c commander) searchTx(tags []string) ([]byte, error) { return nil, err } - info, err := formatTxResults(c.cdc, res) + info, err := formatTxResults(cdc, res) if err != nil { return nil, err } - output, err := c.cdc.MarshalJSON(info) + output, err := cdc.MarshalJSON(info) if err != nil { return nil, err } @@ -79,24 +90,11 @@ func formatTxResults(cdc *wire.Codec, res []*ctypes.ResultTx) ([]txInfo, error) return out, nil } -// CMD - -func (c commander) searchAndPrintTx(cmd *cobra.Command, args []string) error { - tags := viper.GetStringSlice(flagTags) - - output, err := c.searchTx(tags) - if err != nil { - return err - } - - fmt.Println(string(output)) - return nil -} - +///////////////////////////////////////// // REST +// Search Tx REST Handler func SearchTxRequestHandler(cdc *wire.Codec) func(http.ResponseWriter, *http.Request) { - c := commander{cdc} return func(w http.ResponseWriter, r *http.Request) { tag := r.FormValue("tag") if tag == "" { @@ -106,7 +104,7 @@ func SearchTxRequestHandler(cdc *wire.Codec) func(http.ResponseWriter, *http.Req } tags := []string{tag} - output, err := c.searchTx(tags) + output, err := searchTx(cdc, tags) if err != nil { w.WriteHeader(500) w.Write([]byte(err.Error())) diff --git a/client/tx/sign.go b/client/tx/sign.go index 3a3fff4a0..2d885b049 100644 --- a/client/tx/sign.go +++ b/client/tx/sign.go @@ -8,12 +8,15 @@ import ( keys "github.com/tendermint/go-crypto/keys" ) +// REST request body +// TODO does this need to be exposed? type SignTxBody struct { Name string `json="name"` Password string `json="password"` TxBytes string `json="tx"` } +// sign transaction REST Handler func SignTxRequstHandler(w http.ResponseWriter, r *http.Request) { var kb keys.Keybase var m SignTxBody diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 57a5d672c..e780c08bf 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -27,15 +27,15 @@ type GaiaApp struct { cdc *wire.Codec // keys to access the substores - capKeyMainStore *sdk.KVStoreKey - capKeyAccountStore *sdk.KVStoreKey - capKeyIBCStore *sdk.KVStoreKey - capKeyStakeStore *sdk.KVStoreKey + keyMain *sdk.KVStoreKey + keyAccount *sdk.KVStoreKey + keyIBC *sdk.KVStoreKey + keyStake *sdk.KVStoreKey // Manage getting and setting accounts accountMapper sdk.AccountMapper - coinKeeper bank.CoinKeeper - ibcMapper ibc.IBCMapper + coinKeeper bank.Keeper + ibcMapper ibc.Mapper stakeKeeper stake.Keeper // Handle fees @@ -45,25 +45,25 @@ type GaiaApp struct { func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp { // create your application object var app = &GaiaApp{ - BaseApp: bam.NewBaseApp(appName, logger, db), - cdc: MakeCodec(), - capKeyMainStore: sdk.NewKVStoreKey("main"), - capKeyAccountStore: sdk.NewKVStoreKey("acc"), - capKeyIBCStore: sdk.NewKVStoreKey("ibc"), - capKeyStakeStore: sdk.NewKVStoreKey("stake"), + BaseApp: bam.NewBaseApp(appName, logger, db), + cdc: MakeCodec(), + keyMain: sdk.NewKVStoreKey("main"), + keyAccount: sdk.NewKVStoreKey("acc"), + keyIBC: sdk.NewKVStoreKey("ibc"), + keyStake: sdk.NewKVStoreKey("stake"), } // define the accountMapper app.accountMapper = auth.NewAccountMapper( app.cdc, - app.capKeyMainStore, // target store + app.keyMain, // target store &auth.BaseAccount{}, // prototype ).Seal() // add handlers - app.coinKeeper = bank.NewCoinKeeper(app.accountMapper) - app.ibcMapper = ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore, app.RegisterCodespace(ibc.DefaultCodespace)) - app.stakeKeeper = stake.NewKeeper(app.cdc, app.capKeyStakeStore, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace)) + app.coinKeeper = bank.NewKeeper(app.accountMapper) + app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) + app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace)) app.Router(). AddRoute("bank", bank.NewHandler(app.coinKeeper)). @@ -77,9 +77,9 @@ func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp { app.SetTxDecoder(app.txDecoder) app.SetInitChainer(app.initChainer) app.SetEndBlocker(stake.NewEndBlocker(app.stakeKeeper)) - app.MountStoresIAVL(app.capKeyMainStore, app.capKeyAccountStore, app.capKeyIBCStore, app.capKeyStakeStore) + app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake) app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeHandler)) - err := app.LoadLatestVersion(app.capKeyMainStore) + err := app.LoadLatestVersion(app.keyMain) if err != nil { cmn.Exit(err.Error()) } diff --git a/cmd/gaia/app/app_test.go b/cmd/gaia/app/app_test.go index b3350b503..721215999 100644 --- a/cmd/gaia/app/app_test.go +++ b/cmd/gaia/app/app_test.go @@ -42,12 +42,12 @@ var ( 0, } - sendMsg1 = bank.SendMsg{ + sendMsg1 = bank.MsgSend{ Inputs: []bank.Input{bank.NewInput(addr1, coins)}, Outputs: []bank.Output{bank.NewOutput(addr2, coins)}, } - sendMsg2 = bank.SendMsg{ + sendMsg2 = bank.MsgSend{ Inputs: []bank.Input{bank.NewInput(addr1, coins)}, Outputs: []bank.Output{ bank.NewOutput(addr2, halfCoins), @@ -55,7 +55,7 @@ var ( }, } - sendMsg3 = bank.SendMsg{ + sendMsg3 = bank.MsgSend{ Inputs: []bank.Input{ bank.NewInput(addr1, coins), bank.NewInput(addr4, coins), @@ -66,7 +66,7 @@ var ( }, } - sendMsg4 = bank.SendMsg{ + sendMsg4 = bank.MsgSend{ Inputs: []bank.Input{ bank.NewInput(addr2, coins), }, @@ -75,7 +75,7 @@ var ( }, } - sendMsg5 = bank.SendMsg{ + sendMsg5 = bank.MsgSend{ Inputs: []bank.Input{ bank.NewInput(addr1, manyCoins), }, @@ -191,7 +191,7 @@ func TestGenesis(t *testing.T) { assert.Equal(t, baseAcc, res1) } -func TestSendMsgWithAccounts(t *testing.T) { +func TestMsgSendWithAccounts(t *testing.T) { gapp := newGaiaApp() // Construct some genesis bytes to reflect GaiaAccount @@ -233,7 +233,7 @@ func TestSendMsgWithAccounts(t *testing.T) { SignCheckDeliver(t, gapp, sendMsg1, []int64{1}, true, priv1) } -func TestSendMsgMultipleOut(t *testing.T) { +func TestMsgSendMultipleOut(t *testing.T) { gapp := newGaiaApp() genCoins, err := sdk.ParseCoins("42foocoin") @@ -293,7 +293,7 @@ func TestSengMsgMultipleInOut(t *testing.T) { CheckBalance(t, gapp, addr3, "10foocoin") } -func TestSendMsgDependent(t *testing.T) { +func TestMsgSendDependent(t *testing.T) { gapp := newGaiaApp() genCoins, err := sdk.ParseCoins("42foocoin") diff --git a/cmd/gaia/cmd/gaiacli/main.go b/cmd/gaia/cmd/gaiacli/main.go index 1e5528308..45818b36b 100644 --- a/cmd/gaia/cmd/gaiacli/main.go +++ b/cmd/gaia/cmd/gaiacli/main.go @@ -12,7 +12,6 @@ import ( "github.com/cosmos/cosmos-sdk/client/lcd" "github.com/cosmos/cosmos-sdk/client/rpc" "github.com/cosmos/cosmos-sdk/client/tx" - "github.com/cosmos/cosmos-sdk/version" authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands" bankcmd "github.com/cosmos/cosmos-sdk/x/bank/commands" diff --git a/docs/guide.md b/docs/guide.md index fe28a09cb..9f8329835 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -69,12 +69,12 @@ but this is mostly for convenience and not type-safe. For instance, the `Basecoin` message types are defined in `x/bank/tx.go`: ```go -type SendMsg struct { +type MsgSend struct { Inputs []Input `json:"inputs"` Outputs []Output `json:"outputs"` } -type IssueMsg struct { +type MsgIssue struct { Banker sdk.Address `json:"banker"` Outputs []Output `json:"outputs"` } @@ -83,7 +83,7 @@ type IssueMsg struct { Each specifies the addresses that must sign the message: ```go -func (msg SendMsg) GetSigners() []sdk.Address { +func (msg MsgSend) GetSigners() []sdk.Address { addrs := make([]sdk.Address, len(msg.Inputs)) for i, in := range msg.Inputs { addrs[i] = in.Address @@ -91,7 +91,7 @@ func (msg SendMsg) GetSigners() []sdk.Address { return addrs } -func (msg IssueMsg) GetSigners() []sdk.Address { +func (msg MsgIssue) GetSigners() []sdk.Address { return []sdk.Address{msg.Banker} } ``` @@ -174,13 +174,13 @@ property that it can unmarshal into interface types, but it requires the relevant types to be registered ahead of type. Registration happens on a `Codec` object, so as not to taint the global name space. -For instance, in `Basecoin`, we wish to register the `SendMsg` and `IssueMsg` +For instance, in `Basecoin`, we wish to register the `MsgSend` and `MsgIssue` types: ```go cdc.RegisterInterface((*sdk.Msg)(nil), nil) -cdc.RegisterConcrete(bank.SendMsg{}, "cosmos-sdk/SendMsg", nil) -cdc.RegisterConcrete(bank.IssueMsg{}, "cosmos-sdk/IssueMsg", nil) +cdc.RegisterConcrete(bank.MsgSend{}, "cosmos-sdk/MsgSend", nil) +cdc.RegisterConcrete(bank.MsgIssue{}, "cosmos-sdk/MsgIssue", nil) ``` Note how each concrete type is given a name - these name determine the type's @@ -319,8 +319,8 @@ func NewHandler(am sdk.AccountMapper) sdk.Handler { The quintessential SDK application is Basecoin - a simple multi-asset cryptocurrency. Basecoin consists of a set of accounts stored in a Merkle tree, where each account may have -many coins. There are two message types: SendMsg and IssueMsg. -SendMsg allows coins to be sent around, while IssueMsg allows a +many coins. There are two message types: MsgSend and MsgIssue. +MsgSend allows coins to be sent around, while MsgIssue allows a set of predefined users to issue new coins. ## Conclusion diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index bb3ef05ac..e9f5b6e5a 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -64,8 +64,8 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp { ).Seal() // Add handlers. - coinKeeper := bank.NewCoinKeeper(app.accountMapper) - ibcMapper := ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore, app.RegisterCodespace(ibc.DefaultCodespace)) + coinKeeper := bank.NewKeeper(app.accountMapper) + ibcMapper := ibc.NewMapper(app.cdc, app.capKeyIBCStore, app.RegisterCodespace(ibc.DefaultCodespace)) stakeKeeper := simplestake.NewKeeper(app.capKeyStakingStore, coinKeeper, app.RegisterCodespace(simplestake.DefaultCodespace)) app.Router(). AddRoute("bank", bank.NewHandler(coinKeeper)). @@ -94,12 +94,12 @@ func MakeCodec() *wire.Codec { // Register Msgs cdc.RegisterInterface((*sdk.Msg)(nil), nil) - cdc.RegisterConcrete(bank.SendMsg{}, "basecoin/Send", nil) - cdc.RegisterConcrete(bank.IssueMsg{}, "basecoin/Issue", nil) + cdc.RegisterConcrete(bank.MsgSend{}, "basecoin/Send", nil) + cdc.RegisterConcrete(bank.MsgIssue{}, "basecoin/Issue", nil) cdc.RegisterConcrete(ibc.IBCTransferMsg{}, "basecoin/IBCTransferMsg", nil) cdc.RegisterConcrete(ibc.IBCReceiveMsg{}, "basecoin/IBCReceiveMsg", nil) - cdc.RegisterConcrete(simplestake.BondMsg{}, "basecoin/BondMsg", nil) - cdc.RegisterConcrete(simplestake.UnbondMsg{}, "basecoin/UnbondMsg", nil) + cdc.RegisterConcrete(simplestake.MsgBond{}, "basecoin/BondMsg", nil) + cdc.RegisterConcrete(simplestake.MsgUnbond{}, "basecoin/UnbondMsg", nil) // Register AppAccount cdc.RegisterInterface((*sdk.Account)(nil), nil) diff --git a/examples/basecoin/app/app_test.go b/examples/basecoin/app/app_test.go index bc1735dde..b502aae46 100644 --- a/examples/basecoin/app/app_test.go +++ b/examples/basecoin/app/app_test.go @@ -42,12 +42,12 @@ var ( 0, } - sendMsg1 = bank.SendMsg{ + sendMsg1 = bank.MsgSend{ Inputs: []bank.Input{bank.NewInput(addr1, coins)}, Outputs: []bank.Output{bank.NewOutput(addr2, coins)}, } - sendMsg2 = bank.SendMsg{ + sendMsg2 = bank.MsgSend{ Inputs: []bank.Input{bank.NewInput(addr1, coins)}, Outputs: []bank.Output{ bank.NewOutput(addr2, halfCoins), @@ -55,7 +55,7 @@ var ( }, } - sendMsg3 = bank.SendMsg{ + sendMsg3 = bank.MsgSend{ Inputs: []bank.Input{ bank.NewInput(addr1, coins), bank.NewInput(addr4, coins), @@ -66,7 +66,7 @@ var ( }, } - sendMsg4 = bank.SendMsg{ + sendMsg4 = bank.MsgSend{ Inputs: []bank.Input{ bank.NewInput(addr2, coins), }, @@ -75,7 +75,7 @@ var ( }, } - sendMsg5 = bank.SendMsg{ + sendMsg5 = bank.MsgSend{ Inputs: []bank.Input{ bank.NewInput(addr1, manyCoins), }, @@ -208,7 +208,7 @@ func TestGenesis(t *testing.T) { assert.Equal(t, acc, res1) } -func TestSendMsgWithAccounts(t *testing.T) { +func TestMsgSendWithAccounts(t *testing.T) { bapp := newBasecoinApp() // Construct some genesis bytes to reflect basecoin/types/AppAccount @@ -249,7 +249,7 @@ func TestSendMsgWithAccounts(t *testing.T) { SignCheckDeliver(t, bapp, sendMsg1, []int64{1}, true, priv1) } -func TestSendMsgMultipleOut(t *testing.T) { +func TestMsgSendMultipleOut(t *testing.T) { bapp := newBasecoinApp() genCoins, err := sdk.ParseCoins("42foocoin") @@ -311,7 +311,7 @@ func TestSengMsgMultipleInOut(t *testing.T) { CheckBalance(t, bapp, addr3, "10foocoin") } -func TestSendMsgDependent(t *testing.T) { +func TestMsgSendDependent(t *testing.T) { bapp := newBasecoinApp() genCoins, err := sdk.ParseCoins("42foocoin") @@ -339,7 +339,7 @@ func TestSendMsgDependent(t *testing.T) { CheckBalance(t, bapp, addr1, "42foocoin") } -func TestQuizMsg(t *testing.T) { +func TestMsgQuiz(t *testing.T) { bapp := newBasecoinApp() // Construct genesis state diff --git a/examples/democoin/app/app.go b/examples/democoin/app/app.go index 4e5e4e22f..290a04d66 100644 --- a/examples/democoin/app/app.go +++ b/examples/democoin/app/app.go @@ -69,10 +69,10 @@ func NewDemocoinApp(logger log.Logger, db dbm.DB) *DemocoinApp { ).Seal() // Add handlers. - coinKeeper := bank.NewCoinKeeper(app.accountMapper) + coinKeeper := bank.NewKeeper(app.accountMapper) coolKeeper := cool.NewKeeper(app.capKeyMainStore, coinKeeper, app.RegisterCodespace(cool.DefaultCodespace)) - powKeeper := pow.NewKeeper(app.capKeyPowStore, pow.NewPowConfig("pow", int64(1)), coinKeeper, app.RegisterCodespace(pow.DefaultCodespace)) - ibcMapper := ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore, app.RegisterCodespace(ibc.DefaultCodespace)) + powKeeper := pow.NewKeeper(app.capKeyPowStore, pow.NewConfig("pow", int64(1)), coinKeeper, app.RegisterCodespace(pow.DefaultCodespace)) + ibcMapper := ibc.NewMapper(app.cdc, app.capKeyIBCStore, app.RegisterCodespace(ibc.DefaultCodespace)) stakeKeeper := simplestake.NewKeeper(app.capKeyStakingStore, coinKeeper, app.RegisterCodespace(simplestake.DefaultCodespace)) app.Router(). AddRoute("bank", bank.NewHandler(coinKeeper)). @@ -104,15 +104,15 @@ func MakeCodec() *wire.Codec { // Register Msgs cdc.RegisterInterface((*sdk.Msg)(nil), nil) - cdc.RegisterConcrete(bank.SendMsg{}, "democoin/Send", nil) - cdc.RegisterConcrete(bank.IssueMsg{}, "democoin/Issue", nil) - cdc.RegisterConcrete(cool.QuizMsg{}, "democoin/Quiz", nil) - cdc.RegisterConcrete(cool.SetTrendMsg{}, "democoin/SetTrend", nil) - cdc.RegisterConcrete(pow.MineMsg{}, "democoin/Mine", nil) + cdc.RegisterConcrete(bank.MsgSend{}, "democoin/Send", nil) + cdc.RegisterConcrete(bank.MsgIssue{}, "democoin/Issue", nil) + cdc.RegisterConcrete(cool.MsgQuiz{}, "democoin/Quiz", nil) + cdc.RegisterConcrete(cool.MsgSetTrend{}, "democoin/SetTrend", nil) + cdc.RegisterConcrete(pow.MsgMine{}, "democoin/Mine", nil) cdc.RegisterConcrete(ibc.IBCTransferMsg{}, "democoin/IBCTransferMsg", nil) cdc.RegisterConcrete(ibc.IBCReceiveMsg{}, "democoin/IBCReceiveMsg", nil) - cdc.RegisterConcrete(simplestake.BondMsg{}, "democoin/BondMsg", nil) - cdc.RegisterConcrete(simplestake.UnbondMsg{}, "democoin/UnbondMsg", nil) + cdc.RegisterConcrete(simplestake.MsgBond{}, "democoin/BondMsg", nil) + cdc.RegisterConcrete(simplestake.MsgUnbond{}, "democoin/UnbondMsg", nil) // Register AppAccount cdc.RegisterInterface((*sdk.Account)(nil), nil) @@ -169,7 +169,7 @@ func (app *DemocoinApp) initChainerFn(coolKeeper cool.Keeper, powKeeper pow.Keep // return sdk.ErrGenesisParse("").TraceCause(err, "") } - err = powKeeper.InitGenesis(ctx, genesisState.PowGenesis) + err = powKeeper.InitGenesis(ctx, genesisState.POWGenesis) if err != nil { panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468 // return sdk.ErrGenesisParse("").TraceCause(err, "") diff --git a/examples/democoin/app/app_test.go b/examples/democoin/app/app_test.go index f17e2a9b0..c67782d92 100644 --- a/examples/democoin/app/app_test.go +++ b/examples/democoin/app/app_test.go @@ -36,32 +36,32 @@ var ( 0, } - sendMsg = bank.SendMsg{ + sendMsg = bank.MsgSend{ Inputs: []bank.Input{bank.NewInput(addr1, coins)}, Outputs: []bank.Output{bank.NewOutput(addr2, coins)}, } - quizMsg1 = cool.QuizMsg{ + quizMsg1 = cool.MsgQuiz{ Sender: addr1, CoolAnswer: "icecold", } - quizMsg2 = cool.QuizMsg{ + quizMsg2 = cool.MsgQuiz{ Sender: addr1, CoolAnswer: "badvibesonly", } - setTrendMsg1 = cool.SetTrendMsg{ + setTrendMsg1 = cool.MsgSetTrend{ Sender: addr1, Cool: "icecold", } - setTrendMsg2 = cool.SetTrendMsg{ + setTrendMsg2 = cool.MsgSetTrend{ Sender: addr1, Cool: "badvibesonly", } - setTrendMsg3 = cool.SetTrendMsg{ + setTrendMsg3 = cool.MsgSetTrend{ Sender: addr1, Cool: "warmandkind", } @@ -157,7 +157,7 @@ func TestGenesis(t *testing.T) { assert.Equal(t, acc, res1) } -func TestSendMsgWithAccounts(t *testing.T) { +func TestMsgSendWithAccounts(t *testing.T) { bapp := newDemocoinApp() // Construct some genesis bytes to reflect democoin/types/AppAccount @@ -233,7 +233,7 @@ func TestSendMsgWithAccounts(t *testing.T) { assert.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) } -func TestMineMsg(t *testing.T) { +func TestMsgMine(t *testing.T) { bapp := newDemocoinApp() // Construct genesis state @@ -271,11 +271,11 @@ func TestMineMsg(t *testing.T) { assert.Equal(t, acc1, res1) // Mine and check for reward - mineMsg1 := pow.GenerateMineMsg(addr1, 1, 2) + mineMsg1 := pow.GenerateMsgMine(addr1, 1, 2) SignCheckDeliver(t, bapp, mineMsg1, 0, true) CheckBalance(t, bapp, "1pow") // Mine again and check for reward - mineMsg2 := pow.GenerateMineMsg(addr1, 2, 3) + mineMsg2 := pow.GenerateMsgMine(addr1, 2, 3) SignCheckDeliver(t, bapp, mineMsg2, 1, true) CheckBalance(t, bapp, "2pow") // Mine again - should be invalid @@ -284,7 +284,7 @@ func TestMineMsg(t *testing.T) { } -func TestQuizMsg(t *testing.T) { +func TestMsgQuiz(t *testing.T) { bapp := newDemocoinApp() // Construct genesis state diff --git a/examples/democoin/types/account.go b/examples/democoin/types/account.go index d90525f1d..8a744229a 100644 --- a/examples/democoin/types/account.go +++ b/examples/democoin/types/account.go @@ -45,8 +45,8 @@ func GetAccountDecoder(cdc *wire.Codec) sdk.AccountDecoder { // State to Unmarshal type GenesisState struct { Accounts []*GenesisAccount `json:"accounts"` - PowGenesis pow.PowGenesis `json:"pow"` - CoolGenesis cool.CoolGenesis `json:"cool"` + POWGenesis pow.Genesis `json:"pow"` + CoolGenesis cool.Genesis `json:"cool"` } // GenesisAccount doesn't need pubkey or sequence diff --git a/examples/democoin/x/cool/commands/tx.go b/examples/democoin/x/cool/commands/tx.go index 88c5e4e68..90f31d283 100644 --- a/examples/democoin/x/cool/commands/tx.go +++ b/examples/democoin/x/cool/commands/tx.go @@ -34,19 +34,13 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command { } // create the message - msg := cool.NewQuizMsg(from, args[0]) + msg := cool.NewMsgQuiz(from, args[0]) // get account name name := viper.GetString(client.FlagName) - // default to next sequence number if none provided - ctx, err = context.EnsureSequence(ctx) - if err != nil { - return err - } - // build and sign the transaction, then broadcast to Tendermint - res, err := ctx.SignBuildBroadcast(name, msg, cdc) + res, err := ctx.EnsureSignBuildBroadcast(name, msg, cdc) if err != nil { return err } @@ -78,17 +72,11 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command { // get account name name := viper.GetString(client.FlagName) - // default to next sequence number if none provided - ctx, err = context.EnsureSequence(ctx) - if err != nil { - return err - } - // create the message - msg := cool.NewSetTrendMsg(from, args[0]) + msg := cool.NewMsgSetTrend(from, args[0]) // build and sign the transaction, then broadcast to Tendermint - res, err := ctx.SignBuildBroadcast(name, msg, cdc) + res, err := ctx.EnsureSignBuildBroadcast(name, msg, cdc) if err != nil { return err } diff --git a/examples/democoin/x/cool/errors.go b/examples/democoin/x/cool/errors.go index 4c28f94ba..7a5e62c5d 100644 --- a/examples/democoin/x/cool/errors.go +++ b/examples/democoin/x/cool/errors.go @@ -6,6 +6,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +// Cool errors reserve 400 ~ 499. const ( DefaultCodespace sdk.CodespaceType = 6 diff --git a/examples/democoin/x/cool/handler.go b/examples/democoin/x/cool/handler.go index e2b36b218..c82fa4ae4 100644 --- a/examples/democoin/x/cool/handler.go +++ b/examples/democoin/x/cool/handler.go @@ -21,10 +21,10 @@ import ( func NewHandler(k Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { switch msg := msg.(type) { - case SetTrendMsg: - return handleSetTrendMsg(ctx, k, msg) - case QuizMsg: - return handleQuizMsg(ctx, k, msg) + case MsgSetTrend: + return handleMsgSetTrend(ctx, k, msg) + case MsgQuiz: + return handleMsgQuiz(ctx, k, msg) default: errMsg := fmt.Sprintf("Unrecognized cool Msg type: %v", reflect.TypeOf(msg).Name()) return sdk.ErrUnknownRequest(errMsg).Result() @@ -32,14 +32,14 @@ func NewHandler(k Keeper) sdk.Handler { } } -// Handle QuizMsg This is the engine of your module -func handleSetTrendMsg(ctx sdk.Context, k Keeper, msg SetTrendMsg) sdk.Result { +// Handle MsgQuiz This is the engine of your module +func handleMsgSetTrend(ctx sdk.Context, k Keeper, msg MsgSetTrend) sdk.Result { k.setTrend(ctx, msg.Cool) return sdk.Result{} } -// Handle QuizMsg This is the engine of your module -func handleQuizMsg(ctx sdk.Context, k Keeper, msg QuizMsg) sdk.Result { +// Handle MsgQuiz This is the engine of your module +func handleMsgQuiz(ctx sdk.Context, k Keeper, msg MsgQuiz) sdk.Result { correct := k.CheckTrend(ctx, msg.CoolAnswer) diff --git a/examples/democoin/x/cool/keeper.go b/examples/democoin/x/cool/keeper.go index 3b6c8e9ae..b180cd23c 100644 --- a/examples/democoin/x/cool/keeper.go +++ b/examples/democoin/x/cool/keeper.go @@ -7,7 +7,7 @@ import ( // Keeper - handlers sets/gets of custom variables for your module type Keeper struct { - ck bank.CoinKeeper + ck bank.Keeper storeKey sdk.StoreKey // The (unexposed) key used to access the store from the Context. @@ -15,7 +15,7 @@ type Keeper struct { } // NewKeeper - Returns the Keeper -func NewKeeper(key sdk.StoreKey, bankKeeper bank.CoinKeeper, codespace sdk.CodespaceType) Keeper { +func NewKeeper(key sdk.StoreKey, bankKeeper bank.Keeper, codespace sdk.CodespaceType) Keeper { return Keeper{bankKeeper, key, codespace} } @@ -44,7 +44,7 @@ func (k Keeper) CheckTrend(ctx sdk.Context, guessedTrend string) bool { } // InitGenesis - store the genesis trend -func (k Keeper) InitGenesis(ctx sdk.Context, data CoolGenesis) error { +func (k Keeper) InitGenesis(ctx sdk.Context, data Genesis) error { k.setTrend(ctx, data.Trend) return nil } diff --git a/examples/democoin/x/cool/types.go b/examples/democoin/x/cool/types.go index e24c363ac..caaf8610f 100644 --- a/examples/democoin/x/cool/types.go +++ b/examples/democoin/x/cool/types.go @@ -8,39 +8,39 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// A really cool msg type, these fields are can be entirely arbitrary and +// a really cool msg type, these fields are can be entirely arbitrary and // custom to your message -type SetTrendMsg struct { +type MsgSetTrend struct { Sender sdk.Address Cool string } -// Genesis state - specify genesis trend -type CoolGenesis struct { +// genesis state - specify genesis trend +type Genesis struct { Trend string `json:"trend"` } -// New cool message -func NewSetTrendMsg(sender sdk.Address, cool string) SetTrendMsg { - return SetTrendMsg{ +// new cool message +func NewMsgSetTrend(sender sdk.Address, cool string) MsgSetTrend { + return MsgSetTrend{ Sender: sender, Cool: cool, } } // enforce the msg type at compile time -var _ sdk.Msg = SetTrendMsg{} +var _ sdk.Msg = MsgSetTrend{} // nolint -func (msg SetTrendMsg) Type() string { return "cool" } -func (msg SetTrendMsg) Get(key interface{}) (value interface{}) { return nil } -func (msg SetTrendMsg) GetSigners() []sdk.Address { return []sdk.Address{msg.Sender} } -func (msg SetTrendMsg) String() string { - return fmt.Sprintf("SetTrendMsg{Sender: %v, Cool: %v}", msg.Sender, msg.Cool) +func (msg MsgSetTrend) Type() string { return "cool" } +func (msg MsgSetTrend) Get(key interface{}) (value interface{}) { return nil } +func (msg MsgSetTrend) GetSigners() []sdk.Address { return []sdk.Address{msg.Sender} } +func (msg MsgSetTrend) String() string { + return fmt.Sprintf("MsgSetTrend{Sender: %v, Cool: %v}", msg.Sender, msg.Cool) } // Validate Basic is used to quickly disqualify obviously invalid messages quickly -func (msg SetTrendMsg) ValidateBasic() sdk.Error { +func (msg MsgSetTrend) ValidateBasic() sdk.Error { if len(msg.Sender) == 0 { return sdk.ErrUnknownAddress(msg.Sender.String()).Trace("") } @@ -54,7 +54,7 @@ func (msg SetTrendMsg) ValidateBasic() sdk.Error { } // Get the bytes for the message signer to sign on -func (msg SetTrendMsg) GetSignBytes() []byte { +func (msg MsgSetTrend) GetSignBytes() []byte { b, err := json.Marshal(msg) if err != nil { panic(err) @@ -66,32 +66,32 @@ func (msg SetTrendMsg) GetSignBytes() []byte { // A message type to quiz how cool you are. these fields are can be entirely // arbitrary and custom to your message -type QuizMsg struct { +type MsgQuiz struct { Sender sdk.Address CoolAnswer string } // New cool message -func NewQuizMsg(sender sdk.Address, coolerthancool string) QuizMsg { - return QuizMsg{ +func NewMsgQuiz(sender sdk.Address, coolerthancool string) MsgQuiz { + return MsgQuiz{ Sender: sender, CoolAnswer: coolerthancool, } } // enforce the msg type at compile time -var _ sdk.Msg = QuizMsg{} +var _ sdk.Msg = MsgQuiz{} // nolint -func (msg QuizMsg) Type() string { return "cool" } -func (msg QuizMsg) Get(key interface{}) (value interface{}) { return nil } -func (msg QuizMsg) GetSigners() []sdk.Address { return []sdk.Address{msg.Sender} } -func (msg QuizMsg) String() string { - return fmt.Sprintf("QuizMsg{Sender: %v, CoolAnswer: %v}", msg.Sender, msg.CoolAnswer) +func (msg MsgQuiz) Type() string { return "cool" } +func (msg MsgQuiz) Get(key interface{}) (value interface{}) { return nil } +func (msg MsgQuiz) GetSigners() []sdk.Address { return []sdk.Address{msg.Sender} } +func (msg MsgQuiz) String() string { + return fmt.Sprintf("MsgQuiz{Sender: %v, CoolAnswer: %v}", msg.Sender, msg.CoolAnswer) } // Validate Basic is used to quickly disqualify obviously invalid messages quickly -func (msg QuizMsg) ValidateBasic() sdk.Error { +func (msg MsgQuiz) ValidateBasic() sdk.Error { if len(msg.Sender) == 0 { return sdk.ErrUnknownAddress(msg.Sender.String()).Trace("") } @@ -99,7 +99,7 @@ func (msg QuizMsg) ValidateBasic() sdk.Error { } // Get the bytes for the message signer to sign on -func (msg QuizMsg) GetSignBytes() []byte { +func (msg MsgQuiz) GetSignBytes() []byte { b, err := json.Marshal(msg) if err != nil { panic(err) diff --git a/examples/democoin/x/pow/commands/tx.go b/examples/democoin/x/pow/commands/tx.go index 5fa11a476..017047d08 100644 --- a/examples/democoin/x/pow/commands/tx.go +++ b/examples/democoin/x/pow/commands/tx.go @@ -14,6 +14,7 @@ import ( authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands" ) +// command to mine some pow! func MineCmd(cdc *wire.Codec) *cobra.Command { return &cobra.Command{ Use: "mine [difficulty] [count] [nonce] [solution]", @@ -36,12 +37,10 @@ func MineCmd(cdc *wire.Codec) *cobra.Command { if err != nil { return err } - count, err := strconv.ParseUint(args[1], 0, 64) if err != nil { return err } - nonce, err := strconv.ParseUint(args[2], 0, 64) if err != nil { return err @@ -49,19 +48,13 @@ func MineCmd(cdc *wire.Codec) *cobra.Command { solution := []byte(args[3]) - msg := pow.NewMineMsg(from, difficulty, count, nonce, solution) + msg := pow.NewMsgMine(from, difficulty, count, nonce, solution) // get account name name := ctx.FromAddressName - // default to next sequence number if none provided - ctx, err = context.EnsureSequence(ctx) - if err != nil { - return err - } - // build and sign the transaction, then broadcast to Tendermint - res, err := ctx.SignBuildBroadcast(name, msg, cdc) + res, err := ctx.EnsureSignBuildBroadcast(name, msg, cdc) if err != nil { return err } diff --git a/examples/democoin/x/pow/errors.go b/examples/democoin/x/pow/errors.go index d387f9b9a..a499e0d9f 100644 --- a/examples/democoin/x/pow/errors.go +++ b/examples/democoin/x/pow/errors.go @@ -4,19 +4,20 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +// TODO remove, seems hacky type CodeType = sdk.CodeType +// POW errors reserve 200 ~ 299 const ( - DefaultCodespace sdk.CodespaceType = 5 - - CodeInvalidDifficulty CodeType = 201 - CodeNonexistentDifficulty CodeType = 202 - CodeNonexistentReward CodeType = 203 - CodeNonexistentCount CodeType = 204 - CodeInvalidProof CodeType = 205 - CodeNotBelowTarget CodeType = 206 - CodeInvalidCount CodeType = 207 - CodeUnknownRequest CodeType = sdk.CodeUnknownRequest + DefaultCodespace sdk.CodespaceType = 5 + CodeInvalidDifficulty CodeType = 201 + CodeNonexistentDifficulty CodeType = 202 + CodeNonexistentReward CodeType = 203 + CodeNonexistentCount CodeType = 204 + CodeInvalidProof CodeType = 205 + CodeNotBelowTarget CodeType = 206 + CodeInvalidCount CodeType = 207 + CodeUnknownRequest CodeType = sdk.CodeUnknownRequest ) func codeToDefaultMsg(code CodeType) string { @@ -42,30 +43,25 @@ func codeToDefaultMsg(code CodeType) string { } } +// nolint func ErrInvalidDifficulty(codespace sdk.CodespaceType, msg string) sdk.Error { return newError(codespace, CodeInvalidDifficulty, msg) } - func ErrNonexistentDifficulty(codespace sdk.CodespaceType) sdk.Error { return newError(codespace, CodeNonexistentDifficulty, "") } - func ErrNonexistentReward(codespace sdk.CodespaceType) sdk.Error { return newError(codespace, CodeNonexistentReward, "") } - func ErrNonexistentCount(codespace sdk.CodespaceType) sdk.Error { return newError(codespace, CodeNonexistentCount, "") } - func ErrInvalidProof(codespace sdk.CodespaceType, msg string) sdk.Error { return newError(codespace, CodeInvalidProof, msg) } - func ErrNotBelowTarget(codespace sdk.CodespaceType, msg string) sdk.Error { return newError(codespace, CodeNotBelowTarget, msg) } - func ErrInvalidCount(codespace sdk.CodespaceType, msg string) sdk.Error { return newError(codespace, CodeInvalidCount, msg) } @@ -73,9 +69,8 @@ func ErrInvalidCount(codespace sdk.CodespaceType, msg string) sdk.Error { func msgOrDefaultMsg(msg string, code CodeType) string { if msg != "" { return msg - } else { - return codeToDefaultMsg(code) } + return codeToDefaultMsg(code) } func newError(codespace sdk.CodespaceType, code CodeType, msg string) sdk.Error { diff --git a/examples/democoin/x/pow/handler.go b/examples/democoin/x/pow/handler.go index d1a691139..2dd549bde 100644 --- a/examples/democoin/x/pow/handler.go +++ b/examples/democoin/x/pow/handler.go @@ -6,17 +6,18 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +// POW handler func (pk Keeper) Handler(ctx sdk.Context, msg sdk.Msg) sdk.Result { switch msg := msg.(type) { - case MineMsg: - return handleMineMsg(ctx, pk, msg) + case MsgMine: + return handleMsgMine(ctx, pk, msg) default: errMsg := "Unrecognized pow Msg type: " + reflect.TypeOf(msg).Name() return sdk.ErrUnknownRequest(errMsg).Result() } } -func handleMineMsg(ctx sdk.Context, pk Keeper, msg MineMsg) sdk.Result { +func handleMsgMine(ctx sdk.Context, pk Keeper, msg MsgMine) sdk.Result { // precondition: msg has passed ValidateBasic diff --git a/examples/democoin/x/pow/handler_test.go b/examples/democoin/x/pow/handler_test.go index 4b1a571f7..8a4f81de2 100644 --- a/examples/democoin/x/pow/handler_test.go +++ b/examples/democoin/x/pow/handler_test.go @@ -20,8 +20,8 @@ func TestPowHandler(t *testing.T) { am := auth.NewAccountMapper(cdc, capKey, &auth.BaseAccount{}) ctx := sdk.NewContext(ms, abci.Header{}, false, nil) - config := NewPowConfig("pow", int64(1)) - ck := bank.NewCoinKeeper(am) + config := NewConfig("pow", int64(1)) + ck := bank.NewKeeper(am) keeper := NewKeeper(capKey, config, ck, DefaultCodespace) handler := keeper.Handler @@ -30,11 +30,11 @@ func TestPowHandler(t *testing.T) { count := uint64(1) difficulty := uint64(2) - err := keeper.InitGenesis(ctx, PowGenesis{uint64(1), uint64(0)}) + err := keeper.InitGenesis(ctx, Genesis{uint64(1), uint64(0)}) assert.Nil(t, err) nonce, proof := mine(addr, count, difficulty) - msg := NewMineMsg(addr, difficulty, count, nonce, proof) + msg := NewMsgMine(addr, difficulty, count, nonce, proof) result := handler(ctx, msg) assert.Equal(t, result, sdk.Result{}) @@ -51,7 +51,7 @@ func TestPowHandler(t *testing.T) { difficulty = uint64(4) nonce, proof = mine(addr, count, difficulty) - msg = NewMineMsg(addr, difficulty, count, nonce, proof) + msg = NewMsgMine(addr, difficulty, count, nonce, proof) result = handler(ctx, msg) assert.NotEqual(t, result, sdk.Result{}) diff --git a/examples/democoin/x/pow/keeper.go b/examples/democoin/x/pow/keeper.go index 70453d6d6..9a5edf0b5 100644 --- a/examples/democoin/x/pow/keeper.go +++ b/examples/democoin/x/pow/keeper.go @@ -9,42 +9,45 @@ import ( ) // module users must specify coin denomination and reward (constant) per PoW solution -type PowConfig struct { +type Config struct { Denomination string Reward int64 } // genesis info must specify starting difficulty and starting count -type PowGenesis struct { +type Genesis struct { Difficulty uint64 `json:"difficulty"` Count uint64 `json:"count"` } +// POW Keeper type Keeper struct { key sdk.StoreKey - config PowConfig - ck bank.CoinKeeper + config Config + ck bank.Keeper codespace sdk.CodespaceType } -func NewPowConfig(denomination string, reward int64) PowConfig { - return PowConfig{denomination, reward} +func NewConfig(denomination string, reward int64) Config { + return Config{denomination, reward} } -func NewKeeper(key sdk.StoreKey, config PowConfig, ck bank.CoinKeeper, codespace sdk.CodespaceType) Keeper { +func NewKeeper(key sdk.StoreKey, config Config, ck bank.Keeper, codespace sdk.CodespaceType) Keeper { return Keeper{key, config, ck, codespace} } -func (pk Keeper) InitGenesis(ctx sdk.Context, genesis PowGenesis) error { - pk.SetLastDifficulty(ctx, genesis.Difficulty) - pk.SetLastCount(ctx, genesis.Count) +// Init Genessis for the POW module +func (k Keeper) InitGenesis(ctx sdk.Context, genesis Genesis) error { + k.SetLastDifficulty(ctx, genesis.Difficulty) + k.SetLastCount(ctx, genesis.Count) return nil } var lastDifficultyKey = []byte("lastDifficultyKey") -func (pk Keeper) GetLastDifficulty(ctx sdk.Context) (uint64, error) { - store := ctx.KVStore(pk.key) +// get the last mining difficulty +func (k Keeper) GetLastDifficulty(ctx sdk.Context) (uint64, error) { + store := ctx.KVStore(k.key) stored := store.Get(lastDifficultyKey) if stored == nil { panic("no stored difficulty") @@ -53,15 +56,17 @@ func (pk Keeper) GetLastDifficulty(ctx sdk.Context) (uint64, error) { } } -func (pk Keeper) SetLastDifficulty(ctx sdk.Context, diff uint64) { - store := ctx.KVStore(pk.key) +// set the last mining difficulty +func (k Keeper) SetLastDifficulty(ctx sdk.Context, diff uint64) { + store := ctx.KVStore(k.key) store.Set(lastDifficultyKey, []byte(strconv.FormatUint(diff, 16))) } var countKey = []byte("count") -func (pk Keeper) GetLastCount(ctx sdk.Context) (uint64, error) { - store := ctx.KVStore(pk.key) +// get the last count +func (k Keeper) GetLastCount(ctx sdk.Context) (uint64, error) { + store := ctx.KVStore(k.key) stored := store.Get(countKey) if stored == nil { panic("no stored count") @@ -70,45 +75,45 @@ func (pk Keeper) GetLastCount(ctx sdk.Context) (uint64, error) { } } -func (pk Keeper) SetLastCount(ctx sdk.Context, count uint64) { - store := ctx.KVStore(pk.key) +// set the last count +func (k Keeper) SetLastCount(ctx sdk.Context, count uint64) { + store := ctx.KVStore(k.key) store.Set(countKey, []byte(strconv.FormatUint(count, 16))) } -func (pk Keeper) CheckValid(ctx sdk.Context, difficulty uint64, count uint64) (uint64, uint64, sdk.Error) { +// Is the keeper state valid? +func (k Keeper) CheckValid(ctx sdk.Context, difficulty uint64, count uint64) (uint64, uint64, sdk.Error) { - lastDifficulty, err := pk.GetLastDifficulty(ctx) + lastDifficulty, err := k.GetLastDifficulty(ctx) if err != nil { - return 0, 0, ErrNonexistentDifficulty(pk.codespace) + return 0, 0, ErrNonexistentDifficulty(k.codespace) } newDifficulty := lastDifficulty + 1 - lastCount, err := pk.GetLastCount(ctx) + lastCount, err := k.GetLastCount(ctx) if err != nil { - return 0, 0, ErrNonexistentCount(pk.codespace) + return 0, 0, ErrNonexistentCount(k.codespace) } newCount := lastCount + 1 if count != newCount { - return 0, 0, ErrInvalidCount(pk.codespace, fmt.Sprintf("invalid count: was %d, should have been %d", count, newCount)) + return 0, 0, ErrInvalidCount(k.codespace, fmt.Sprintf("invalid count: was %d, should have been %d", count, newCount)) } - if difficulty != newDifficulty { - return 0, 0, ErrInvalidDifficulty(pk.codespace, fmt.Sprintf("invalid difficulty: was %d, should have been %d", difficulty, newDifficulty)) + return 0, 0, ErrInvalidDifficulty(k.codespace, fmt.Sprintf("invalid difficulty: was %d, should have been %d", difficulty, newDifficulty)) } - return newDifficulty, newCount, nil - } -func (pk Keeper) ApplyValid(ctx sdk.Context, sender sdk.Address, newDifficulty uint64, newCount uint64) sdk.Error { - _, ckErr := pk.ck.AddCoins(ctx, sender, []sdk.Coin{sdk.Coin{pk.config.Denomination, pk.config.Reward}}) +// Add some coins for a POW well done +func (k Keeper) ApplyValid(ctx sdk.Context, sender sdk.Address, newDifficulty uint64, newCount uint64) sdk.Error { + _, ckErr := k.ck.AddCoins(ctx, sender, []sdk.Coin{sdk.Coin{k.config.Denomination, k.config.Reward}}) if ckErr != nil { return ckErr } - pk.SetLastDifficulty(ctx, newDifficulty) - pk.SetLastCount(ctx, newCount) + k.SetLastDifficulty(ctx, newDifficulty) + k.SetLastCount(ctx, newCount) return nil } diff --git a/examples/democoin/x/pow/keeper_test.go b/examples/democoin/x/pow/keeper_test.go index d0b60fa17..4c01559f6 100644 --- a/examples/democoin/x/pow/keeper_test.go +++ b/examples/democoin/x/pow/keeper_test.go @@ -33,11 +33,11 @@ func TestPowKeeperGetSet(t *testing.T) { am := auth.NewAccountMapper(cdc, capKey, &auth.BaseAccount{}) ctx := sdk.NewContext(ms, abci.Header{}, false, nil) - config := NewPowConfig("pow", int64(1)) - ck := bank.NewCoinKeeper(am) + config := NewConfig("pow", int64(1)) + ck := bank.NewKeeper(am) keeper := NewKeeper(capKey, config, ck, DefaultCodespace) - err := keeper.InitGenesis(ctx, PowGenesis{uint64(1), uint64(0)}) + err := keeper.InitGenesis(ctx, Genesis{uint64(1), uint64(0)}) assert.Nil(t, err) res, err := keeper.GetLastDifficulty(ctx) diff --git a/examples/democoin/x/pow/mine.go b/examples/democoin/x/pow/mine.go index ff2264aaa..21d389a1d 100644 --- a/examples/democoin/x/pow/mine.go +++ b/examples/democoin/x/pow/mine.go @@ -9,9 +9,10 @@ import ( crypto "github.com/tendermint/go-crypto" ) -func GenerateMineMsg(sender sdk.Address, count uint64, difficulty uint64) MineMsg { +// generate the mine message +func GenerateMsgMine(sender sdk.Address, count uint64, difficulty uint64) MsgMine { nonce, hash := mine(sender, count, difficulty) - return NewMineMsg(sender, difficulty, count, nonce, hash) + return NewMsgMine(sender, difficulty, count, nonce, hash) } func hash(sender sdk.Address, count uint64, nonce uint64) []byte { diff --git a/examples/democoin/x/pow/types.go b/examples/democoin/x/pow/types.go index 69d56e4f1..999dd4197 100644 --- a/examples/democoin/x/pow/types.go +++ b/examples/democoin/x/pow/types.go @@ -13,8 +13,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// MineMsg - mine some coins with PoW -type MineMsg struct { +// MsgMine - mine some coins with PoW +type MsgMine struct { Sender sdk.Address `json:"sender"` Difficulty uint64 `json:"difficulty"` Count uint64 `json:"count"` @@ -23,21 +23,23 @@ type MineMsg struct { } // enforce the msg type at compile time -var _ sdk.Msg = MineMsg{} +var _ sdk.Msg = MsgMine{} -// NewMineMsg - construct mine message -func NewMineMsg(sender sdk.Address, difficulty uint64, count uint64, nonce uint64, proof []byte) MineMsg { - return MineMsg{sender, difficulty, count, nonce, proof} +// NewMsgMine - construct mine message +func NewMsgMine(sender sdk.Address, difficulty uint64, count uint64, nonce uint64, proof []byte) MsgMine { + return MsgMine{sender, difficulty, count, nonce, proof} } -func (msg MineMsg) Type() string { return "pow" } -func (msg MineMsg) Get(key interface{}) (value interface{}) { return nil } -func (msg MineMsg) GetSigners() []sdk.Address { return []sdk.Address{msg.Sender} } -func (msg MineMsg) String() string { - return fmt.Sprintf("MineMsg{Sender: %v, Difficulty: %d, Count: %d, Nonce: %d, Proof: %s}", msg.Sender, msg.Difficulty, msg.Count, msg.Nonce, msg.Proof) +// nolint +func (msg MsgMine) Type() string { return "pow" } +func (msg MsgMine) Get(key interface{}) (value interface{}) { return nil } +func (msg MsgMine) GetSigners() []sdk.Address { return []sdk.Address{msg.Sender} } +func (msg MsgMine) String() string { + return fmt.Sprintf("MsgMine{Sender: %v, Difficulty: %d, Count: %d, Nonce: %d, Proof: %s}", msg.Sender, msg.Difficulty, msg.Count, msg.Nonce, msg.Proof) } -func (msg MineMsg) ValidateBasic() sdk.Error { +// validate the mine message +func (msg MsgMine) ValidateBasic() sdk.Error { // check hash var data []byte // hash must include sender, so no other users can race the tx @@ -69,7 +71,8 @@ func (msg MineMsg) ValidateBasic() sdk.Error { return nil } -func (msg MineMsg) GetSignBytes() []byte { +// get the mine message sign bytes +func (msg MsgMine) GetSignBytes() []byte { b, err := json.Marshal(msg) if err != nil { panic(err) diff --git a/examples/democoin/x/pow/types_test.go b/examples/democoin/x/pow/types_test.go index 34ab8914e..bf2e9169b 100644 --- a/examples/democoin/x/pow/types_test.go +++ b/examples/democoin/x/pow/types_test.go @@ -9,70 +9,72 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func TestNewMineMsg(t *testing.T) { +func TestNewMsgMine(t *testing.T) { addr := sdk.Address([]byte("sender")) - msg := MineMsg{addr, 0, 0, 0, []byte("")} - equiv := NewMineMsg(addr, 0, 0, 0, []byte("")) + msg := MsgMine{addr, 0, 0, 0, []byte("")} + equiv := NewMsgMine(addr, 0, 0, 0, []byte("")) assert.Equal(t, msg, equiv, "%s != %s", msg, equiv) } -func TestMineMsgType(t *testing.T) { +func TestMsgMineType(t *testing.T) { addr := sdk.Address([]byte("sender")) - msg := MineMsg{addr, 0, 0, 0, []byte("")} + msg := MsgMine{addr, 0, 0, 0, []byte("")} assert.Equal(t, msg.Type(), "pow") } -func TestMineMsgValidation(t *testing.T) { +func TestMsgMineValidation(t *testing.T) { addr := sdk.Address([]byte("sender")) otherAddr := sdk.Address([]byte("another")) count := uint64(0) + for difficulty := uint64(1); difficulty < 1000; difficulty += 100 { - count += 1 + + count++ nonce, proof := mine(addr, count, difficulty) - msg := MineMsg{addr, difficulty, count, nonce, proof} + msg := MsgMine{addr, difficulty, count, nonce, proof} err := msg.ValidateBasic() assert.Nil(t, err, "error with difficulty %d - %+v", difficulty, err) - msg.Count += 1 + msg.Count++ err = msg.ValidateBasic() assert.NotNil(t, err, "count was wrong, should have thrown error with msg %s", msg) - msg.Count -= 1 - msg.Nonce += 1 + msg.Count-- + msg.Nonce++ err = msg.ValidateBasic() assert.NotNil(t, err, "nonce was wrong, should have thrown error with msg %s", msg) - msg.Nonce -= 1 + msg.Nonce-- msg.Sender = otherAddr err = msg.ValidateBasic() assert.NotNil(t, err, "sender was wrong, should have thrown error with msg %s", msg) } } -func TestMineMsgString(t *testing.T) { +func TestMsgMineString(t *testing.T) { addr := sdk.Address([]byte("sender")) - msg := MineMsg{addr, 0, 0, 0, []byte("abc")} + msg := MsgMine{addr, 0, 0, 0, []byte("abc")} res := msg.String() - assert.Equal(t, res, "MineMsg{Sender: 73656E646572, Difficulty: 0, Count: 0, Nonce: 0, Proof: abc}") + assert.Equal(t, res, "MsgMine{Sender: 73656E646572, Difficulty: 0, Count: 0, Nonce: 0, Proof: abc}") } -func TestMineMsgGet(t *testing.T) { +func TestMsgMineGet(t *testing.T) { addr := sdk.Address([]byte("sender")) - msg := MineMsg{addr, 0, 0, 0, []byte("")} + msg := MsgMine{addr, 0, 0, 0, []byte("")} res := msg.Get(nil) assert.Nil(t, res) } -func TestMineMsgGetSignBytes(t *testing.T) { +func TestMsgMineGetSignBytes(t *testing.T) { addr := sdk.Address([]byte("sender")) - msg := MineMsg{addr, 1, 1, 1, []byte("abc")} + msg := MsgMine{addr, 1, 1, 1, []byte("abc")} res := msg.GetSignBytes() assert.Equal(t, string(res), `{"sender":"73656E646572","difficulty":1,"count":1,"nonce":1,"proof":"YWJj"}`) } -func TestMineMsgGetSigners(t *testing.T) { +func TestMsgMineGetSigners(t *testing.T) { addr := sdk.Address([]byte("sender")) - msg := MineMsg{addr, 1, 1, 1, []byte("abc")} + msg := MsgMine{addr, 1, 1, 1, []byte("abc")} res := msg.GetSigners() assert.Equal(t, fmt.Sprintf("%v", res), "[73656E646572]") } diff --git a/examples/kvstore/main.go b/examples/kvstore/main.go index 0d80826ed..d6b71171d 100644 --- a/examples/kvstore/main.go +++ b/examples/kvstore/main.go @@ -41,7 +41,7 @@ func main() { baseApp.SetTxDecoder(decodeTx) // Set a handler Route. - baseApp.Router().AddRoute("kvstore", KVStoreHandler(capKeyMainStore)) + baseApp.Router().AddRoute("kvstore", Handler(capKeyMainStore)) // Load latest version. if err := baseApp.LoadLatestVersion(capKeyMainStore); err != nil { @@ -65,11 +65,12 @@ func main() { return } -func KVStoreHandler(storeKey sdk.StoreKey) sdk.Handler { +// KVStore Handler +func Handler(storeKey sdk.StoreKey) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { dTx, ok := msg.(kvstoreTx) if !ok { - panic("KVStoreHandler should only receive kvstoreTx") + panic("Handler should only receive kvstoreTx") } // tx is already unmarshalled diff --git a/server/init.go b/server/init.go index f2578cb19..a68566cdf 100644 --- a/server/init.go +++ b/server/init.go @@ -76,10 +76,10 @@ func (c initCmd) run(cmd *cobra.Command, args []string) error { return err } - var DEFAULT_DENOM = "mycoin" + var defaultDenom = "mycoin" // Now, we want to add the custom app_state - appState, err := c.genAppState(args, addr, DEFAULT_DENOM) + appState, err := c.genAppState(args, addr, defaultDenom) if err != nil { return err } diff --git a/server/tm_cmds.go b/server/tm_cmds.go index 2a9b680e5..67504fa6b 100644 --- a/server/tm_cmds.go +++ b/server/tm_cmds.go @@ -12,7 +12,7 @@ import ( // ShowNodeIDCmd - ported from Tendermint, dump node ID to stdout func ShowNodeIDCmd(ctx *Context) *cobra.Command { - cmd := showNodeId{ctx} + cmd := showNodeID{ctx} return &cobra.Command{ Use: "show_node_id", Short: "Show this node's ID", @@ -20,11 +20,11 @@ func ShowNodeIDCmd(ctx *Context) *cobra.Command { } } -type showNodeId struct { +type showNodeID struct { context *Context } -func (s showNodeId) run(cmd *cobra.Command, args []string) error { +func (s showNodeID) run(cmd *cobra.Command, args []string) error { cfg := s.context.Config nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile()) if err != nil { diff --git a/server/util.go b/server/util.go index 95dc4b30d..cf37ec5cc 100644 --- a/server/util.go +++ b/server/util.go @@ -14,6 +14,7 @@ import ( "github.com/tendermint/tmlibs/log" ) +// server context type Context struct { Config *cfg.Config Logger log.Logger @@ -59,6 +60,7 @@ func PersistentPreRunEFn(context *Context) func(*cobra.Command, []string) error } } +// add server commands func AddCommands( rootCmd *cobra.Command, appState GenAppState, appCreator AppCreator, diff --git a/store/cachekvstore.go b/store/cachekvstore.go index 6c5cc9542..772b59305 100644 --- a/store/cachekvstore.go +++ b/store/cachekvstore.go @@ -26,13 +26,12 @@ type cacheKVStore struct { var _ CacheKVStore = (*cacheKVStore)(nil) +// nolint func NewCacheKVStore(parent KVStore) *cacheKVStore { - ci := &cacheKVStore{ cache: make(map[string]cValue), parent: parent, } - return ci } @@ -170,9 +169,8 @@ func (ci *cacheKVStore) dirtyItems(ascending bool) []cmn.KVPair { sort.Slice(items, func(i, j int) bool { if ascending { return bytes.Compare(items[i].Key, items[j].Key) < 0 - } else { - return bytes.Compare(items[i].Key, items[j].Key) > 0 } + return bytes.Compare(items[i].Key, items[j].Key) > 0 }) return items } diff --git a/store/cachekvstore_test.go b/store/cachekvstore_test.go index e29cd6156..0c88ca27d 100644 --- a/store/cachekvstore_test.go +++ b/store/cachekvstore_test.go @@ -105,7 +105,7 @@ func TestCacheKVIteratorBounds(t *testing.T) { k, v := itr.Key(), itr.Value() assert.Equal(t, keyFmt(i), k) assert.Equal(t, valFmt(i), v) - i += 1 + i++ } assert.Equal(t, nItems, i) @@ -113,7 +113,7 @@ func TestCacheKVIteratorBounds(t *testing.T) { itr = st.Iterator(bz("money"), nil) i = 0 for ; itr.Valid(); itr.Next() { - i += 1 + i++ } assert.Equal(t, 0, i) @@ -124,7 +124,7 @@ func TestCacheKVIteratorBounds(t *testing.T) { k, v := itr.Key(), itr.Value() assert.Equal(t, keyFmt(i), k) assert.Equal(t, valFmt(i), v) - i += 1 + i++ } assert.Equal(t, 3, i) @@ -135,7 +135,7 @@ func TestCacheKVIteratorBounds(t *testing.T) { k, v := itr.Key(), itr.Value() assert.Equal(t, keyFmt(i), k) assert.Equal(t, valFmt(i), v) - i += 1 + i++ } assert.Equal(t, 4, i) } @@ -369,7 +369,7 @@ func assertIterateDomain(t *testing.T, st KVStore, expectedN int) { k, v := itr.Key(), itr.Value() assert.Equal(t, keyFmt(i), k) assert.Equal(t, valFmt(i), v) - i += 1 + i++ } assert.Equal(t, expectedN, i) } @@ -397,7 +397,7 @@ func assertIterateDomainCheck(t *testing.T, st KVStore, mem dbm.DB, r []keyRange itr.Next() itr2.Next() - i += 1 + i++ } assert.False(t, itr.Valid()) @@ -479,10 +479,10 @@ func (krc *keyRangeCounter) valid() bool { func (krc *keyRangeCounter) next() { thisKeyRange := krc.keyRanges[krc.rangeIdx] if krc.idx == thisKeyRange.len()-1 { - krc.rangeIdx += 1 + krc.rangeIdx++ krc.idx = 0 } else { - krc.idx += 1 + krc.idx++ } } diff --git a/store/cachemergeiterator.go b/store/cachemergeiterator.go index b6c50c42c..cd739500d 100644 --- a/store/cachemergeiterator.go +++ b/store/cachemergeiterator.go @@ -151,9 +151,8 @@ func (iter *cacheMergeIterator) Close() { func (iter *cacheMergeIterator) compare(a, b []byte) int { if iter.ascending { return bytes.Compare(a, b) - } else { - return bytes.Compare(a, b) * -1 } + return bytes.Compare(a, b) * -1 } // Skip all delete-items from the cache w/ `key < until`. After this function, diff --git a/store/dbstoreadapter.go b/store/dbstoreadapter.go index 10c175a99..7a299471f 100644 --- a/store/dbstoreadapter.go +++ b/store/dbstoreadapter.go @@ -10,7 +10,7 @@ type dbStoreAdapter struct { } // Implements Store. -func (_ dbStoreAdapter) GetStoreType() StoreType { +func (dbStoreAdapter) GetStoreType() StoreType { return sdk.StoreTypeDB } diff --git a/store/firstlast.go b/store/firstlast.go index e0c8b11bb..e6cb08432 100644 --- a/store/firstlast.go +++ b/store/firstlast.go @@ -2,6 +2,7 @@ package store import ( "bytes" + cmn "github.com/tendermint/tmlibs/common" ) @@ -22,9 +23,8 @@ func Last(st KVStore, start, end []byte) (kv cmn.KVPair, ok bool) { if !iter.Valid() { if v := st.Get(start); v != nil { return cmn.KVPair{cp(start), cp(v)}, true - } else { - return kv, false } + return kv, false } defer iter.Close() diff --git a/store/iavlstore.go b/store/iavlstore.go index 7d006d3c1..de32e27e1 100644 --- a/store/iavlstore.go +++ b/store/iavlstore.go @@ -17,6 +17,7 @@ const ( defaultIAVLNumHistory = 1<<53 - 1 // DEPRECATED ) +// load the iavl store func LoadIAVLStore(db dbm.DB, id CommitID) (CommitStore, error) { tree := iavl.NewVersionedTree(db, defaultIAVLCacheSize) _, err := tree.LoadVersion(id.Version) diff --git a/store/iavlstore_test.go b/store/iavlstore_test.go index 824617c26..4557dea06 100644 --- a/store/iavlstore_test.go +++ b/store/iavlstore_test.go @@ -80,7 +80,7 @@ func TestIAVLIterator(t *testing.T) { key, value := iter.Key(), iter.Value() assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, value, treeData[expectedKey]) - i += 1 + i++ } assert.Equal(t, len(expected), i) @@ -91,7 +91,7 @@ func TestIAVLIterator(t *testing.T) { key, value := iter.Key(), iter.Value() assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, value, treeData[expectedKey]) - i += 1 + i++ } assert.Equal(t, len(expected), i) @@ -102,7 +102,7 @@ func TestIAVLIterator(t *testing.T) { key, value := iter.Key(), iter.Value() assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, value, treeData[expectedKey]) - i += 1 + i++ } assert.Equal(t, len(expected), i) @@ -113,7 +113,7 @@ func TestIAVLIterator(t *testing.T) { key, value := iter.Key(), iter.Value() assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, value, treeData[expectedKey]) - i += 1 + i++ } assert.Equal(t, len(expected), i) @@ -124,7 +124,7 @@ func TestIAVLIterator(t *testing.T) { key, value := iter.Key(), iter.Value() assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, value, treeData[expectedKey]) - i += 1 + i++ } assert.Equal(t, len(expected), i) @@ -135,7 +135,7 @@ func TestIAVLIterator(t *testing.T) { key, value := iter.Key(), iter.Value() assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, value, treeData[expectedKey]) - i += 1 + i++ } assert.Equal(t, len(expected), i) } @@ -164,7 +164,7 @@ func TestIAVLSubspaceIterator(t *testing.T) { key, value := iter.Key(), iter.Value() assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, value, expectedKey) - i += 1 + i++ } assert.Equal(t, len(expected), i) @@ -179,7 +179,7 @@ func TestIAVLSubspaceIterator(t *testing.T) { key, value := iter.Key(), iter.Value() assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, value, []byte("test4")) - i += 1 + i++ } assert.Equal(t, len(expected), i) @@ -194,7 +194,7 @@ func TestIAVLSubspaceIterator(t *testing.T) { key, value := iter.Key(), iter.Value() assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, value, []byte("test4")) - i += 1 + i++ } assert.Equal(t, len(expected), i) } @@ -223,7 +223,7 @@ func TestIAVLReverseSubspaceIterator(t *testing.T) { key, value := iter.Key(), iter.Value() assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, value, expectedKey) - i += 1 + i++ } assert.Equal(t, len(expected), i) @@ -238,7 +238,7 @@ func TestIAVLReverseSubspaceIterator(t *testing.T) { key, value := iter.Key(), iter.Value() assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, value, []byte("test4")) - i += 1 + i++ } assert.Equal(t, len(expected), i) @@ -253,7 +253,7 @@ func TestIAVLReverseSubspaceIterator(t *testing.T) { key, value := iter.Key(), iter.Value() assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, value, []byte("test4")) - i += 1 + i++ } assert.Equal(t, len(expected), i) } diff --git a/store/rootmultistore.go b/store/rootmultistore.go index 3e094712b..217e8eb14 100644 --- a/store/rootmultistore.go +++ b/store/rootmultistore.go @@ -33,6 +33,7 @@ type rootMultiStore struct { var _ CommitMultiStore = (*rootMultiStore)(nil) var _ Queryable = (*rootMultiStore)(nil) +// nolint func NewCommitMultiStore(db dbm.DB) *rootMultiStore { return &rootMultiStore{ db: db, @@ -267,7 +268,7 @@ func (rs *rootMultiStore) loadCommitStoreFromParams(id CommitID, params storePar } func (rs *rootMultiStore) nameToKey(name string) StoreKey { - for key, _ := range rs.storesParams { + for key := range rs.storesParams { if key.Name() == name { return key } diff --git a/store/types.go b/store/types.go index fa27e94da..ca43dab6b 100644 --- a/store/types.go +++ b/store/types.go @@ -5,6 +5,7 @@ import ( ) // Import cosmos-sdk/types/store.go for convenience. +// nolint type Store = types.Store type Committer = types.Committer type CommitStore = types.CommitStore diff --git a/types/errors.go b/types/errors.go index c2fe726a2..059a0dd74 100644 --- a/types/errors.go +++ b/types/errors.go @@ -25,6 +25,7 @@ func (code ABCICodeType) IsOK() bool { return false } +// get the abci code from the local code and codespace func ToABCICode(space CodespaceType, code CodeType) ABCICodeType { // TODO: Make Tendermint more aware of codespaces. if space == CodespaceRoot && code == CodeOK { @@ -33,6 +34,7 @@ func ToABCICode(space CodespaceType, code CodeType) ABCICodeType { return ABCICodeType((uint32(space) << 16) | uint32(code)) } +// SDK error codes const ( // ABCI error codes ABCICodeOK ABCICodeType = 0 diff --git a/version/command.go b/version/command.go index e28cbe57e..b505414b1 100644 --- a/version/command.go +++ b/version/command.go @@ -25,15 +25,13 @@ func getVersion() string { } // CMD - func printVersion(cmd *cobra.Command, args []string) { v := getVersion() fmt.Println(v) } -// REST - -func VersionRequestHandler(w http.ResponseWriter, r *http.Request) { +// version REST handler endpoint +func RequestHandler(w http.ResponseWriter, r *http.Request) { v := getVersion() w.Write([]byte(v)) } diff --git a/wire/wire.go b/wire/wire.go index 32c82a676..0ee01939d 100644 --- a/wire/wire.go +++ b/wire/wire.go @@ -8,6 +8,7 @@ import ( "github.com/tendermint/go-crypto" ) +// amino codec to marshal/unmarshal type Codec = amino.Codec func NewCodec() *Codec { @@ -15,10 +16,12 @@ func NewCodec() *Codec { return cdc } +// Register the go-crypto to the codec func RegisterCrypto(cdc *Codec) { crypto.RegisterAmino(cdc) } +// attempt to make some pretty json func MarshalJSONIndent(cdc *Codec, obj interface{}) ([]byte, error) { bz, err := cdc.MarshalJSON(obj) if err != nil { diff --git a/x/auth/commands/account.go b/x/auth/commands/account.go index 56f441f35..4da601df8 100644 --- a/x/auth/commands/account.go +++ b/x/auth/commands/account.go @@ -17,6 +17,7 @@ func GetAccountCmdDefault(storeName string, cdc *wire.Codec) *cobra.Command { return GetAccountCmd(storeName, cdc, GetAccountDecoder(cdc)) } +// Get account decoder for auth.DefaultAccount func GetAccountDecoder(cdc *wire.Codec) sdk.AccountDecoder { return func(accBytes []byte) (acct sdk.Account, err error) { // acct := new(auth.BaseAccount) diff --git a/x/auth/context.go b/x/auth/context.go index 91259d9e6..b233f1e86 100644 --- a/x/auth/context.go +++ b/x/auth/context.go @@ -33,10 +33,12 @@ const ( contextKeySigners contextKey = iota ) +// add the signers to the context func WithSigners(ctx types.Context, accounts []types.Account) types.Context { return ctx.WithValue(contextKeySigners, accounts) } +// get the signers from the context func GetSigners(ctx types.Context) []types.Account { v := ctx.Value(contextKeySigners) if v == nil { diff --git a/x/auth/mapper.go b/x/auth/mapper.go index 7bc23aee1..ed69034be 100644 --- a/x/auth/mapper.go +++ b/x/auth/mapper.go @@ -28,6 +28,7 @@ type accountMapper struct { // NewAccountMapper returns a new sdk.AccountMapper that // uses go-amino to (binary) encode and decode concrete sdk.Accounts. +// nolint func NewAccountMapper(cdc *wire.Codec, key sdk.StoreKey, proto sdk.Account) accountMapper { return accountMapper{ key: key, @@ -107,14 +108,14 @@ func (am accountMapper) clonePrototype() sdk.Account { panic(fmt.Sprintf("accountMapper requires a proto sdk.Account, but %v doesn't implement sdk.Account", protoRt)) } return clone - } else { - protoRv := reflect.New(protoRt).Elem() - clone, ok := protoRv.Interface().(sdk.Account) - if !ok { - panic(fmt.Sprintf("accountMapper requires a proto sdk.Account, but %v doesn't implement sdk.Account", protoRt)) - } - return clone } + + protoRv := reflect.New(protoRt).Elem() + clone, ok := protoRv.Interface().(sdk.Account) + if !ok { + panic(fmt.Sprintf("accountMapper requires a proto sdk.Account, but %v doesn't implement sdk.Account", protoRt)) + } + return clone } func (am accountMapper) encodeAccount(acc sdk.Account) []byte { diff --git a/x/auth/rest/query.go b/x/auth/rest/query.go index c401fe47f..b97f883f9 100644 --- a/x/auth/rest/query.go +++ b/x/auth/rest/query.go @@ -10,16 +10,19 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" + auth "github.com/cosmos/cosmos-sdk/x/auth/commands" ) -type commander struct { - storeName string - cdc *wire.Codec - decoder sdk.AccountDecoder +// register REST routes +func RegisterRoutes(r *mux.Router, cdc *wire.Codec, storeName string) { + r.HandleFunc( + "/accounts/{address}", + QueryAccountRequestHandler(storeName, cdc, auth.GetAccountDecoder(cdc)), + ).Methods("GET") } +// query accountREST Handler func QueryAccountRequestHandler(storeName string, cdc *wire.Codec, decoder sdk.AccountDecoder) func(http.ResponseWriter, *http.Request) { - c := commander{storeName, cdc, decoder} ctx := context.NewCoreContextFromViper() return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -33,7 +36,7 @@ func QueryAccountRequestHandler(storeName string, cdc *wire.Codec, decoder sdk.A } key := sdk.Address(bz) - res, err := ctx.Query(key, c.storeName) + res, err := ctx.Query(key, storeName) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf("Could't query account. Error: %s", err.Error()))) @@ -47,7 +50,7 @@ func QueryAccountRequestHandler(storeName string, cdc *wire.Codec, decoder sdk.A } // decode the value - account, err := c.decoder(res) + account, err := decoder(res) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf("Could't parse query result. Result: %s. Error: %s", res, err.Error()))) diff --git a/x/auth/rest/root.go b/x/auth/rest/root.go deleted file mode 100644 index 5417cf868..000000000 --- a/x/auth/rest/root.go +++ /dev/null @@ -1,11 +0,0 @@ -package rest - -import ( - "github.com/cosmos/cosmos-sdk/wire" - auth "github.com/cosmos/cosmos-sdk/x/auth/commands" - "github.com/gorilla/mux" -) - -func RegisterRoutes(r *mux.Router, cdc *wire.Codec, storeName string) { - r.HandleFunc("/accounts/{address}", QueryAccountRequestHandler(storeName, cdc, auth.GetAccountDecoder(cdc))).Methods("GET") -} diff --git a/x/bank/commands/sendtx.go b/x/bank/commands/sendtx.go index 56048262d..dbf2bb3c9 100644 --- a/x/bank/commands/sendtx.go +++ b/x/bank/commands/sendtx.go @@ -20,68 +20,53 @@ const ( ) // SendTxCommand will create a send tx and sign it with the given key -func SendTxCmd(Cdc *wire.Codec) *cobra.Command { - cmdr := Commander{Cdc} +func SendTxCmd(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "send", Short: "Create and sign a send tx", - RunE: cmdr.sendTxCmd, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) + + // get the from/to address + from, err := ctx.GetFromAddress() + if err != nil { + return err + } + + toStr := viper.GetString(flagTo) + bz, err := hex.DecodeString(toStr) + if err != nil { + return err + } + to := sdk.Address(bz) + + // parse coins + amount := viper.GetString(flagAmount) + coins, err := sdk.ParseCoins(amount) + if err != nil { + return err + } + + // build and sign the transaction, then broadcast to Tendermint + msg := BuildMsg(from, to, coins) + res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc) + if err != nil { + return err + } + fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) + return nil + }, } + cmd.Flags().String(flagTo, "", "Address to send coins") cmd.Flags().String(flagAmount, "", "Amount of coins to send") return cmd } -type Commander struct { - Cdc *wire.Codec -} - -func (c Commander) sendTxCmd(cmd *cobra.Command, args []string) error { - ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(c.Cdc)) - - // get the from address - from, err := ctx.GetFromAddress() - if err != nil { - return err - } - - // parse coins - amount := viper.GetString(flagAmount) - coins, err := sdk.ParseCoins(amount) - if err != nil { - return err - } - - // parse destination address - dest := viper.GetString(flagTo) - bz, err := hex.DecodeString(dest) - if err != nil { - return err - } - to := sdk.Address(bz) - - // build message - msg := BuildMsg(from, to, coins) - - // default to next sequence number if none provided - ctx, err = context.EnsureSequence(ctx) - if err != nil { - return err - } - - // build and sign the transaction, then broadcast to Tendermint - res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, c.Cdc) - if err != nil { - return err - } - - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) - return nil -} - +// build the sendTx msg func BuildMsg(from sdk.Address, to sdk.Address, coins sdk.Coins) sdk.Msg { input := bank.NewInput(from, coins) output := bank.NewOutput(to, coins) - msg := bank.NewSendMsg([]bank.Input{input}, []bank.Output{output}) + msg := bank.NewMsgSend([]bank.Input{input}, []bank.Output{output}) return msg } diff --git a/x/bank/errors.go b/x/bank/errors.go index d7c7e9748..bf2a3ef26 100644 --- a/x/bank/errors.go +++ b/x/bank/errors.go @@ -5,7 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// Coin errors reserve 100 ~ 199. +// Bank errors reserve 100 ~ 199. const ( DefaultCodespace sdk.CodespaceType = 2 diff --git a/x/bank/handler.go b/x/bank/handler.go index 8eca94a86..a50b0afcf 100644 --- a/x/bank/handler.go +++ b/x/bank/handler.go @@ -7,13 +7,13 @@ import ( ) // NewHandler returns a handler for "bank" type messages. -func NewHandler(ck CoinKeeper) sdk.Handler { +func NewHandler(k Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { switch msg := msg.(type) { - case SendMsg: - return handleSendMsg(ctx, ck, msg) - case IssueMsg: - return handleIssueMsg(ctx, ck, msg) + case MsgSend: + return handleMsgSend(ctx, k, msg) + case MsgIssue: + return handleMsgIssue(ctx, k, msg) default: errMsg := "Unrecognized bank Msg type: " + reflect.TypeOf(msg).Name() return sdk.ErrUnknownRequest(errMsg).Result() @@ -21,11 +21,11 @@ func NewHandler(ck CoinKeeper) sdk.Handler { } } -// Handle SendMsg. -func handleSendMsg(ctx sdk.Context, ck CoinKeeper, msg SendMsg) sdk.Result { +// Handle MsgSend. +func handleMsgSend(ctx sdk.Context, k Keeper, msg MsgSend) sdk.Result { // NOTE: totalIn == totalOut should already have been checked - err := ck.InputOutputCoins(ctx, msg.Inputs, msg.Outputs) + err := k.InputOutputCoins(ctx, msg.Inputs, msg.Outputs) if err != nil { return err.Result() } @@ -34,7 +34,7 @@ func handleSendMsg(ctx sdk.Context, ck CoinKeeper, msg SendMsg) sdk.Result { return sdk.Result{} // TODO } -// Handle IssueMsg. -func handleIssueMsg(ctx sdk.Context, ck CoinKeeper, msg IssueMsg) sdk.Result { +// Handle MsgIssue. +func handleMsgIssue(ctx sdk.Context, k Keeper, msg MsgIssue) sdk.Result { panic("not implemented yet") } diff --git a/x/bank/keeper.go b/x/bank/keeper.go index a5fabdbb0..d1fdeaea0 100644 --- a/x/bank/keeper.go +++ b/x/bank/keeper.go @@ -6,7 +6,106 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -const moduleName = "bank" +// Keeper manages transfers between accounts +type Keeper struct { + am sdk.AccountMapper +} + +// NewKeeper returns a new Keeper +func NewKeeper(am sdk.AccountMapper) Keeper { + return Keeper{am: am} +} + +// GetCoins returns the coins at the addr. +func (keeper Keeper) GetCoins(ctx sdk.Context, addr sdk.Address) sdk.Coins { + return getCoins(ctx, keeper.am, addr) +} + +// SetCoins sets the coins at the addr. +func (keeper Keeper) SetCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) sdk.Error { + return setCoins(ctx, keeper.am, addr, amt) +} + +// HasCoins returns whether or not an account has at least amt coins. +func (keeper Keeper) HasCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) bool { + return hasCoins(ctx, keeper.am, addr, amt) +} + +// SubtractCoins subtracts amt from the coins at the addr. +func (keeper Keeper) SubtractCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Error) { + return subtractCoins(ctx, keeper.am, addr, amt) +} + +// AddCoins adds amt to the coins at the addr. +func (keeper Keeper) AddCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Error) { + return addCoins(ctx, keeper.am, addr, amt) +} + +// SendCoins moves coins from one account to another +func (keeper Keeper) SendCoins(ctx sdk.Context, fromAddr sdk.Address, toAddr sdk.Address, amt sdk.Coins) sdk.Error { + return sendCoins(ctx, keeper.am, fromAddr, toAddr, amt) +} + +// InputOutputCoins handles a list of inputs and outputs +func (keeper Keeper) InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) sdk.Error { + return inputOutputCoins(ctx, keeper.am, inputs, outputs) +} + +//______________________________________________________________________________________________ + +// SendKeeper only allows transfers between accounts, without the possibility of creating coins +type SendKeeper struct { + am sdk.AccountMapper +} + +// NewSendKeeper returns a new Keeper +func NewSendKeeper(am sdk.AccountMapper) SendKeeper { + return SendKeeper{am: am} +} + +// GetCoins returns the coins at the addr. +func (keeper SendKeeper) GetCoins(ctx sdk.Context, addr sdk.Address) sdk.Coins { + return getCoins(ctx, keeper.am, addr) +} + +// HasCoins returns whether or not an account has at least amt coins. +func (keeper SendKeeper) HasCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) bool { + return hasCoins(ctx, keeper.am, addr, amt) +} + +// SendCoins moves coins from one account to another +func (keeper SendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.Address, toAddr sdk.Address, amt sdk.Coins) sdk.Error { + return sendCoins(ctx, keeper.am, fromAddr, toAddr, amt) +} + +// InputOutputCoins handles a list of inputs and outputs +func (keeper SendKeeper) InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) sdk.Error { + return inputOutputCoins(ctx, keeper.am, inputs, outputs) +} + +//______________________________________________________________________________________________ + +// ViewKeeper only allows reading of balances +type ViewKeeper struct { + am sdk.AccountMapper +} + +// NewViewKeeper returns a new Keeper +func NewViewKeeper(am sdk.AccountMapper) ViewKeeper { + return ViewKeeper{am: am} +} + +// GetCoins returns the coins at the addr. +func (keeper ViewKeeper) GetCoins(ctx sdk.Context, addr sdk.Address) sdk.Coins { + return getCoins(ctx, keeper.am, addr) +} + +// HasCoins returns whether or not an account has at least amt coins. +func (keeper ViewKeeper) HasCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) bool { + return hasCoins(ctx, keeper.am, addr, amt) +} + +//______________________________________________________________________________________________ func getCoins(ctx sdk.Context, am sdk.AccountMapper, addr sdk.Address) sdk.Coins { acc := am.GetAccount(ctx, addr) @@ -88,102 +187,3 @@ func inputOutputCoins(ctx sdk.Context, am sdk.AccountMapper, inputs []Input, out return nil } - -// CoinKeeper manages transfers between accounts -type CoinKeeper struct { - am sdk.AccountMapper -} - -// NewCoinKeeper returns a new CoinKeeper -func NewCoinKeeper(am sdk.AccountMapper) CoinKeeper { - return CoinKeeper{am: am} -} - -// GetCoins returns the coins at the addr. -func (keeper CoinKeeper) GetCoins(ctx sdk.Context, addr sdk.Address) sdk.Coins { - return getCoins(ctx, keeper.am, addr) -} - -// SetCoins sets the coins at the addr. -func (keeper CoinKeeper) SetCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) sdk.Error { - return setCoins(ctx, keeper.am, addr, amt) -} - -// HasCoins returns whether or not an account has at least amt coins. -func (keeper CoinKeeper) HasCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) bool { - return hasCoins(ctx, keeper.am, addr, amt) -} - -// SubtractCoins subtracts amt from the coins at the addr. -func (keeper CoinKeeper) SubtractCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Error) { - return subtractCoins(ctx, keeper.am, addr, amt) -} - -// AddCoins adds amt to the coins at the addr. -func (keeper CoinKeeper) AddCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Error) { - return addCoins(ctx, keeper.am, addr, amt) -} - -// SendCoins moves coins from one account to another -func (keeper CoinKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.Address, toAddr sdk.Address, amt sdk.Coins) sdk.Error { - return sendCoins(ctx, keeper.am, fromAddr, toAddr, amt) -} - -// InputOutputCoins handles a list of inputs and outputs -func (keeper CoinKeeper) InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) sdk.Error { - return inputOutputCoins(ctx, keeper.am, inputs, outputs) -} - -// -------------------------------------------------- - -// SendKeeper only allows transfers between accounts, without the possibility of creating coins -type SendKeeper struct { - am sdk.AccountMapper -} - -// NewSendKeeper returns a new CoinKeeper -func NewSendKeeper(am sdk.AccountMapper) SendKeeper { - return SendKeeper{am: am} -} - -// GetCoins returns the coins at the addr. -func (keeper SendKeeper) GetCoins(ctx sdk.Context, addr sdk.Address) sdk.Coins { - return getCoins(ctx, keeper.am, addr) -} - -// HasCoins returns whether or not an account has at least amt coins. -func (keeper SendKeeper) HasCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) bool { - return hasCoins(ctx, keeper.am, addr, amt) -} - -// SendCoins moves coins from one account to another -func (keeper SendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.Address, toAddr sdk.Address, amt sdk.Coins) sdk.Error { - return sendCoins(ctx, keeper.am, fromAddr, toAddr, amt) -} - -// InputOutputCoins handles a list of inputs and outputs -func (keeper SendKeeper) InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) sdk.Error { - return inputOutputCoins(ctx, keeper.am, inputs, outputs) -} - -// -------------------------------------------------- - -// ViewKeeper only allows reading of balances -type ViewKeeper struct { - am sdk.AccountMapper -} - -// NewViewKeeper returns a new CoinKeeper -func NewViewKeeper(am sdk.AccountMapper) ViewKeeper { - return ViewKeeper{am: am} -} - -// GetCoins returns the coins at the addr. -func (keeper ViewKeeper) GetCoins(ctx sdk.Context, addr sdk.Address) sdk.Coins { - return getCoins(ctx, keeper.am, addr) -} - -// HasCoins returns whether or not an account has at least amt coins. -func (keeper ViewKeeper) HasCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) bool { - return hasCoins(ctx, keeper.am, addr, amt) -} diff --git a/x/bank/keeper_test.go b/x/bank/keeper_test.go index 1e160d472..7db9c275d 100644 --- a/x/bank/keeper_test.go +++ b/x/bank/keeper_test.go @@ -24,7 +24,7 @@ func setupMultiStore() (sdk.MultiStore, *sdk.KVStoreKey) { return ms, authKey } -func TestCoinKeeper(t *testing.T) { +func TestKeeper(t *testing.T) { ms, authKey := setupMultiStore() cdc := wire.NewCodec() @@ -32,7 +32,7 @@ func TestCoinKeeper(t *testing.T) { ctx := sdk.NewContext(ms, abci.Header{}, false, nil) accountMapper := auth.NewAccountMapper(cdc, authKey, &auth.BaseAccount{}) - coinKeeper := NewCoinKeeper(accountMapper) + coinKeeper := NewKeeper(accountMapper) addr := sdk.Address([]byte("addr1")) addr2 := sdk.Address([]byte("addr2")) @@ -118,7 +118,7 @@ func TestSendKeeper(t *testing.T) { ctx := sdk.NewContext(ms, abci.Header{}, false, nil) accountMapper := auth.NewAccountMapper(cdc, authKey, &auth.BaseAccount{}) - coinKeeper := NewCoinKeeper(accountMapper) + coinKeeper := NewKeeper(accountMapper) sendKeeper := NewSendKeeper(accountMapper) addr := sdk.Address([]byte("addr1")) @@ -187,7 +187,7 @@ func TestViewKeeper(t *testing.T) { ctx := sdk.NewContext(ms, abci.Header{}, false, nil) accountMapper := auth.NewAccountMapper(cdc, authKey, &auth.BaseAccount{}) - coinKeeper := NewCoinKeeper(accountMapper) + coinKeeper := NewKeeper(accountMapper) viewKeeper := NewViewKeeper(accountMapper) addr := sdk.Address([]byte("addr1")) diff --git a/x/bank/msgs.go b/x/bank/msgs.go index c0f2ad46a..0b0ea471e 100644 --- a/x/bank/msgs.go +++ b/x/bank/msgs.go @@ -2,29 +2,28 @@ package bank import ( "encoding/json" - "fmt" sdk "github.com/cosmos/cosmos-sdk/types" ) -// SendMsg - high level transaction of the coin module -type SendMsg struct { +// MsgSend - high level transaction of the coin module +type MsgSend struct { Inputs []Input `json:"inputs"` Outputs []Output `json:"outputs"` } -var _ sdk.Msg = SendMsg{} +var _ sdk.Msg = MsgSend{} -// NewSendMsg - construct arbitrary multi-in, multi-out send msg. -func NewSendMsg(in []Input, out []Output) SendMsg { - return SendMsg{Inputs: in, Outputs: out} +// NewMsgSend - construct arbitrary multi-in, multi-out send msg. +func NewMsgSend(in []Input, out []Output) MsgSend { + return MsgSend{Inputs: in, Outputs: out} } // Implements Msg. -func (msg SendMsg) Type() string { return "bank" } // TODO: "bank/send" +func (msg MsgSend) Type() string { return "bank" } // TODO: "bank/send" // Implements Msg. -func (msg SendMsg) ValidateBasic() sdk.Error { +func (msg MsgSend) ValidateBasic() sdk.Error { // this just makes sure all the inputs and outputs are properly formatted, // not that they actually have the money inside if len(msg.Inputs) == 0 { @@ -54,17 +53,13 @@ func (msg SendMsg) ValidateBasic() sdk.Error { return nil } -func (msg SendMsg) String() string { - return fmt.Sprintf("SendMsg{%v->%v}", msg.Inputs, msg.Outputs) -} - // Implements Msg. -func (msg SendMsg) Get(key interface{}) (value interface{}) { +func (msg MsgSend) Get(key interface{}) (value interface{}) { return nil } // Implements Msg. -func (msg SendMsg) GetSignBytes() []byte { +func (msg MsgSend) GetSignBytes() []byte { b, err := json.Marshal(msg) // XXX: ensure some canonical form if err != nil { panic(err) @@ -73,7 +68,7 @@ func (msg SendMsg) GetSignBytes() []byte { } // Implements Msg. -func (msg SendMsg) GetSigners() []sdk.Address { +func (msg MsgSend) GetSigners() []sdk.Address { addrs := make([]sdk.Address, len(msg.Inputs)) for i, in := range msg.Inputs { addrs[i] = in.Address @@ -82,24 +77,24 @@ func (msg SendMsg) GetSigners() []sdk.Address { } //---------------------------------------- -// IssueMsg +// MsgIssue -// IssueMsg - high level transaction of the coin module -type IssueMsg struct { +// MsgIssue - high level transaction of the coin module +type MsgIssue struct { Banker sdk.Address `json:"banker"` Outputs []Output `json:"outputs"` } -// NewIssueMsg - construct arbitrary multi-in, multi-out send msg. -func NewIssueMsg(banker sdk.Address, out []Output) IssueMsg { - return IssueMsg{Banker: banker, Outputs: out} +// NewMsgIssue - construct arbitrary multi-in, multi-out send msg. +func NewMsgIssue(banker sdk.Address, out []Output) MsgIssue { + return MsgIssue{Banker: banker, Outputs: out} } // Implements Msg. -func (msg IssueMsg) Type() string { return "bank" } // TODO: "bank/issue" +func (msg MsgIssue) Type() string { return "bank" } // TODO: "bank/issue" // Implements Msg. -func (msg IssueMsg) ValidateBasic() sdk.Error { +func (msg MsgIssue) ValidateBasic() sdk.Error { // XXX if len(msg.Outputs) == 0 { return ErrNoOutputs(DefaultCodespace).Trace("") @@ -112,17 +107,13 @@ func (msg IssueMsg) ValidateBasic() sdk.Error { return nil } -func (msg IssueMsg) String() string { - return fmt.Sprintf("IssueMsg{%v#%v}", msg.Banker, msg.Outputs) -} - // Implements Msg. -func (msg IssueMsg) Get(key interface{}) (value interface{}) { +func (msg MsgIssue) Get(key interface{}) (value interface{}) { return nil } // Implements Msg. -func (msg IssueMsg) GetSignBytes() []byte { +func (msg MsgIssue) GetSignBytes() []byte { b, err := json.Marshal(msg) // XXX: ensure some canonical form if err != nil { panic(err) @@ -131,7 +122,7 @@ func (msg IssueMsg) GetSignBytes() []byte { } // Implements Msg. -func (msg IssueMsg) GetSigners() []sdk.Address { +func (msg MsgIssue) GetSigners() []sdk.Address { return []sdk.Address{msg.Banker} } @@ -158,11 +149,7 @@ func (in Input) ValidateBasic() sdk.Error { return nil } -func (in Input) String() string { - return fmt.Sprintf("Input{%v,%v}", in.Address, in.Coins) -} - -// NewInput - create a transaction input, used with SendMsg +// NewInput - create a transaction input, used with MsgSend func NewInput(addr sdk.Address, coins sdk.Coins) Input { input := Input{ Address: addr, @@ -194,11 +181,7 @@ func (out Output) ValidateBasic() sdk.Error { return nil } -func (out Output) String() string { - return fmt.Sprintf("Output{%v,%v}", out.Address, out.Coins) -} - -// NewOutput - create a transaction output, used with SendMsg +// NewOutput - create a transaction output, used with MsgSend func NewOutput(addr sdk.Address, coins sdk.Coins) Output { output := Output{ Address: addr, diff --git a/x/bank/msgs_test.go b/x/bank/msgs_test.go index b158405d9..d3e1ef4f6 100644 --- a/x/bank/msgs_test.go +++ b/x/bank/msgs_test.go @@ -9,14 +9,14 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func TestNewSendMsg(t *testing.T) {} +func TestNewMsgSend(t *testing.T) {} -func TestSendMsgType(t *testing.T) { - // Construct a SendMsg +func TestMsgSendType(t *testing.T) { + // Construct a MsgSend addr1 := sdk.Address([]byte("input")) addr2 := sdk.Address([]byte("output")) coins := sdk.Coins{{"atom", 10}} - var msg = SendMsg{ + var msg = MsgSend{ Inputs: []Input{NewInput(addr1, coins)}, Outputs: []Output{NewOutput(addr2, coins)}, } @@ -109,7 +109,7 @@ func TestOutputValidation(t *testing.T) { } } -func TestSendMsgValidation(t *testing.T) { +func TestMsgSendValidation(t *testing.T) { addr1 := sdk.Address([]byte{1, 2}) addr2 := sdk.Address([]byte{7, 8}) atom123 := sdk.Coins{{"atom", 123}} @@ -128,40 +128,40 @@ func TestSendMsgValidation(t *testing.T) { cases := []struct { valid bool - tx SendMsg + tx MsgSend }{ - {false, SendMsg{}}, // no input or output - {false, SendMsg{Inputs: []Input{input1}}}, // just input - {false, SendMsg{Outputs: []Output{output1}}}, // just ouput - {false, SendMsg{ + {false, MsgSend{}}, // no input or output + {false, MsgSend{Inputs: []Input{input1}}}, // just input + {false, MsgSend{Outputs: []Output{output1}}}, // just ouput + {false, MsgSend{ Inputs: []Input{NewInput(emptyAddr, atom123)}, // invalid input Outputs: []Output{output1}}}, - {false, SendMsg{ + {false, MsgSend{ Inputs: []Input{input1}, Outputs: []Output{{emptyAddr, atom123}}}, // invalid ouput }, - {false, SendMsg{ + {false, MsgSend{ Inputs: []Input{input1}, Outputs: []Output{output2}}, // amounts dont match }, - {false, SendMsg{ + {false, MsgSend{ Inputs: []Input{input1}, Outputs: []Output{output3}}, // amounts dont match }, - {false, SendMsg{ + {false, MsgSend{ Inputs: []Input{input1}, Outputs: []Output{outputMulti}}, // amounts dont match }, - {false, SendMsg{ + {false, MsgSend{ Inputs: []Input{input2}, Outputs: []Output{output1}}, // amounts dont match }, - {true, SendMsg{ + {true, MsgSend{ Inputs: []Input{input1}, Outputs: []Output{output1}}, }, - {true, SendMsg{ + {true, MsgSend{ Inputs: []Input{input1, input2}, Outputs: []Output{outputMulti}}, }, @@ -177,29 +177,11 @@ func TestSendMsgValidation(t *testing.T) { } } -func TestSendMsgString(t *testing.T) { - // Construct a SendMsg - addr1String := "input" - addr2String := "output" - addr1 := sdk.Address([]byte(addr1String)) - addr2 := sdk.Address([]byte(addr2String)) - coins := sdk.Coins{{"atom", 10}} - var msg = SendMsg{ - Inputs: []Input{NewInput(addr1, coins)}, - Outputs: []Output{NewOutput(addr2, coins)}, - } - - res := msg.String() - expected := fmt.Sprintf("SendMsg{[Input{%X,10atom}]->[Output{%X,10atom}]}", addr1String, addr2String) - // TODO some failures for bad results - assert.Equal(t, expected, res) -} - -func TestSendMsgGet(t *testing.T) { +func TestMsgSendGet(t *testing.T) { addr1 := sdk.Address([]byte("input")) addr2 := sdk.Address([]byte("output")) coins := sdk.Coins{{"atom", 10}} - var msg = SendMsg{ + var msg = MsgSend{ Inputs: []Input{NewInput(addr1, coins)}, Outputs: []Output{NewOutput(addr2, coins)}, } @@ -207,11 +189,11 @@ func TestSendMsgGet(t *testing.T) { assert.Nil(t, res) } -func TestSendMsgGetSignBytes(t *testing.T) { +func TestMsgSendGetSignBytes(t *testing.T) { addr1 := sdk.Address([]byte("input")) addr2 := sdk.Address([]byte("output")) coins := sdk.Coins{{"atom", 10}} - var msg = SendMsg{ + var msg = MsgSend{ Inputs: []Input{NewInput(addr1, coins)}, Outputs: []Output{NewOutput(addr2, coins)}, } @@ -220,8 +202,8 @@ func TestSendMsgGetSignBytes(t *testing.T) { assert.Equal(t, string(res), `{"inputs":[{"address":"696E707574","coins":[{"denom":"atom","amount":10}]}],"outputs":[{"address":"6F7574707574","coins":[{"denom":"atom","amount":10}]}]}`) } -func TestSendMsgGetSigners(t *testing.T) { - var msg = SendMsg{ +func TestMsgSendGetSigners(t *testing.T) { + var msg = MsgSend{ Inputs: []Input{ NewInput(sdk.Address([]byte("input1")), nil), NewInput(sdk.Address([]byte("input2")), nil), @@ -235,7 +217,7 @@ func TestSendMsgGetSigners(t *testing.T) { /* // what to do w/ this test? -func TestSendMsgSigners(t *testing.T) { +func TestMsgSendSigners(t *testing.T) { signers := []sdk.Address{ {1, 2, 3}, {4, 5, 6}, @@ -247,24 +229,24 @@ func TestSendMsgSigners(t *testing.T) { for i, signer := range signers { inputs[i] = NewInput(signer, someCoins) } - tx := NewSendMsg(inputs, nil) + tx := NewMsgSend(inputs, nil) assert.Equal(t, signers, tx.Signers()) } */ // ---------------------------------------- -// IssueMsg Tests +// MsgIssue Tests -func TestNewIssueMsg(t *testing.T) { +func TestNewMsgIssue(t *testing.T) { // TODO } -func TestIssueMsgType(t *testing.T) { - // Construct an IssueMsg +func TestMsgIssueType(t *testing.T) { + // Construct an MsgIssue addr := sdk.Address([]byte("loan-from-bank")) coins := sdk.Coins{{"atom", 10}} - var msg = IssueMsg{ + var msg = MsgIssue{ Banker: sdk.Address([]byte("input")), Outputs: []Output{NewOutput(addr, coins)}, } @@ -273,29 +255,14 @@ func TestIssueMsgType(t *testing.T) { assert.Equal(t, msg.Type(), "bank") } -func TestIssueMsgValidation(t *testing.T) { +func TestMsgIssueValidation(t *testing.T) { // TODO } -func TestIssueMsgString(t *testing.T) { - addrString := "loan-from-bank" - bankerString := "input" - // Construct a IssueMsg - addr := sdk.Address([]byte(addrString)) - coins := sdk.Coins{{"atom", 10}} - var msg = IssueMsg{ - Banker: sdk.Address([]byte(bankerString)), - Outputs: []Output{NewOutput(addr, coins)}, - } - res := msg.String() - expected := fmt.Sprintf("IssueMsg{%X#[Output{%X,10atom}]}", bankerString, addrString) - assert.Equal(t, expected, res) -} - -func TestIssueMsgGet(t *testing.T) { +func TestMsgIssueGet(t *testing.T) { addr := sdk.Address([]byte("loan-from-bank")) coins := sdk.Coins{{"atom", 10}} - var msg = IssueMsg{ + var msg = MsgIssue{ Banker: sdk.Address([]byte("input")), Outputs: []Output{NewOutput(addr, coins)}, } @@ -303,10 +270,10 @@ func TestIssueMsgGet(t *testing.T) { assert.Nil(t, res) } -func TestIssueMsgGetSignBytes(t *testing.T) { +func TestMsgIssueGetSignBytes(t *testing.T) { addr := sdk.Address([]byte("loan-from-bank")) coins := sdk.Coins{{"atom", 10}} - var msg = IssueMsg{ + var msg = MsgIssue{ Banker: sdk.Address([]byte("input")), Outputs: []Output{NewOutput(addr, coins)}, } @@ -315,8 +282,8 @@ func TestIssueMsgGetSignBytes(t *testing.T) { assert.Equal(t, string(res), `{"banker":"696E707574","outputs":[{"address":"6C6F616E2D66726F6D2D62616E6B","coins":[{"denom":"atom","amount":10}]}]}`) } -func TestIssueMsgGetSigners(t *testing.T) { - var msg = IssueMsg{ +func TestMsgIssueGetSigners(t *testing.T) { + var msg = MsgIssue{ Banker: sdk.Address([]byte("onlyone")), } res := msg.GetSigners() diff --git a/x/bank/rest/root.go b/x/bank/rest/root.go deleted file mode 100644 index 4534482a9..000000000 --- a/x/bank/rest/root.go +++ /dev/null @@ -1,14 +0,0 @@ -package rest - -import ( - "github.com/gorilla/mux" - - keys "github.com/tendermint/go-crypto/keys" - - "github.com/cosmos/cosmos-sdk/wire" -) - -// RegisterRoutes - Central function to define routes that get registered by the main application -func RegisterRoutes(r *mux.Router, cdc *wire.Codec, kb keys.Keybase) { - r.HandleFunc("/accounts/{address}/send", SendRequestHandler(cdc, kb)).Methods("POST") -} diff --git a/x/bank/rest/sendtx.go b/x/bank/rest/sendtx.go index b1f8516f3..eec487a3d 100644 --- a/x/bank/rest/sendtx.go +++ b/x/bank/rest/sendtx.go @@ -15,6 +15,11 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank/commands" ) +// RegisterRoutes - Central function to define routes that get registered by the main application +func RegisterRoutes(r *mux.Router, cdc *wire.Codec, kb keys.Keybase) { + r.HandleFunc("/accounts/{address}/send", SendRequestHandler(cdc, kb)).Methods("POST") +} + type sendBody struct { // fees is not used currently // Fees sdk.Coin `json="fees"` @@ -27,7 +32,6 @@ type sendBody struct { // SendRequestHandler - http request handler to send coins to a address func SendRequestHandler(cdc *wire.Codec, kb keys.Keybase) func(http.ResponseWriter, *http.Request) { - c := commands.Commander{cdc} ctx := context.NewCoreContextFromViper() return func(w http.ResponseWriter, r *http.Request) { // collect data @@ -73,7 +77,7 @@ func SendRequestHandler(cdc *wire.Codec, kb keys.Keybase) func(http.ResponseWrit // sign ctx = ctx.WithSequence(m.Sequence) - txBytes, err := ctx.SignAndBuild(m.LocalAccountName, m.Password, msg, c.Cdc) + txBytes, err := ctx.SignAndBuild(m.LocalAccountName, m.Password, msg, cdc) if err != nil { w.WriteHeader(http.StatusUnauthorized) w.Write([]byte(err.Error())) diff --git a/x/bank/wire.go b/x/bank/wire.go index c53f06564..fdb6c252b 100644 --- a/x/bank/wire.go +++ b/x/bank/wire.go @@ -6,6 +6,6 @@ import ( // Register concrete types on wire codec func RegisterWire(cdc *wire.Codec) { - cdc.RegisterConcrete(SendMsg{}, "cosmos-sdk/Send", nil) - cdc.RegisterConcrete(IssueMsg{}, "cosmos-sdk/Issue", nil) + cdc.RegisterConcrete(MsgSend{}, "cosmos-sdk/Send", nil) + cdc.RegisterConcrete(MsgIssue{}, "cosmos-sdk/Issue", nil) } diff --git a/x/ibc/commands/ibctx.go b/x/ibc/commands/ibctx.go index d17b40b21..1fc53b7e6 100644 --- a/x/ibc/commands/ibctx.go +++ b/x/ibc/commands/ibctx.go @@ -23,53 +23,42 @@ const ( flagChain = "chain" ) +// IBC transfer command func IBCTransferCmd(cdc *wire.Codec) *cobra.Command { - cmdr := sendCommander{cdc} cmd := &cobra.Command{ - Use: "transfer", - RunE: cmdr.sendIBCTransfer, + Use: "transfer", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) + + // get the from address + from, err := ctx.GetFromAddress() + if err != nil { + return err + } + + // build the message + msg, err := buildMsg(from) + if err != nil { + return err + } + + // get password + res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc) + if err != nil { + return err + } + + fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) + return nil + }, } + cmd.Flags().String(flagTo, "", "Address to send coins") cmd.Flags().String(flagAmount, "", "Amount of coins to send") cmd.Flags().String(flagChain, "", "Destination chain to send coins") return cmd } -type sendCommander struct { - cdc *wire.Codec -} - -func (c sendCommander) sendIBCTransfer(cmd *cobra.Command, args []string) error { - ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(c.cdc)) - - // get the from address - from, err := ctx.GetFromAddress() - if err != nil { - return err - } - - // build the message - msg, err := buildMsg(from) - if err != nil { - return err - } - - // default to next sequence number if none provided - ctx, err = context.EnsureSequence(ctx) - if err != nil { - return err - } - - // get password - res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, c.cdc) - if err != nil { - return err - } - - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) - return nil -} - func buildMsg(from sdk.Address) (sdk.Msg, error) { amount := viper.GetString(flagAmount) coins, err := sdk.ParseCoins(amount) diff --git a/x/ibc/commands/relay.go b/x/ibc/commands/relay.go index d652e306f..d772735bb 100644 --- a/x/ibc/commands/relay.go +++ b/x/ibc/commands/relay.go @@ -18,6 +18,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc" ) +// flags const ( FlagFromChainID = "from-chain-id" FlagFromChainNode = "from-chain-node" @@ -35,6 +36,7 @@ type relayCommander struct { logger log.Logger } +// IBC relay command func IBCRelayCmd(cdc *wire.Codec) *cobra.Command { cmdr := relayCommander{ cdc: cdc, @@ -91,6 +93,7 @@ func (c relayCommander) loop(fromChainID, fromChainNode, toChainID, toChainNode } ingressKey := ibc.IngressSequenceKey(fromChainID) + OUTER: for { time.Sleep(5 * time.Second) @@ -111,7 +114,7 @@ OUTER: egressLengthbz, err := query(fromChainNode, lengthKey, c.ibcStore) if err != nil { c.logger.Error("Error querying outgoing packet list length", "err", err) - continue OUTER + continue OUTER //TODO replace with continue (I think it should just to the correct place where OUTER is now) } var egressLength int64 if egressLengthbz == nil { @@ -129,14 +132,14 @@ OUTER: egressbz, err := query(fromChainNode, ibc.EgressKey(toChainID, i), c.ibcStore) if err != nil { c.logger.Error("Error querying egress packet", "err", err) - continue OUTER + continue OUTER // TODO replace to break, will break first loop then send back to the beginning (aka OUTER) } err = c.broadcastTx(seq, toChainNode, c.refine(egressbz, i, passphrase)) seq++ if err != nil { c.logger.Error("Error broadcasting ingress packet", "err", err) - continue OUTER + continue OUTER // TODO replace to break, will break first loop then send back to the beginning (aka OUTER) } c.logger.Info("Relayed IBC packet", "number", i) diff --git a/x/ibc/errors.go b/x/ibc/errors.go index 3c52bed7b..60a141eba 100644 --- a/x/ibc/errors.go +++ b/x/ibc/errors.go @@ -4,6 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +// IBC errors reserve 200 ~ 299. const ( DefaultCodespace sdk.CodespaceType = 3 @@ -24,10 +25,10 @@ func codeToDefaultMsg(code sdk.CodeType) string { } } +// nolint func ErrInvalidSequence(codespace sdk.CodespaceType) sdk.Error { return newError(codespace, CodeInvalidSequence, "") } - func ErrIdenticalChains(codespace sdk.CodespaceType) sdk.Error { return newError(codespace, CodeIdenticalChains, "") } @@ -43,7 +44,6 @@ func newError(codespace sdk.CodespaceType, code sdk.CodeType, msg string) sdk.Er func msgOrDefaultMsg(msg string, code sdk.CodeType) string { if msg != "" { return msg - } else { - return codeToDefaultMsg(code) } + return codeToDefaultMsg(code) } diff --git a/x/ibc/handler.go b/x/ibc/handler.go index dcd00359f..46cbf1e30 100644 --- a/x/ibc/handler.go +++ b/x/ibc/handler.go @@ -7,7 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank" ) -func NewHandler(ibcm IBCMapper, ck bank.CoinKeeper) sdk.Handler { +func NewHandler(ibcm Mapper, ck bank.Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { switch msg := msg.(type) { case IBCTransferMsg: @@ -22,7 +22,7 @@ func NewHandler(ibcm IBCMapper, ck bank.CoinKeeper) sdk.Handler { } // IBCTransferMsg deducts coins from the account and creates an egress IBC packet. -func handleIBCTransferMsg(ctx sdk.Context, ibcm IBCMapper, ck bank.CoinKeeper, msg IBCTransferMsg) sdk.Result { +func handleIBCTransferMsg(ctx sdk.Context, ibcm Mapper, ck bank.Keeper, msg IBCTransferMsg) sdk.Result { packet := msg.IBCPacket _, err := ck.SubtractCoins(ctx, packet.SrcAddr, packet.Coins) @@ -39,7 +39,7 @@ func handleIBCTransferMsg(ctx sdk.Context, ibcm IBCMapper, ck bank.CoinKeeper, m } // IBCReceiveMsg adds coins to the destination address and creates an ingress IBC packet. -func handleIBCReceiveMsg(ctx sdk.Context, ibcm IBCMapper, ck bank.CoinKeeper, msg IBCReceiveMsg) sdk.Result { +func handleIBCReceiveMsg(ctx sdk.Context, ibcm Mapper, ck bank.Keeper, msg IBCReceiveMsg) sdk.Result { packet := msg.IBCPacket seq := ibcm.GetIngressSequence(ctx, packet.SrcChain) diff --git a/x/ibc/ibc_test.go b/x/ibc/ibc_test.go index 1fc724e54..61b9182f1 100644 --- a/x/ibc/ibc_test.go +++ b/x/ibc/ibc_test.go @@ -16,7 +16,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank" ) -// AccountMapper(/CoinKeeper) and IBCMapper should use different StoreKey later +// AccountMapper(/Keeper) and IBCMapper should use different StoreKey later func defaultContext(key sdk.StoreKey) sdk.Context { db := dbm.NewMemDB() @@ -31,7 +31,7 @@ func newAddress() crypto.Address { return crypto.GenPrivKeyEd25519().PubKey().Address() } -func getCoins(ck bank.CoinKeeper, ctx sdk.Context, addr crypto.Address) (sdk.Coins, sdk.Error) { +func getCoins(ck bank.Keeper, ctx sdk.Context, addr crypto.Address) (sdk.Coins, sdk.Error) { zero := sdk.Coins(nil) return ck.AddCoins(ctx, addr, zero) } @@ -41,8 +41,8 @@ func makeCodec() *wire.Codec { // Register Msgs cdc.RegisterInterface((*sdk.Msg)(nil), nil) - cdc.RegisterConcrete(bank.SendMsg{}, "test/ibc/Send", nil) - cdc.RegisterConcrete(bank.IssueMsg{}, "test/ibc/Issue", nil) + cdc.RegisterConcrete(bank.MsgSend{}, "test/ibc/Send", nil) + cdc.RegisterConcrete(bank.MsgIssue{}, "test/ibc/Issue", nil) cdc.RegisterConcrete(IBCTransferMsg{}, "test/ibc/IBCTransferMsg", nil) cdc.RegisterConcrete(IBCReceiveMsg{}, "test/ibc/IBCReceiveMsg", nil) @@ -61,7 +61,7 @@ func TestIBC(t *testing.T) { ctx := defaultContext(key) am := auth.NewAccountMapper(cdc, key, &auth.BaseAccount{}) - ck := bank.NewCoinKeeper(am) + ck := bank.NewKeeper(am) src := newAddress() dest := newAddress() @@ -73,7 +73,7 @@ func TestIBC(t *testing.T) { assert.Nil(t, err) assert.Equal(t, mycoins, coins) - ibcm := NewIBCMapper(cdc, key, DefaultCodespace) + ibcm := NewMapper(cdc, key, DefaultCodespace) h := NewHandler(ibcm, ck) packet := IBCPacket{ SrcAddr: src, diff --git a/x/ibc/mapper.go b/x/ibc/mapper.go index d3ecc779d..06631179b 100644 --- a/x/ibc/mapper.go +++ b/x/ibc/mapper.go @@ -7,17 +7,18 @@ import ( wire "github.com/cosmos/cosmos-sdk/wire" ) -type IBCMapper struct { +// IBC Mapper +type Mapper struct { key sdk.StoreKey cdc *wire.Codec codespace sdk.CodespaceType } -// XXX: The IBCMapper should not take a CoinKeeper. Rather have the CoinKeeper -// take an IBCMapper. -func NewIBCMapper(cdc *wire.Codec, key sdk.StoreKey, codespace sdk.CodespaceType) IBCMapper { +// XXX: The Mapper should not take a CoinKeeper. Rather have the CoinKeeper +// take an Mapper. +func NewMapper(cdc *wire.Codec, key sdk.StoreKey, codespace sdk.CodespaceType) Mapper { // XXX: How are these codecs supposed to work? - return IBCMapper{ + return Mapper{ key: key, cdc: cdc, codespace: codespace, @@ -28,7 +29,7 @@ func NewIBCMapper(cdc *wire.Codec, key sdk.StoreKey, codespace sdk.CodespaceType // only be invoked from another module directly and not through a user // transaction. // TODO: Handle invalid IBC packets and return errors. -func (ibcm IBCMapper) PostIBCPacket(ctx sdk.Context, packet IBCPacket) sdk.Error { +func (ibcm Mapper) PostIBCPacket(ctx sdk.Context, packet IBCPacket) sdk.Error { // write everything into the state store := ctx.KVStore(ibcm.key) index := ibcm.getEgressLength(store, packet.DestChain) @@ -52,7 +53,7 @@ func (ibcm IBCMapper) PostIBCPacket(ctx sdk.Context, packet IBCPacket) sdk.Error // to the appropriate callbacks. // XXX: For now this handles all interactions with the CoinKeeper. // XXX: This needs to do some authentication checking. -func (ibcm IBCMapper) ReceiveIBCPacket(ctx sdk.Context, packet IBCPacket) sdk.Error { +func (ibcm Mapper) ReceiveIBCPacket(ctx sdk.Context, packet IBCPacket) sdk.Error { return nil } @@ -74,7 +75,8 @@ func unmarshalBinaryPanic(cdc *wire.Codec, bz []byte, ptr interface{}) { } } -func (ibcm IBCMapper) GetIngressSequence(ctx sdk.Context, srcChain string) int64 { +// TODO add description +func (ibcm Mapper) GetIngressSequence(ctx sdk.Context, srcChain string) int64 { store := ctx.KVStore(ibcm.key) key := IngressSequenceKey(srcChain) @@ -90,7 +92,8 @@ func (ibcm IBCMapper) GetIngressSequence(ctx sdk.Context, srcChain string) int64 return res } -func (ibcm IBCMapper) SetIngressSequence(ctx sdk.Context, srcChain string, sequence int64) { +// TODO add description +func (ibcm Mapper) SetIngressSequence(ctx sdk.Context, srcChain string, sequence int64) { store := ctx.KVStore(ibcm.key) key := IngressSequenceKey(srcChain) @@ -99,7 +102,7 @@ func (ibcm IBCMapper) SetIngressSequence(ctx sdk.Context, srcChain string, seque } // Retrieves the index of the currently stored outgoing IBC packets. -func (ibcm IBCMapper) getEgressLength(store sdk.KVStore, destChain string) int64 { +func (ibcm Mapper) getEgressLength(store sdk.KVStore, destChain string) int64 { bz := store.Get(EgressLengthKey(destChain)) if bz == nil { zero := marshalBinaryPanic(ibcm.cdc, int64(0)) diff --git a/x/ibc/rest/root.go b/x/ibc/rest/root.go deleted file mode 100644 index 81e74d031..000000000 --- a/x/ibc/rest/root.go +++ /dev/null @@ -1,14 +0,0 @@ -package rest - -import ( - "github.com/gorilla/mux" - - keys "github.com/tendermint/go-crypto/keys" - - "github.com/cosmos/cosmos-sdk/wire" -) - -// RegisterRoutes - Central function to define routes that get registered by the main application -func RegisterRoutes(r *mux.Router, cdc *wire.Codec, kb keys.Keybase) { - r.HandleFunc("/ibc/{destchain}/{address}/send", TransferRequestHandler(cdc, kb)).Methods("POST") -} diff --git a/x/ibc/rest/transfer.go b/x/ibc/rest/transfer.go index 1317730e7..c0f70b517 100644 --- a/x/ibc/rest/transfer.go +++ b/x/ibc/rest/transfer.go @@ -11,10 +11,14 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" - "github.com/cosmos/cosmos-sdk/x/bank/commands" "github.com/cosmos/cosmos-sdk/x/ibc" ) +// RegisterRoutes - Central function to define routes that get registered by the main application +func RegisterRoutes(r *mux.Router, cdc *wire.Codec, kb keys.Keybase) { + r.HandleFunc("/ibc/{destchain}/{address}/send", TransferRequestHandler(cdc, kb)).Methods("POST") +} + type transferBody struct { // Fees sdk.Coin `json="fees"` Amount sdk.Coins `json:"amount"` @@ -27,7 +31,6 @@ type transferBody struct { // TransferRequestHandler - http request handler to transfer coins to a address // on a different chain via IBC func TransferRequestHandler(cdc *wire.Codec, kb keys.Keybase) func(http.ResponseWriter, *http.Request) { - c := commands.Commander{cdc} ctx := context.NewCoreContextFromViper() return func(w http.ResponseWriter, r *http.Request) { // collect data @@ -70,7 +73,7 @@ func TransferRequestHandler(cdc *wire.Codec, kb keys.Keybase) func(http.Response // sign ctx = ctx.WithSequence(m.Sequence) - txBytes, err := ctx.SignAndBuild(m.LocalAccountName, m.Password, msg, c.Cdc) + txBytes, err := ctx.SignAndBuild(m.LocalAccountName, m.Password, msg, cdc) if err != nil { w.WriteHeader(http.StatusUnauthorized) w.Write([]byte(err.Error())) diff --git a/x/ibc/types.go b/x/ibc/types.go index 2bf2c4267..6102a2a9f 100644 --- a/x/ibc/types.go +++ b/x/ibc/types.go @@ -9,6 +9,7 @@ import ( // ------------------------------ // IBCPacket +// nolint - TODO rename to Packet as IBCPacket stutters (golint) // IBCPacket defines a piece of data that can be send between two separate // blockchains. type IBCPacket struct { @@ -31,6 +32,7 @@ func NewIBCPacket(srcAddr sdk.Address, destAddr sdk.Address, coins sdk.Coins, } } +// validator the ibc packey func (ibcp IBCPacket) ValidateBasic() sdk.Error { if ibcp.SrcChain == ibcp.DestChain { return ErrIdenticalChains(DefaultCodespace).Trace("") @@ -44,19 +46,20 @@ func (ibcp IBCPacket) ValidateBasic() sdk.Error { // ---------------------------------- // IBCTransferMsg +// nolint - TODO rename to TransferMsg as folks will reference with ibc.TransferMsg // IBCTransferMsg defines how another module can send an IBCPacket. type IBCTransferMsg struct { IBCPacket } -func (msg IBCTransferMsg) Type() string { - return "ibc" -} +// nolint +func (msg IBCTransferMsg) Type() string { return "ibc" } +func (msg IBCTransferMsg) Get(key interface{}) interface{} { return nil } -func (msg IBCTransferMsg) Get(key interface{}) interface{} { - return nil -} +// x/bank/tx.go MsgSend.GetSigners() +func (msg IBCTransferMsg) GetSigners() []sdk.Address { return []sdk.Address{msg.SrcAddr} } +// get the sign bytes for ibc transfer message func (msg IBCTransferMsg) GetSignBytes() []byte { cdc := wire.NewCodec() bz, err := cdc.MarshalBinary(msg) @@ -66,18 +69,15 @@ func (msg IBCTransferMsg) GetSignBytes() []byte { return bz } +// validate ibc transfer message func (msg IBCTransferMsg) ValidateBasic() sdk.Error { return msg.IBCPacket.ValidateBasic() } -// x/bank/tx.go SendMsg.GetSigners() -func (msg IBCTransferMsg) GetSigners() []sdk.Address { - return []sdk.Address{msg.SrcAddr} -} - // ---------------------------------- // IBCReceiveMsg +// nolint - TODO rename to ReceiveMsg as folks will reference with ibc.ReceiveMsg // IBCReceiveMsg defines the message that a relayer uses to post an IBCPacket // to the destination chain. type IBCReceiveMsg struct { @@ -86,14 +86,15 @@ type IBCReceiveMsg struct { Sequence int64 } -func (msg IBCReceiveMsg) Type() string { - return "ibc" -} +// nolint +func (msg IBCReceiveMsg) Type() string { return "ibc" } +func (msg IBCReceiveMsg) Get(key interface{}) interface{} { return nil } +func (msg IBCReceiveMsg) ValidateBasic() sdk.Error { return msg.IBCPacket.ValidateBasic() } -func (msg IBCReceiveMsg) Get(key interface{}) interface{} { - return nil -} +// x/bank/tx.go MsgSend.GetSigners() +func (msg IBCReceiveMsg) GetSigners() []sdk.Address { return []sdk.Address{msg.Relayer} } +// get the sign bytes for ibc receive message func (msg IBCReceiveMsg) GetSignBytes() []byte { cdc := wire.NewCodec() bz, err := cdc.MarshalBinary(msg) @@ -102,12 +103,3 @@ func (msg IBCReceiveMsg) GetSignBytes() []byte { } return bz } - -func (msg IBCReceiveMsg) ValidateBasic() sdk.Error { - return msg.IBCPacket.ValidateBasic() -} - -// x/bank/tx.go SendMsg.GetSigners() -func (msg IBCReceiveMsg) GetSigners() []sdk.Address { - return []sdk.Address{msg.Relayer} -} diff --git a/x/ibc/types_test.go b/x/ibc/types_test.go index c16839ddc..199270b29 100644 --- a/x/ibc/types_test.go +++ b/x/ibc/types_test.go @@ -106,7 +106,6 @@ func constructIBCPacket(valid bool) IBCPacket { if valid { return NewIBCPacket(srcAddr, destAddr, coins, srcChain, destChain) - } else { - return NewIBCPacket(srcAddr, destAddr, coins, srcChain, srcChain) } + return NewIBCPacket(srcAddr, destAddr, coins, srcChain, srcChain) } diff --git a/x/simplestake/commands/commands.go b/x/simplestake/commands/commands.go index ba6602028..78144fdac 100644 --- a/x/simplestake/commands/commands.go +++ b/x/simplestake/commands/commands.go @@ -21,89 +21,72 @@ const ( flagValidator = "validator" ) +// simple bond tx func BondTxCmd(cdc *wire.Codec) *cobra.Command { - cmdr := commander{cdc} cmd := &cobra.Command{ Use: "bond", Short: "Bond to a validator", - RunE: cmdr.bondTxCmd, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCoreContextFromViper() + + from, err := ctx.GetFromAddress() + if err != nil { + return err + } + + stakeString := viper.GetString(flagStake) + if len(stakeString) == 0 { + return fmt.Errorf("specify coins to bond with --stake") + } + + valString := viper.GetString(flagValidator) + if len(valString) == 0 { + return fmt.Errorf("specify pubkey to bond to with --validator") + } + + stake, err := sdk.ParseCoin(stakeString) + if err != nil { + return err + } + + // TODO: bech32 ... + rawPubKey, err := hex.DecodeString(valString) + if err != nil { + return err + } + var pubKeyEd crypto.PubKeyEd25519 + copy(pubKeyEd[:], rawPubKey) + + msg := simplestake.NewMsgBond(from, stake, pubKeyEd) + + return sendMsg(cdc, msg) + }, } cmd.Flags().String(flagStake, "", "Amount of coins to stake") cmd.Flags().String(flagValidator, "", "Validator address to stake") return cmd } +// simple unbond tx func UnbondTxCmd(cdc *wire.Codec) *cobra.Command { - cmdr := commander{cdc} cmd := &cobra.Command{ Use: "unbond", Short: "Unbond from a validator", - RunE: cmdr.unbondTxCmd, + RunE: func(cmd *cobra.Command, args []string) error { + from, err := context.NewCoreContextFromViper().GetFromAddress() + if err != nil { + return err + } + msg := simplestake.NewMsgUnbond(from) + return sendMsg(cdc, msg) + }, } return cmd } -type commander struct { - cdc *wire.Codec -} - -func (co commander) bondTxCmd(cmd *cobra.Command, args []string) error { - ctx := context.NewCoreContextFromViper() - - from, err := ctx.GetFromAddress() - if err != nil { - return err - } - - stakeString := viper.GetString(flagStake) - if len(stakeString) == 0 { - return fmt.Errorf("specify coins to bond with --stake") - } - - valString := viper.GetString(flagValidator) - if len(valString) == 0 { - return fmt.Errorf("specify pubkey to bond to with --validator") - } - - stake, err := sdk.ParseCoin(stakeString) - if err != nil { - return err - } - - // TODO: bech32 ... - rawPubKey, err := hex.DecodeString(valString) - if err != nil { - return err - } - var pubKeyEd crypto.PubKeyEd25519 - copy(pubKeyEd[:], rawPubKey) - - msg := simplestake.NewBondMsg(from, stake, pubKeyEd) - - return co.sendMsg(msg) -} - -func (co commander) unbondTxCmd(cmd *cobra.Command, args []string) error { - from, err := context.NewCoreContextFromViper().GetFromAddress() - if err != nil { - return err - } - - msg := simplestake.NewUnbondMsg(from) - - return co.sendMsg(msg) -} - -func (co commander) sendMsg(msg sdk.Msg) error { - ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(co.cdc)) - - // default to next sequence number if none provided - ctx, err := context.EnsureSequence(ctx) - if err != nil { - return err - } - - res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, co.cdc) +func sendMsg(cdc *wire.Codec, msg sdk.Msg) error { + ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) + res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc) if err != nil { return err } diff --git a/x/simplestake/errors.go b/x/simplestake/errors.go index 0fb7eebce..0effba9c0 100644 --- a/x/simplestake/errors.go +++ b/x/simplestake/errors.go @@ -4,6 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +// simple stake errors reserve 300 ~ 399. const ( DefaultCodespace sdk.CodespaceType = 4 @@ -14,18 +15,16 @@ const ( CodeIncorrectStakingToken sdk.CodeType = 303 ) +// nolint func ErrIncorrectStakingToken(codespace sdk.CodespaceType) sdk.Error { return newError(codespace, CodeIncorrectStakingToken, "") } - func ErrEmptyValidator(codespace sdk.CodespaceType) sdk.Error { return newError(codespace, CodeEmptyValidator, "") } - func ErrInvalidUnbond(codespace sdk.CodespaceType) sdk.Error { return newError(codespace, CodeInvalidUnbond, "") } - func ErrEmptyStake(codespace sdk.CodespaceType) sdk.Error { return newError(codespace, CodeEmptyStake, "") } diff --git a/x/simplestake/handler.go b/x/simplestake/handler.go index 894da04b2..a84e8b07b 100644 --- a/x/simplestake/handler.go +++ b/x/simplestake/handler.go @@ -10,17 +10,17 @@ import ( func NewHandler(k Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { switch msg := msg.(type) { - case BondMsg: - return handleBondMsg(ctx, k, msg) - case UnbondMsg: - return handleUnbondMsg(ctx, k, msg) + case MsgBond: + return handleMsgBond(ctx, k, msg) + case MsgUnbond: + return handleMsgUnbond(ctx, k, msg) default: return sdk.ErrUnknownRequest("No match for message type.").Result() } } } -func handleBondMsg(ctx sdk.Context, k Keeper, msg BondMsg) sdk.Result { +func handleMsgBond(ctx sdk.Context, k Keeper, msg MsgBond) sdk.Result { power, err := k.Bond(ctx, msg.Address, msg.PubKey, msg.Stake) if err != nil { return err.Result() @@ -37,7 +37,7 @@ func handleBondMsg(ctx sdk.Context, k Keeper, msg BondMsg) sdk.Result { } } -func handleUnbondMsg(ctx sdk.Context, k Keeper, msg UnbondMsg) sdk.Result { +func handleMsgUnbond(ctx sdk.Context, k Keeper, msg MsgUnbond) sdk.Result { pubKey, _, err := k.Unbond(ctx, msg.Address) if err != nil { return err.Result() diff --git a/x/simplestake/keeper.go b/x/simplestake/keeper.go index 934d0b5a0..7b61c3623 100644 --- a/x/simplestake/keeper.go +++ b/x/simplestake/keeper.go @@ -12,15 +12,16 @@ const stakingToken = "steak" const moduleName = "simplestake" +// simple stake keeper type Keeper struct { - ck bank.CoinKeeper + ck bank.Keeper key sdk.StoreKey cdc *wire.Codec codespace sdk.CodespaceType } -func NewKeeper(key sdk.StoreKey, coinKeeper bank.CoinKeeper, codespace sdk.CodespaceType) Keeper { +func NewKeeper(key sdk.StoreKey, coinKeeper bank.Keeper, codespace sdk.CodespaceType) Keeper { cdc := wire.NewCodec() wire.RegisterCrypto(cdc) return Keeper{ @@ -59,6 +60,7 @@ func (k Keeper) deleteBondInfo(ctx sdk.Context, addr sdk.Address) { store.Delete(addr) } +// register a bond with the keeper func (k Keeper) Bond(ctx sdk.Context, addr sdk.Address, pubKey crypto.PubKey, stake sdk.Coin) (int64, sdk.Error) { if stake.Denom != stakingToken { return 0, ErrIncorrectStakingToken(k.codespace) @@ -83,6 +85,7 @@ func (k Keeper) Bond(ctx sdk.Context, addr sdk.Address, pubKey crypto.PubKey, st return bi.Power, nil } +// register an unbond with the keeper func (k Keeper) Unbond(ctx sdk.Context, addr sdk.Address) (crypto.PubKey, int64, sdk.Error) { bi := k.getBondInfo(ctx, addr) if bi.isEmpty() { diff --git a/x/simplestake/keeper_test.go b/x/simplestake/keeper_test.go index 833227968..75e9fcded 100644 --- a/x/simplestake/keeper_test.go +++ b/x/simplestake/keeper_test.go @@ -33,7 +33,7 @@ func TestKeeperGetSet(t *testing.T) { ms, _, capKey := setupMultiStore() ctx := sdk.NewContext(ms, abci.Header{}, false, nil) - stakeKeeper := NewKeeper(capKey, bank.NewCoinKeeper(nil), DefaultCodespace) + stakeKeeper := NewKeeper(capKey, bank.NewKeeper(nil), DefaultCodespace) addr := sdk.Address([]byte("some-address")) bi := stakeKeeper.getBondInfo(ctx, addr) @@ -62,7 +62,7 @@ func TestBonding(t *testing.T) { ctx := sdk.NewContext(ms, abci.Header{}, false, nil) accountMapper := auth.NewAccountMapper(cdc, authKey, &auth.BaseAccount{}) - coinKeeper := bank.NewCoinKeeper(accountMapper) + coinKeeper := bank.NewKeeper(accountMapper) stakeKeeper := NewKeeper(capKey, coinKeeper, DefaultCodespace) addr := sdk.Address([]byte("some-address")) privKey := crypto.GenPrivKeyEd25519() diff --git a/x/simplestake/msgs.go b/x/simplestake/msgs.go index 963bfae7b..512d571c5 100644 --- a/x/simplestake/msgs.go +++ b/x/simplestake/msgs.go @@ -8,44 +8,43 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// ------------------------- -// BondMsg +//_________________________________________________________---- -type BondMsg struct { +// simple bond message +type MsgBond struct { Address sdk.Address `json:"address"` Stake sdk.Coin `json:"coins"` PubKey crypto.PubKey `json:"pub_key"` } -func NewBondMsg(addr sdk.Address, stake sdk.Coin, pubKey crypto.PubKey) BondMsg { - return BondMsg{ +func NewMsgBond(addr sdk.Address, stake sdk.Coin, pubKey crypto.PubKey) MsgBond { + return MsgBond{ Address: addr, Stake: stake, PubKey: pubKey, } } -func (msg BondMsg) Type() string { - return moduleName -} +//nolint +func (msg MsgBond) Type() string { return moduleName } //TODO update "stake/declarecandidacy" +func (msg MsgBond) Get(key interface{}) (value interface{}) { return nil } +func (msg MsgBond) GetSigners() []sdk.Address { return []sdk.Address{msg.Address} } -func (msg BondMsg) ValidateBasic() sdk.Error { +// basic validation of the bond message +func (msg MsgBond) ValidateBasic() sdk.Error { if msg.Stake.IsZero() { return ErrEmptyStake(DefaultCodespace) } if msg.PubKey == nil { - return sdk.ErrInvalidPubKey("BondMsg.PubKey must not be empty") + return sdk.ErrInvalidPubKey("MsgBond.PubKey must not be empty") } return nil } -func (msg BondMsg) Get(key interface{}) interface{} { - return nil -} - -func (msg BondMsg) GetSignBytes() []byte { +// get bond message sign bytes +func (msg MsgBond) GetSignBytes() []byte { bz, err := json.Marshal(msg) if err != nil { panic(err) @@ -53,43 +52,30 @@ func (msg BondMsg) GetSignBytes() []byte { return bz } -func (msg BondMsg) GetSigners() []sdk.Address { - return []sdk.Address{msg.Address} -} +//_______________________________________________________________ -// ------------------------- -// UnbondMsg - -type UnbondMsg struct { +// simple unbond message +type MsgUnbond struct { Address sdk.Address `json:"address"` } -func NewUnbondMsg(addr sdk.Address) UnbondMsg { - return UnbondMsg{ +func NewMsgUnbond(addr sdk.Address) MsgUnbond { + return MsgUnbond{ Address: addr, } } -func (msg UnbondMsg) Type() string { - return moduleName -} +//nolint +func (msg MsgUnbond) Type() string { return moduleName } //TODO update "stake/declarecandidacy" +func (msg MsgUnbond) Get(key interface{}) (value interface{}) { return nil } +func (msg MsgUnbond) GetSigners() []sdk.Address { return []sdk.Address{msg.Address} } +func (msg MsgUnbond) ValidateBasic() sdk.Error { return nil } -func (msg UnbondMsg) ValidateBasic() sdk.Error { - return nil -} - -func (msg UnbondMsg) Get(key interface{}) interface{} { - return nil -} - -func (msg UnbondMsg) GetSignBytes() []byte { +// get unbond message sign bytes +func (msg MsgUnbond) GetSignBytes() []byte { bz, err := json.Marshal(msg) if err != nil { panic(err) } return bz } - -func (msg UnbondMsg) GetSigners() []sdk.Address { - return []sdk.Address{msg.Address} -} diff --git a/x/simplestake/msgs_test.go b/x/simplestake/msgs_test.go index 49a8feec5..c71ebe7fc 100644 --- a/x/simplestake/msgs_test.go +++ b/x/simplestake/msgs_test.go @@ -14,14 +14,14 @@ func TestBondMsgValidation(t *testing.T) { privKey := crypto.GenPrivKeyEd25519() cases := []struct { valid bool - bondMsg BondMsg + msgBond MsgBond }{ - {true, NewBondMsg(sdk.Address{}, sdk.Coin{"mycoin", 5}, privKey.PubKey())}, - {false, NewBondMsg(sdk.Address{}, sdk.Coin{"mycoin", 0}, privKey.PubKey())}, + {true, NewMsgBond(sdk.Address{}, sdk.Coin{"mycoin", 5}, privKey.PubKey())}, + {false, NewMsgBond(sdk.Address{}, sdk.Coin{"mycoin", 0}, privKey.PubKey())}, } for i, tc := range cases { - err := tc.bondMsg.ValidateBasic() + err := tc.msgBond.ValidateBasic() if tc.valid { assert.Nil(t, err, "%d: %+v", i, err) } else { diff --git a/x/stake/commands/tx.go b/x/stake/commands/tx.go index 4a1983743..e04a81885 100644 --- a/x/stake/commands/tx.go +++ b/x/stake/commands/tx.go @@ -48,13 +48,7 @@ func GetCmdDeclareCandidacy(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - // default to next sequence number if none provided - ctx, err = context.EnsureSequence(ctx) - if err != nil { - return err - } - - res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc) + res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc) if err != nil { return err } @@ -93,13 +87,7 @@ func GetCmdEditCandidacy(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - // default to next sequence number if none provided - ctx, err = context.EnsureSequence(ctx) - if err != nil { - return err - } - - res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc) + res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc) if err != nil { return err } @@ -136,13 +124,7 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - // default to next sequence number if none provided - ctx, err = context.EnsureSequence(ctx) - if err != nil { - return err - } - - res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc) + res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc) if err != nil { return err } @@ -190,13 +172,7 @@ func GetCmdUnbond(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - // default to next sequence number if none provided - ctx, err = context.EnsureSequence(ctx) - if err != nil { - return err - } - - res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc) + res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc) if err != nil { return err } diff --git a/x/stake/keeper.go b/x/stake/keeper.go index 751b84017..49806f9b9 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -13,7 +13,7 @@ import ( type Keeper struct { storeKey sdk.StoreKey cdc *wire.Codec - coinKeeper bank.CoinKeeper + coinKeeper bank.Keeper // caches gs Pool @@ -23,7 +23,7 @@ type Keeper struct { codespace sdk.CodespaceType } -func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.CoinKeeper, codespace sdk.CodespaceType) Keeper { +func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper { keeper := Keeper{ storeKey: key, cdc: cdc, diff --git a/x/stake/msg.go b/x/stake/msg.go index b5ba09b5a..10cea3fa8 100644 --- a/x/stake/msg.go +++ b/x/stake/msg.go @@ -2,7 +2,6 @@ package stake import ( "encoding/json" - "fmt" sdk "github.com/cosmos/cosmos-sdk/types" crypto "github.com/tendermint/go-crypto" @@ -44,9 +43,6 @@ func NewMsgDeclareCandidacy(candidateAddr sdk.Address, pubkey crypto.PubKey, func (msg MsgDeclareCandidacy) Type() string { return MsgType } //TODO update "stake/declarecandidacy" func (msg MsgDeclareCandidacy) Get(key interface{}) (value interface{}) { return nil } func (msg MsgDeclareCandidacy) GetSigners() []sdk.Address { return []sdk.Address{msg.CandidateAddr} } -func (msg MsgDeclareCandidacy) String() string { - return fmt.Sprintf("CandidateAddr{Address: %v}", msg.CandidateAddr) // XXX fix -} // get the bytes for the message signer to sign on func (msg MsgDeclareCandidacy) GetSignBytes() []byte { @@ -67,7 +63,6 @@ func (msg MsgDeclareCandidacy) ValidateBasic() sdk.Error { } if msg.Bond.Amount <= 0 { return ErrBadBondingAmount(DefaultCodespace) - // return sdk.ErrInvalidCoins(sdk.Coins{msg.Bond}.String()) } empty := Description{} if msg.Description == empty { @@ -95,9 +90,6 @@ func NewMsgEditCandidacy(candidateAddr sdk.Address, description Description) Msg func (msg MsgEditCandidacy) Type() string { return MsgType } //TODO update "stake/msgeditcandidacy" func (msg MsgEditCandidacy) Get(key interface{}) (value interface{}) { return nil } func (msg MsgEditCandidacy) GetSigners() []sdk.Address { return []sdk.Address{msg.CandidateAddr} } -func (msg MsgEditCandidacy) String() string { - return fmt.Sprintf("CandidateAddr{Address: %v}", msg.CandidateAddr) // XXX fix -} // get the bytes for the message signer to sign on func (msg MsgEditCandidacy) GetSignBytes() []byte { @@ -141,9 +133,6 @@ func NewMsgDelegate(delegatorAddr, candidateAddr sdk.Address, bond sdk.Coin) Msg func (msg MsgDelegate) Type() string { return MsgType } //TODO update "stake/msgeditcandidacy" func (msg MsgDelegate) Get(key interface{}) (value interface{}) { return nil } func (msg MsgDelegate) GetSigners() []sdk.Address { return []sdk.Address{msg.DelegatorAddr} } -func (msg MsgDelegate) String() string { - return fmt.Sprintf("Addr{Address: %v}", msg.DelegatorAddr) // XXX fix -} // get the bytes for the message signer to sign on func (msg MsgDelegate) GetSignBytes() []byte { @@ -167,7 +156,6 @@ func (msg MsgDelegate) ValidateBasic() sdk.Error { } if msg.Bond.Amount <= 0 { return ErrBadBondingAmount(DefaultCodespace) - // return sdk.ErrInvalidCoins(sdk.Coins{msg.Bond}.String()) } return nil } @@ -193,9 +181,6 @@ func NewMsgUnbond(delegatorAddr, candidateAddr sdk.Address, shares string) MsgUn func (msg MsgUnbond) Type() string { return MsgType } //TODO update "stake/msgeditcandidacy" func (msg MsgUnbond) Get(key interface{}) (value interface{}) { return nil } func (msg MsgUnbond) GetSigners() []sdk.Address { return []sdk.Address{msg.DelegatorAddr} } -func (msg MsgUnbond) String() string { - return fmt.Sprintf("Addr{Address: %v}", msg.DelegatorAddr) // XXX fix -} // get the bytes for the message signer to sign on func (msg MsgUnbond) GetSignBytes() []byte { diff --git a/x/stake/test_common.go b/x/stake/test_common.go index 1de86c912..9d7b13e7c 100644 --- a/x/stake/test_common.go +++ b/x/stake/test_common.go @@ -96,8 +96,8 @@ func makeTestCodec() *wire.Codec { // Register Msgs cdc.RegisterInterface((*sdk.Msg)(nil), nil) - cdc.RegisterConcrete(bank.SendMsg{}, "test/stake/Send", nil) - cdc.RegisterConcrete(bank.IssueMsg{}, "test/stake/Issue", nil) + cdc.RegisterConcrete(bank.MsgSend{}, "test/stake/Send", nil) + cdc.RegisterConcrete(bank.MsgIssue{}, "test/stake/Issue", nil) cdc.RegisterConcrete(MsgDeclareCandidacy{}, "test/stake/DeclareCandidacy", nil) cdc.RegisterConcrete(MsgEditCandidacy{}, "test/stake/EditCandidacy", nil) cdc.RegisterConcrete(MsgUnbond{}, "test/stake/Unbond", nil) @@ -139,7 +139,7 @@ func createTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context keyMain, // target store &auth.BaseAccount{}, // prototype ).Seal() - ck := bank.NewCoinKeeper(accountMapper) + ck := bank.NewKeeper(accountMapper) keeper := NewKeeper(cdc, keyStake, ck, DefaultCodespace) keeper.setPool(ctx, initialPool()) keeper.setParams(ctx, defaultParams()) From b1c83f2edb8a0f7acd9d064c816d18bc200934fc Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 6 Apr 2018 13:11:26 +0200 Subject: [PATCH 30/71] WIP: Track validator height (closes #582) --- x/stake/keeper.go | 6 +++--- x/stake/keeper_keys.go | 10 +++++++--- x/stake/types.go | 28 ++++++++++++++++------------ 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/x/stake/keeper.go b/x/stake/keeper.go index 751b84017..2dcfd3caf 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -101,9 +101,9 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { // update the list ordered by voting power if oldFound { - store.Delete(GetValidatorKey(address, oldCandidate.Assets, k.cdc)) + store.Delete(GetValidatorKey(address, oldCandidate.Assets, oldCandidate.ValidatorHeight, k.cdc)) } - store.Set(GetValidatorKey(address, validator.Power, k.cdc), bz) + store.Set(GetValidatorKey(address, validator.Power, validator.Height, k.cdc), bz) // add to the validators to update list if is already a validator // or is a new validator @@ -136,7 +136,7 @@ func (k Keeper) removeCandidate(ctx sdk.Context, address sdk.Address) { // delete the old candidate record store := ctx.KVStore(k.storeKey) store.Delete(GetCandidateKey(address)) - store.Delete(GetValidatorKey(address, candidate.Assets, k.cdc)) + store.Delete(GetValidatorKey(address, candidate.Assets, candidate.ValidatorHeight, k.cdc)) // delete from recent and power weighted validator groups if the validator // exists and add validator with zero power to the validator updates diff --git a/x/stake/keeper_keys.go b/x/stake/keeper_keys.go index 45e0570bc..ae8f9d733 100644 --- a/x/stake/keeper_keys.go +++ b/x/stake/keeper_keys.go @@ -1,6 +1,8 @@ package stake import ( + "encoding/binary" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" ) @@ -30,9 +32,11 @@ func GetCandidateKey(addr sdk.Address) []byte { } // get the key for the validator used in the power-store -func GetValidatorKey(addr sdk.Address, power sdk.Rat, cdc *wire.Codec) []byte { - powerBytes := []byte(power.ToLeftPadded(maxDigitsForAccount)) - return append(ValidatorsKey, append(powerBytes, addr.Bytes()...)...) +func GetValidatorKey(addr sdk.Address, power sdk.Rat, height uint64, cdc *wire.Codec) []byte { + powerBytes := []byte(power.ToLeftPadded(maxDigitsForAccount)) // power big-endian (more powerful validators first) + heightBytes := make([]byte, 8) + binary.LittleEndian.PutUint64(heightBytes, height) // height little-endian (older validators first) + return append(ValidatorsKey, append(powerBytes, append(heightBytes, addr.Bytes()...)...)...) } // get the key for the accumulated update validators diff --git a/x/stake/types.go b/x/stake/types.go index 9f7d97ae5..7757566bf 100644 --- a/x/stake/types.go +++ b/x/stake/types.go @@ -59,12 +59,13 @@ const ( // exchange rate. Voting power can be calculated as total bonds multiplied by // exchange rate. type Candidate struct { - Status CandidateStatus `json:"status"` // Bonded status - Address sdk.Address `json:"owner"` // Sender of BondTx - UnbondTx returns here - PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate - Assets sdk.Rat `json:"assets"` // total shares of a global hold pools - Liabilities sdk.Rat `json:"liabilities"` // total shares issued to a candidate's delegators - Description Description `json:"description"` // Description terms for the candidate + Status CandidateStatus `json:"status"` // Bonded status + Address sdk.Address `json:"owner"` // Sender of BondTx - UnbondTx returns here + PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate + Assets sdk.Rat `json:"assets"` // total shares of a global hold pools + Liabilities sdk.Rat `json:"liabilities"` // total shares issued to a candidate's delegators + Description Description `json:"description"` // Description terms for the candidate + ValidatorHeight uint64 `json:"validator_height"` // If considered a validator, height when first considered a validator, else 0 } // Candidates - list of Candidates @@ -73,12 +74,13 @@ type Candidates []Candidate // NewCandidate - initialize a new candidate func NewCandidate(address sdk.Address, pubKey crypto.PubKey, description Description) Candidate { return Candidate{ - Status: Unbonded, - Address: address, - PubKey: pubKey, - Assets: sdk.ZeroRat, - Liabilities: sdk.ZeroRat, - Description: description, + Status: Unbonded, + Address: address, + PubKey: pubKey, + Assets: sdk.ZeroRat, + Liabilities: sdk.ZeroRat, + Description: description, + ValidatorHeight: uint64(0), } } @@ -114,6 +116,7 @@ func (c Candidate) validator() Validator { Address: c.Address, PubKey: c.PubKey, Power: c.Assets, + Height: c.ValidatorHeight, } } @@ -127,6 +130,7 @@ type Validator struct { Address sdk.Address `json:"address"` PubKey crypto.PubKey `json:"pub_key"` Power sdk.Rat `json:"voting_power"` + Height uint64 `json:"height"` // If considered a validator, height when first considered a validator, else 0 } // abci validator from stake validator type From 905a9eefb9b6113a5675bc7e095ef51d9bb1b797 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 9 Apr 2018 12:17:45 +0200 Subject: [PATCH 31/71] Cleanup implementation --- x/stake/keeper.go | 7 ++++++- x/stake/keeper_keys.go | 4 ++-- x/stake/types.go | 6 +++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/x/stake/keeper.go b/x/stake/keeper.go index 2dcfd3caf..a51877b3c 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -80,6 +80,9 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { // retreive the old candidate record oldCandidate, oldFound := k.GetCandidate(ctx, address) + // update the validator block height (will only get written if stake has changed) + candidate.ValidatorHeight = ctx.BlockHeight() + // marshal the candidate record and add to the state bz, err := k.cdc.MarshalBinary(candidate) if err != nil { @@ -87,7 +90,7 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { } store.Set(GetCandidateKey(candidate.Address), bz) - // mashal the new validator record + // marshal the new validator record validator := candidate.validator() bz, err = k.cdc.MarshalBinary(validator) if err != nil { @@ -121,7 +124,9 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { panic(err) } store.Set(GetAccUpdateValidatorKey(validator.Address), bz) + } + return } diff --git a/x/stake/keeper_keys.go b/x/stake/keeper_keys.go index ae8f9d733..a8adc2a12 100644 --- a/x/stake/keeper_keys.go +++ b/x/stake/keeper_keys.go @@ -32,10 +32,10 @@ func GetCandidateKey(addr sdk.Address) []byte { } // get the key for the validator used in the power-store -func GetValidatorKey(addr sdk.Address, power sdk.Rat, height uint64, cdc *wire.Codec) []byte { +func GetValidatorKey(addr sdk.Address, power sdk.Rat, height int64, cdc *wire.Codec) []byte { powerBytes := []byte(power.ToLeftPadded(maxDigitsForAccount)) // power big-endian (more powerful validators first) heightBytes := make([]byte, 8) - binary.LittleEndian.PutUint64(heightBytes, height) // height little-endian (older validators first) + binary.LittleEndian.PutUint64(heightBytes, uint64(height)) // height little-endian (older validators first) return append(ValidatorsKey, append(powerBytes, append(heightBytes, addr.Bytes()...)...)...) } diff --git a/x/stake/types.go b/x/stake/types.go index 7757566bf..052a50fa2 100644 --- a/x/stake/types.go +++ b/x/stake/types.go @@ -65,7 +65,7 @@ type Candidate struct { Assets sdk.Rat `json:"assets"` // total shares of a global hold pools Liabilities sdk.Rat `json:"liabilities"` // total shares issued to a candidate's delegators Description Description `json:"description"` // Description terms for the candidate - ValidatorHeight uint64 `json:"validator_height"` // If considered a validator, height when first considered a validator, else 0 + ValidatorHeight int64 `json:"validator_height"` // Earliest height at current voting power } // Candidates - list of Candidates @@ -80,7 +80,7 @@ func NewCandidate(address sdk.Address, pubKey crypto.PubKey, description Descrip Assets: sdk.ZeroRat, Liabilities: sdk.ZeroRat, Description: description, - ValidatorHeight: uint64(0), + ValidatorHeight: int64(0), } } @@ -130,7 +130,7 @@ type Validator struct { Address sdk.Address `json:"address"` PubKey crypto.PubKey `json:"pub_key"` Power sdk.Rat `json:"voting_power"` - Height uint64 `json:"height"` // If considered a validator, height when first considered a validator, else 0 + Height int64 `json:"height"` // Earliest height at current voting power } // abci validator from stake validator type From 36f579766049e8cf2dd0c0b4a85944e12d53b0d6 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 9 Apr 2018 13:12:08 +0200 Subject: [PATCH 32/71] Ordering fixes, testcases --- x/stake/keeper.go | 32 ++++++++++++++++++++------------ x/stake/keeper_keys.go | 4 ++-- x/stake/keeper_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 14 deletions(-) diff --git a/x/stake/keeper.go b/x/stake/keeper.go index a51877b3c..f6aa01c63 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -80,9 +80,6 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { // retreive the old candidate record oldCandidate, oldFound := k.GetCandidate(ctx, address) - // update the validator block height (will only get written if stake has changed) - candidate.ValidatorHeight = ctx.BlockHeight() - // marshal the candidate record and add to the state bz, err := k.cdc.MarshalBinary(candidate) if err != nil { @@ -90,6 +87,26 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { } store.Set(GetCandidateKey(candidate.Address), bz) + // if the voting power is the same no need to update any of the other indexes + if oldFound && oldCandidate.Assets.Equal(candidate.Assets) { + return + } + + // update the list ordered by voting power + if oldFound { + store.Delete(GetValidatorKey(address, oldCandidate.Assets, oldCandidate.ValidatorHeight, k.cdc)) + } + + // update the validator block height + candidate.ValidatorHeight = ctx.BlockHeight() + + // update the candidate record + bz, err = k.cdc.MarshalBinary(candidate) + if err != nil { + panic(err) + } + store.Set(GetCandidateKey(candidate.Address), bz) + // marshal the new validator record validator := candidate.validator() bz, err = k.cdc.MarshalBinary(validator) @@ -97,15 +114,6 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { panic(err) } - // if the voting power is the same no need to update any of the other indexes - if oldFound && oldCandidate.Assets.Equal(candidate.Assets) { - return - } - - // update the list ordered by voting power - if oldFound { - store.Delete(GetValidatorKey(address, oldCandidate.Assets, oldCandidate.ValidatorHeight, k.cdc)) - } store.Set(GetValidatorKey(address, validator.Power, validator.Height, k.cdc), bz) // add to the validators to update list if is already a validator diff --git a/x/stake/keeper_keys.go b/x/stake/keeper_keys.go index a8adc2a12..e9db23c2c 100644 --- a/x/stake/keeper_keys.go +++ b/x/stake/keeper_keys.go @@ -34,8 +34,8 @@ func GetCandidateKey(addr sdk.Address) []byte { // get the key for the validator used in the power-store func GetValidatorKey(addr sdk.Address, power sdk.Rat, height int64, cdc *wire.Codec) []byte { powerBytes := []byte(power.ToLeftPadded(maxDigitsForAccount)) // power big-endian (more powerful validators first) - heightBytes := make([]byte, 8) - binary.LittleEndian.PutUint64(heightBytes, uint64(height)) // height little-endian (older validators first) + heightBytes := make([]byte, binary.MaxVarintLen64) + binary.BigEndian.PutUint64(heightBytes, ^uint64(height)) // invert height (older validators first) return append(ValidatorsKey, append(powerBytes, append(heightBytes, addr.Bytes()...)...)...) } diff --git a/x/stake/keeper_test.go b/x/stake/keeper_test.go index e01df1aae..baaa2ec8c 100644 --- a/x/stake/keeper_test.go +++ b/x/stake/keeper_test.go @@ -243,6 +243,47 @@ func TestGetValidators(t *testing.T) { assert.Equal(t, sdk.NewRat(300), validators[0].Power, "%v", validators) assert.Equal(t, candidates[3].Address, validators[0].Address, "%v", validators) + // test equal voting power, different age + candidates[3].Assets = sdk.NewRat(200) + ctx = ctx.WithBlockHeight(10) + keeper.setCandidate(ctx, candidates[3]) + validators = keeper.GetValidators(ctx) + require.Equal(t, len(validators), n) + assert.Equal(t, sdk.NewRat(200), validators[0].Power, "%v", validators) + assert.Equal(t, sdk.NewRat(200), validators[1].Power, "%v", validators) + assert.Equal(t, candidates[4].Address, validators[0].Address, "%v", validators) + assert.Equal(t, candidates[3].Address, validators[1].Address, "%v", validators) + assert.Equal(t, int64(0), validators[0].Height, "%v", validators) + assert.Equal(t, int64(10), validators[1].Height, "%v", validators) + + // no change in voting power - no change in sort + ctx = ctx.WithBlockHeight(20) + keeper.setCandidate(ctx, candidates[4]) + validators = keeper.GetValidators(ctx) + require.Equal(t, len(validators), n) + assert.Equal(t, candidates[4].Address, validators[0].Address, "%v", validators) + assert.Equal(t, candidates[3].Address, validators[1].Address, "%v", validators) + + // change in voting power of both candidates, ages swapped + candidates[3].Assets = sdk.NewRat(300) + candidates[4].Assets = sdk.NewRat(300) + keeper.setCandidate(ctx, candidates[3]) + validators = keeper.GetValidators(ctx) + require.Equal(t, len(validators), n) + ctx = ctx.WithBlockHeight(30) + keeper.setCandidate(ctx, candidates[4]) + validators = keeper.GetValidators(ctx) + require.Equal(t, len(validators), n, "%v", validators) + assert.Equal(t, candidates[3].Address, validators[0].Address, "%v", validators) + assert.Equal(t, candidates[4].Address, validators[1].Address, "%v", validators) + + // reset assets / heights + candidates[3].Assets = sdk.NewRat(300) + candidates[4].Assets = sdk.NewRat(200) + ctx = ctx.WithBlockHeight(0) + keeper.setCandidate(ctx, candidates[3]) + keeper.setCandidate(ctx, candidates[4]) + // test a swap in voting power candidates[0].Assets = sdk.NewRat(600) keeper.setCandidate(ctx, candidates[0]) From 91e850b568b244272b5503ecb9d74f02b0e81021 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 6 Apr 2018 13:11:26 +0200 Subject: [PATCH 33/71] WIP: Track validator height (closes #582) --- x/stake/keeper.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/x/stake/keeper.go b/x/stake/keeper.go index f6aa01c63..7f35da1a9 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -96,24 +96,6 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { if oldFound { store.Delete(GetValidatorKey(address, oldCandidate.Assets, oldCandidate.ValidatorHeight, k.cdc)) } - - // update the validator block height - candidate.ValidatorHeight = ctx.BlockHeight() - - // update the candidate record - bz, err = k.cdc.MarshalBinary(candidate) - if err != nil { - panic(err) - } - store.Set(GetCandidateKey(candidate.Address), bz) - - // marshal the new validator record - validator := candidate.validator() - bz, err = k.cdc.MarshalBinary(validator) - if err != nil { - panic(err) - } - store.Set(GetValidatorKey(address, validator.Power, validator.Height, k.cdc), bz) // add to the validators to update list if is already a validator From 7fa634e772952cde9b0de68c8eff5fdc2228752a Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 9 Apr 2018 12:17:45 +0200 Subject: [PATCH 34/71] Cleanup implementation --- x/stake/keeper.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/x/stake/keeper.go b/x/stake/keeper.go index 7f35da1a9..a51877b3c 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -80,6 +80,9 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { // retreive the old candidate record oldCandidate, oldFound := k.GetCandidate(ctx, address) + // update the validator block height (will only get written if stake has changed) + candidate.ValidatorHeight = ctx.BlockHeight() + // marshal the candidate record and add to the state bz, err := k.cdc.MarshalBinary(candidate) if err != nil { @@ -87,6 +90,13 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { } store.Set(GetCandidateKey(candidate.Address), bz) + // marshal the new validator record + validator := candidate.validator() + bz, err = k.cdc.MarshalBinary(validator) + if err != nil { + panic(err) + } + // if the voting power is the same no need to update any of the other indexes if oldFound && oldCandidate.Assets.Equal(candidate.Assets) { return From 90d88114d9063bcec2dc2b0b459fe9b1f896116c Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 9 Apr 2018 13:12:08 +0200 Subject: [PATCH 35/71] Ordering fixes, testcases --- x/stake/keeper.go | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/x/stake/keeper.go b/x/stake/keeper.go index a51877b3c..f6aa01c63 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -80,9 +80,6 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { // retreive the old candidate record oldCandidate, oldFound := k.GetCandidate(ctx, address) - // update the validator block height (will only get written if stake has changed) - candidate.ValidatorHeight = ctx.BlockHeight() - // marshal the candidate record and add to the state bz, err := k.cdc.MarshalBinary(candidate) if err != nil { @@ -90,6 +87,26 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { } store.Set(GetCandidateKey(candidate.Address), bz) + // if the voting power is the same no need to update any of the other indexes + if oldFound && oldCandidate.Assets.Equal(candidate.Assets) { + return + } + + // update the list ordered by voting power + if oldFound { + store.Delete(GetValidatorKey(address, oldCandidate.Assets, oldCandidate.ValidatorHeight, k.cdc)) + } + + // update the validator block height + candidate.ValidatorHeight = ctx.BlockHeight() + + // update the candidate record + bz, err = k.cdc.MarshalBinary(candidate) + if err != nil { + panic(err) + } + store.Set(GetCandidateKey(candidate.Address), bz) + // marshal the new validator record validator := candidate.validator() bz, err = k.cdc.MarshalBinary(validator) @@ -97,15 +114,6 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { panic(err) } - // if the voting power is the same no need to update any of the other indexes - if oldFound && oldCandidate.Assets.Equal(candidate.Assets) { - return - } - - // update the list ordered by voting power - if oldFound { - store.Delete(GetValidatorKey(address, oldCandidate.Assets, oldCandidate.ValidatorHeight, k.cdc)) - } store.Set(GetValidatorKey(address, validator.Power, validator.Height, k.cdc), bz) // add to the validators to update list if is already a validator From 166711742e0694d7e8fa24e2fed89a9f8769b6a7 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 12 Apr 2018 11:52:54 +0200 Subject: [PATCH 36/71] Rebase, test fix --- x/stake/keeper.go | 8 +++++--- x/stake/keeper_test.go | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/x/stake/keeper.go b/x/stake/keeper.go index f6aa01c63..8cce331cf 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -94,12 +94,14 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { // update the list ordered by voting power if oldFound { + // retain the old validator height, even though stake has changed + candidate.ValidatorHeight = oldCandidate.ValidatorHeight store.Delete(GetValidatorKey(address, oldCandidate.Assets, oldCandidate.ValidatorHeight, k.cdc)) + } else { + // update the validator block height + candidate.ValidatorHeight = ctx.BlockHeight() } - // update the validator block height - candidate.ValidatorHeight = ctx.BlockHeight() - // update the candidate record bz, err = k.cdc.MarshalBinary(candidate) if err != nil { diff --git a/x/stake/keeper_test.go b/x/stake/keeper_test.go index baaa2ec8c..85b2d72ba 100644 --- a/x/stake/keeper_test.go +++ b/x/stake/keeper_test.go @@ -254,7 +254,7 @@ func TestGetValidators(t *testing.T) { assert.Equal(t, candidates[4].Address, validators[0].Address, "%v", validators) assert.Equal(t, candidates[3].Address, validators[1].Address, "%v", validators) assert.Equal(t, int64(0), validators[0].Height, "%v", validators) - assert.Equal(t, int64(10), validators[1].Height, "%v", validators) + assert.Equal(t, int64(0), validators[1].Height, "%v", validators) // no change in voting power - no change in sort ctx = ctx.WithBlockHeight(20) @@ -274,8 +274,8 @@ func TestGetValidators(t *testing.T) { keeper.setCandidate(ctx, candidates[4]) validators = keeper.GetValidators(ctx) require.Equal(t, len(validators), n, "%v", validators) - assert.Equal(t, candidates[3].Address, validators[0].Address, "%v", validators) - assert.Equal(t, candidates[4].Address, validators[1].Address, "%v", validators) + assert.Equal(t, candidates[4].Address, validators[0].Address, "%v", validators) + assert.Equal(t, candidates[3].Address, validators[1].Address, "%v", validators) // reset assets / heights candidates[3].Assets = sdk.NewRat(300) From 6424bb85ff1addd3ba13851840f2966e0f4d5914 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 12 Apr 2018 12:37:38 +0200 Subject: [PATCH 37/71] Update ordering logic --- x/stake/keeper.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/x/stake/keeper.go b/x/stake/keeper.go index 8cce331cf..88d82650a 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -94,11 +94,16 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { // update the list ordered by voting power if oldFound { - // retain the old validator height, even though stake has changed - candidate.ValidatorHeight = oldCandidate.ValidatorHeight + if k.isNewValidator(ctx, store, candidate.Address) { + // already in the validator set - retain the old validator height + candidate.ValidatorHeight = oldCandidate.ValidatorHeight + } else { + // wasn't in the validator set, update the validator block height + candidate.ValidatorHeight = ctx.BlockHeight() + } store.Delete(GetValidatorKey(address, oldCandidate.Assets, oldCandidate.ValidatorHeight, k.cdc)) } else { - // update the validator block height + // wasn't a candidate, update the validator block height candidate.ValidatorHeight = ctx.BlockHeight() } From 4e72250dd1d936279403603ac6f8cd979d171b6d Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 13 Apr 2018 13:28:41 +0200 Subject: [PATCH 38/71] Add testcases (ref #582 discussion) --- x/stake/keeper_test.go | 62 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/x/stake/keeper_test.go b/x/stake/keeper_test.go index 85b2d72ba..a137047e5 100644 --- a/x/stake/keeper_test.go +++ b/x/stake/keeper_test.go @@ -264,7 +264,7 @@ func TestGetValidators(t *testing.T) { assert.Equal(t, candidates[4].Address, validators[0].Address, "%v", validators) assert.Equal(t, candidates[3].Address, validators[1].Address, "%v", validators) - // change in voting power of both candidates, ages swapped + // change in voting power of both candidates, both still in v-set, no age change candidates[3].Assets = sdk.NewRat(300) candidates[4].Assets = sdk.NewRat(300) keeper.setCandidate(ctx, candidates[3]) @@ -277,10 +277,68 @@ func TestGetValidators(t *testing.T) { assert.Equal(t, candidates[4].Address, validators[0].Address, "%v", validators) assert.Equal(t, candidates[3].Address, validators[1].Address, "%v", validators) + // now 2 max validators + params := keeper.GetParams(ctx) + params.MaxValidators = 2 + keeper.setParams(ctx, params) + candidates[0].Assets = sdk.NewRat(500) + keeper.setCandidate(ctx, candidates[0]) + validators = keeper.GetValidators(ctx) + require.Equal(t, uint16(len(validators)), params.MaxValidators) + require.Equal(t, candidates[0].Address, validators[0].Address, "%v", validators) + // candidate 4 was set before candidate 3 + require.Equal(t, candidates[4].Address, validators[1].Address, "%v", validators) + + // simulate scenario from https://github.com/cosmos/cosmos-sdk/issues/582#issuecomment-380757108 + ctx = ctx.WithBlockHeight(40) + // candidate 4 kicked out temporarily + candidates[4].Assets = sdk.NewRat(200) + keeper.setCandidate(ctx, candidates[4]) + validators = keeper.GetValidators(ctx) + require.Equal(t, uint16(len(validators)), params.MaxValidators) + require.Equal(t, candidates[0].Address, validators[0].Address, "%v", validators) + require.Equal(t, candidates[3].Address, validators[1].Address, "%v", validators) + // candidate 4 does not get spot back + candidates[4].Assets = sdk.NewRat(300) + keeper.setCandidate(ctx, candidates[4]) + validators = keeper.GetValidators(ctx) + require.Equal(t, uint16(len(validators)), params.MaxValidators) + require.Equal(t, candidates[0].Address, validators[0].Address, "%v", validators) + require.Equal(t, candidates[3].Address, validators[1].Address, "%v", validators) + candidate, exists := keeper.GetCandidate(ctx, candidates[4].Address) + require.Equal(t, exists, true) + require.Equal(t, candidate.ValidatorHeight, int64(40)) + + // first transaction wins + candidates[1].Assets = sdk.NewRat(1000) + candidates[2].Assets = sdk.NewRat(1000) + keeper.setCandidate(ctx, candidates[1]) + keeper.setCandidate(ctx, candidates[2]) + validators = keeper.GetValidators(ctx) + require.Equal(t, uint16(len(validators)), params.MaxValidators) + require.Equal(t, candidates[1].Address, validators[0].Address, "%v", validators) + require.Equal(t, candidates[2].Address, validators[1].Address, "%v", validators) + candidates[1].Assets = sdk.NewRat(1100) + candidates[2].Assets = sdk.NewRat(1100) + keeper.setCandidate(ctx, candidates[2]) + keeper.setCandidate(ctx, candidates[1]) + validators = keeper.GetValidators(ctx) + require.Equal(t, uint16(len(validators)), params.MaxValidators) + require.Equal(t, candidates[2].Address, validators[0].Address, "%v", validators) + require.Equal(t, candidates[1].Address, validators[1].Address, "%v", validators) + // reset assets / heights + params.MaxValidators = 100 + keeper.setParams(ctx, params) + candidates[0].Assets = sdk.NewRat(0) + candidates[1].Assets = sdk.NewRat(100) + candidates[2].Assets = sdk.NewRat(1) candidates[3].Assets = sdk.NewRat(300) candidates[4].Assets = sdk.NewRat(200) ctx = ctx.WithBlockHeight(0) + keeper.setCandidate(ctx, candidates[0]) + keeper.setCandidate(ctx, candidates[1]) + keeper.setCandidate(ctx, candidates[2]) keeper.setCandidate(ctx, candidates[3]) keeper.setCandidate(ctx, candidates[4]) @@ -295,7 +353,7 @@ func TestGetValidators(t *testing.T) { assert.Equal(t, candidates[3].Address, validators[1].Address, "%v", validators) // test the max validators term - params := keeper.GetParams(ctx) + params = keeper.GetParams(ctx) n = 2 params.MaxValidators = uint16(n) keeper.setParams(ctx, params) From 7f38f3470935a5e1aacd1335e5602e992b032621 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 16 Apr 2018 13:22:05 +0200 Subject: [PATCH 39/71] Stake module block-local tx index counter --- x/stake/keeper.go | 68 +++++++++++++++++++++++++++++++++++------- x/stake/keeper_keys.go | 8 +++-- x/stake/keeper_test.go | 32 +++++++++++--------- x/stake/tick.go | 3 ++ x/stake/types.go | 34 +++++++++++---------- 5 files changed, 104 insertions(+), 41 deletions(-) diff --git a/x/stake/keeper.go b/x/stake/keeper.go index 88d82650a..935a0ab46 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -33,6 +33,42 @@ func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.CoinKeeper, codespace return keeper } +// InitGenesis - store genesis parameters +func (k Keeper) InitGenesis(ctx sdk.Context, data json.RawMessage) error { + var state GenesisState + if err := json.Unmarshal(data, &state); err != nil { + return err + } + k.setPool(ctx, state.Pool) + k.setParams(ctx, state.Params) + return nil +} + +// get the current counter +func (k Keeper) getCounter(ctx sdk.Context) int64 { + store := ctx.KVStore(k.storeKey) + b := store.Get(CounterKey) + if b == nil { + return 0 + } + var counter int64 + err := k.cdc.UnmarshalBinary(b, &counter) + if err != nil { + panic(err) + } + return counter +} + +// set the current counter +func (k Keeper) setCounter(ctx sdk.Context, counter int64) { + store := ctx.KVStore(k.storeKey) + bz, err := k.cdc.MarshalBinary(counter) + if err != nil { + panic(err) + } + store.Set(CounterKey, bz) +} + //_________________________________________________________________________ // get a single candidate @@ -80,6 +116,12 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { // retreive the old candidate record oldCandidate, oldFound := k.GetCandidate(ctx, address) + // if found, copy the old block height and counter + if oldFound { + candidate.ValidatorHeight = oldCandidate.ValidatorHeight + candidate.ValidatorCounter = oldCandidate.ValidatorCounter + } + // marshal the candidate record and add to the state bz, err := k.cdc.MarshalBinary(candidate) if err != nil { @@ -92,19 +134,25 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { return } + updateHeight := false + // update the list ordered by voting power if oldFound { - if k.isNewValidator(ctx, store, candidate.Address) { - // already in the validator set - retain the old validator height - candidate.ValidatorHeight = oldCandidate.ValidatorHeight - } else { - // wasn't in the validator set, update the validator block height - candidate.ValidatorHeight = ctx.BlockHeight() + if !k.isNewValidator(ctx, store, candidate.Address) { + updateHeight = true } - store.Delete(GetValidatorKey(address, oldCandidate.Assets, oldCandidate.ValidatorHeight, k.cdc)) + // else already in the validator set - retain the old validator height and counter + store.Delete(GetValidatorKey(address, oldCandidate.Assets, oldCandidate.ValidatorHeight, oldCandidate.ValidatorCounter, k.cdc)) } else { - // wasn't a candidate, update the validator block height + updateHeight = true + } + + if updateHeight { + // wasn't a candidate or wasn't in the validator set, update the validator block height and counter candidate.ValidatorHeight = ctx.BlockHeight() + counter := k.getCounter(ctx) + candidate.ValidatorCounter = counter + k.setCounter(ctx, counter+1) } // update the candidate record @@ -121,7 +169,7 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { panic(err) } - store.Set(GetValidatorKey(address, validator.Power, validator.Height, k.cdc), bz) + store.Set(GetValidatorKey(address, validator.Power, validator.Height, validator.Counter, k.cdc), bz) // add to the validators to update list if is already a validator // or is a new validator @@ -156,7 +204,7 @@ func (k Keeper) removeCandidate(ctx sdk.Context, address sdk.Address) { // delete the old candidate record store := ctx.KVStore(k.storeKey) store.Delete(GetCandidateKey(address)) - store.Delete(GetValidatorKey(address, candidate.Assets, candidate.ValidatorHeight, k.cdc)) + store.Delete(GetValidatorKey(address, candidate.Assets, candidate.ValidatorHeight, candidate.ValidatorCounter, k.cdc)) // delete from recent and power weighted validator groups if the validator // exists and add validator with zero power to the validator updates diff --git a/x/stake/keeper_keys.go b/x/stake/keeper_keys.go index e9db23c2c..c34d40480 100644 --- a/x/stake/keeper_keys.go +++ b/x/stake/keeper_keys.go @@ -22,6 +22,8 @@ var ( ToKickOutValidatorsKey = []byte{0x06} // prefix for each key to the last updated validator group DelegatorBondKeyPrefix = []byte{0x07} // prefix for each key to a delegator's bond + + CounterKey = []byte{0x08} // key for block-local tx index ) const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch @@ -32,11 +34,13 @@ func GetCandidateKey(addr sdk.Address) []byte { } // get the key for the validator used in the power-store -func GetValidatorKey(addr sdk.Address, power sdk.Rat, height int64, cdc *wire.Codec) []byte { +func GetValidatorKey(addr sdk.Address, power sdk.Rat, height int64, counter int64, cdc *wire.Codec) []byte { powerBytes := []byte(power.ToLeftPadded(maxDigitsForAccount)) // power big-endian (more powerful validators first) heightBytes := make([]byte, binary.MaxVarintLen64) binary.BigEndian.PutUint64(heightBytes, ^uint64(height)) // invert height (older validators first) - return append(ValidatorsKey, append(powerBytes, append(heightBytes, addr.Bytes()...)...)...) + counterBytes := make([]byte, binary.MaxVarintLen64) + binary.BigEndian.PutUint64(counterBytes, ^uint64(counter)) // invert counter (first txns have priority) + return append(ValidatorsKey, append(powerBytes, append(heightBytes, append(counterBytes, addr.Bytes()...)...)...)...) } // get the key for the accumulated update validators diff --git a/x/stake/keeper_test.go b/x/stake/keeper_test.go index a137047e5..442bc2c5e 100644 --- a/x/stake/keeper_test.go +++ b/x/stake/keeper_test.go @@ -251,8 +251,8 @@ func TestGetValidators(t *testing.T) { require.Equal(t, len(validators), n) assert.Equal(t, sdk.NewRat(200), validators[0].Power, "%v", validators) assert.Equal(t, sdk.NewRat(200), validators[1].Power, "%v", validators) - assert.Equal(t, candidates[4].Address, validators[0].Address, "%v", validators) - assert.Equal(t, candidates[3].Address, validators[1].Address, "%v", validators) + assert.Equal(t, candidates[3].Address, validators[0].Address, "%v", validators) + assert.Equal(t, candidates[4].Address, validators[1].Address, "%v", validators) assert.Equal(t, int64(0), validators[0].Height, "%v", validators) assert.Equal(t, int64(0), validators[1].Height, "%v", validators) @@ -261,8 +261,8 @@ func TestGetValidators(t *testing.T) { keeper.setCandidate(ctx, candidates[4]) validators = keeper.GetValidators(ctx) require.Equal(t, len(validators), n) - assert.Equal(t, candidates[4].Address, validators[0].Address, "%v", validators) - assert.Equal(t, candidates[3].Address, validators[1].Address, "%v", validators) + assert.Equal(t, candidates[3].Address, validators[0].Address, "%v", validators) + assert.Equal(t, candidates[4].Address, validators[1].Address, "%v", validators) // change in voting power of both candidates, both still in v-set, no age change candidates[3].Assets = sdk.NewRat(300) @@ -274,8 +274,8 @@ func TestGetValidators(t *testing.T) { keeper.setCandidate(ctx, candidates[4]) validators = keeper.GetValidators(ctx) require.Equal(t, len(validators), n, "%v", validators) - assert.Equal(t, candidates[4].Address, validators[0].Address, "%v", validators) - assert.Equal(t, candidates[3].Address, validators[1].Address, "%v", validators) + assert.Equal(t, candidates[3].Address, validators[0].Address, "%v", validators) + assert.Equal(t, candidates[4].Address, validators[1].Address, "%v", validators) // now 2 max validators params := keeper.GetParams(ctx) @@ -286,8 +286,8 @@ func TestGetValidators(t *testing.T) { validators = keeper.GetValidators(ctx) require.Equal(t, uint16(len(validators)), params.MaxValidators) require.Equal(t, candidates[0].Address, validators[0].Address, "%v", validators) - // candidate 4 was set before candidate 3 - require.Equal(t, candidates[4].Address, validators[1].Address, "%v", validators) + // candidate 3 was set before candidate 4 + require.Equal(t, candidates[3].Address, validators[1].Address, "%v", validators) // simulate scenario from https://github.com/cosmos/cosmos-sdk/issues/582#issuecomment-380757108 ctx = ctx.WithBlockHeight(40) @@ -309,23 +309,25 @@ func TestGetValidators(t *testing.T) { require.Equal(t, exists, true) require.Equal(t, candidate.ValidatorHeight, int64(40)) - // first transaction wins + // first transaction wins, https://github.com/cosmos/cosmos-sdk/issues/582#issuecomment-381250392 + candidates[0].Assets = sdk.NewRat(2000) + keeper.setCandidate(ctx, candidates[0]) candidates[1].Assets = sdk.NewRat(1000) candidates[2].Assets = sdk.NewRat(1000) keeper.setCandidate(ctx, candidates[1]) keeper.setCandidate(ctx, candidates[2]) validators = keeper.GetValidators(ctx) require.Equal(t, uint16(len(validators)), params.MaxValidators) - require.Equal(t, candidates[1].Address, validators[0].Address, "%v", validators) - require.Equal(t, candidates[2].Address, validators[1].Address, "%v", validators) + require.Equal(t, candidates[0].Address, validators[0].Address, "%v", validators) + require.Equal(t, candidates[1].Address, validators[1].Address, "%v", validators) candidates[1].Assets = sdk.NewRat(1100) candidates[2].Assets = sdk.NewRat(1100) keeper.setCandidate(ctx, candidates[2]) keeper.setCandidate(ctx, candidates[1]) validators = keeper.GetValidators(ctx) require.Equal(t, uint16(len(validators)), params.MaxValidators) - require.Equal(t, candidates[2].Address, validators[0].Address, "%v", validators) - require.Equal(t, candidates[1].Address, validators[1].Address, "%v", validators) + require.Equal(t, candidates[0].Address, validators[0].Address, "%v", validators) + require.Equal(t, candidates[2].Address, validators[1].Address, "%v", validators) // reset assets / heights params.MaxValidators = 100 @@ -627,7 +629,9 @@ func TestIsRecentValidator(t *testing.T) { validators = keeper.GetValidators(ctx) require.Equal(t, 2, len(validators)) assert.Equal(t, candidatesIn[0].validator(), validators[0]) - assert.Equal(t, candidatesIn[1].validator(), validators[1]) + c1ValWithCounter := candidatesIn[1].validator() + c1ValWithCounter.Counter = int64(1) + assert.Equal(t, c1ValWithCounter, validators[1]) // test a basic retrieve of something that should be a recent validator assert.True(t, keeper.IsRecentValidator(ctx, candidatesIn[0].Address)) diff --git a/x/stake/tick.go b/x/stake/tick.go index 129be58f0..0b3dd1c83 100644 --- a/x/stake/tick.go +++ b/x/stake/tick.go @@ -26,6 +26,9 @@ func (k Keeper) Tick(ctx sdk.Context) (change []abci.Validator) { // save the params k.setPool(ctx, p) + // reset the counter + k.setCounter(ctx, 0) + change = k.getAccUpdateValidators(ctx) return diff --git a/x/stake/types.go b/x/stake/types.go index 052a50fa2..64f1e3dc2 100644 --- a/x/stake/types.go +++ b/x/stake/types.go @@ -59,13 +59,14 @@ const ( // exchange rate. Voting power can be calculated as total bonds multiplied by // exchange rate. type Candidate struct { - Status CandidateStatus `json:"status"` // Bonded status - Address sdk.Address `json:"owner"` // Sender of BondTx - UnbondTx returns here - PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate - Assets sdk.Rat `json:"assets"` // total shares of a global hold pools - Liabilities sdk.Rat `json:"liabilities"` // total shares issued to a candidate's delegators - Description Description `json:"description"` // Description terms for the candidate - ValidatorHeight int64 `json:"validator_height"` // Earliest height at current voting power + Status CandidateStatus `json:"status"` // Bonded status + Address sdk.Address `json:"owner"` // Sender of BondTx - UnbondTx returns here + PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate + Assets sdk.Rat `json:"assets"` // total shares of a global hold pools + Liabilities sdk.Rat `json:"liabilities"` // total shares issued to a candidate's delegators + Description Description `json:"description"` // Description terms for the candidate + ValidatorHeight int64 `json:"validator_height"` // Earliest height at current voting power + ValidatorCounter int64 `json:"validator_counter"` // Block-local tx index of validator change } // Candidates - list of Candidates @@ -74,13 +75,14 @@ type Candidates []Candidate // NewCandidate - initialize a new candidate func NewCandidate(address sdk.Address, pubKey crypto.PubKey, description Description) Candidate { return Candidate{ - Status: Unbonded, - Address: address, - PubKey: pubKey, - Assets: sdk.ZeroRat, - Liabilities: sdk.ZeroRat, - Description: description, - ValidatorHeight: int64(0), + Status: Unbonded, + Address: address, + PubKey: pubKey, + Assets: sdk.ZeroRat, + Liabilities: sdk.ZeroRat, + Description: description, + ValidatorHeight: int64(0), + ValidatorCounter: int64(0), } } @@ -117,6 +119,7 @@ func (c Candidate) validator() Validator { PubKey: c.PubKey, Power: c.Assets, Height: c.ValidatorHeight, + Counter: c.ValidatorCounter, } } @@ -130,7 +133,8 @@ type Validator struct { Address sdk.Address `json:"address"` PubKey crypto.PubKey `json:"pub_key"` Power sdk.Rat `json:"voting_power"` - Height int64 `json:"height"` // Earliest height at current voting power + Height int64 `json:"height"` // Earliest height at current voting power + Counter int64 `json:"counter"` // Block-local tx index for resolving equal voting power & height } // abci validator from stake validator type From d2fa76aa3765e7fadcb379634ef249afe2aaa092 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 19 Apr 2018 13:52:57 +0200 Subject: [PATCH 40/71] Rebase onto develop --- x/stake/keeper.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/x/stake/keeper.go b/x/stake/keeper.go index 935a0ab46..ffb8ad80e 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -33,17 +33,6 @@ func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.CoinKeeper, codespace return keeper } -// InitGenesis - store genesis parameters -func (k Keeper) InitGenesis(ctx sdk.Context, data json.RawMessage) error { - var state GenesisState - if err := json.Unmarshal(data, &state); err != nil { - return err - } - k.setPool(ctx, state.Pool) - k.setParams(ctx, state.Params) - return nil -} - // get the current counter func (k Keeper) getCounter(ctx sdk.Context) int64 { store := ctx.KVStore(k.storeKey) From 12336f249c3b2c3948f759b31269308f0a2774e6 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 19 Apr 2018 14:09:12 +0200 Subject: [PATCH 41/71] Address PR comments Clarify field names, explain testing scenarios in more depth --- x/stake/keeper.go | 22 +++++++++++----------- x/stake/keeper_keys.go | 6 +++--- x/stake/keeper_test.go | 25 +++++++++++++++++++++---- x/stake/types.go | 40 ++++++++++++++++++++-------------------- 4 files changed, 55 insertions(+), 38 deletions(-) diff --git a/x/stake/keeper.go b/x/stake/keeper.go index ffb8ad80e..a3502960e 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -33,14 +33,14 @@ func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.CoinKeeper, codespace return keeper } -// get the current counter -func (k Keeper) getCounter(ctx sdk.Context) int64 { +// get the current in-block validator operation counter +func (k Keeper) getCounter(ctx sdk.Context) int16 { store := ctx.KVStore(k.storeKey) b := store.Get(CounterKey) if b == nil { return 0 } - var counter int64 + var counter int16 err := k.cdc.UnmarshalBinary(b, &counter) if err != nil { panic(err) @@ -48,8 +48,8 @@ func (k Keeper) getCounter(ctx sdk.Context) int64 { return counter } -// set the current counter -func (k Keeper) setCounter(ctx sdk.Context, counter int64) { +// set the current in-block validator operation counter +func (k Keeper) setCounter(ctx sdk.Context, counter int16) { store := ctx.KVStore(k.storeKey) bz, err := k.cdc.MarshalBinary(counter) if err != nil { @@ -107,8 +107,8 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { // if found, copy the old block height and counter if oldFound { - candidate.ValidatorHeight = oldCandidate.ValidatorHeight - candidate.ValidatorCounter = oldCandidate.ValidatorCounter + candidate.ValidatorBondHeight = oldCandidate.ValidatorBondHeight + candidate.ValidatorBondCounter = oldCandidate.ValidatorBondCounter } // marshal the candidate record and add to the state @@ -131,16 +131,16 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { updateHeight = true } // else already in the validator set - retain the old validator height and counter - store.Delete(GetValidatorKey(address, oldCandidate.Assets, oldCandidate.ValidatorHeight, oldCandidate.ValidatorCounter, k.cdc)) + store.Delete(GetValidatorKey(address, oldCandidate.Assets, oldCandidate.ValidatorBondHeight, oldCandidate.ValidatorBondCounter, k.cdc)) } else { updateHeight = true } if updateHeight { // wasn't a candidate or wasn't in the validator set, update the validator block height and counter - candidate.ValidatorHeight = ctx.BlockHeight() + candidate.ValidatorBondHeight = ctx.BlockHeight() counter := k.getCounter(ctx) - candidate.ValidatorCounter = counter + candidate.ValidatorBondCounter = counter k.setCounter(ctx, counter+1) } @@ -193,7 +193,7 @@ func (k Keeper) removeCandidate(ctx sdk.Context, address sdk.Address) { // delete the old candidate record store := ctx.KVStore(k.storeKey) store.Delete(GetCandidateKey(address)) - store.Delete(GetValidatorKey(address, candidate.Assets, candidate.ValidatorHeight, candidate.ValidatorCounter, k.cdc)) + store.Delete(GetValidatorKey(address, candidate.Assets, candidate.ValidatorBondHeight, candidate.ValidatorBondCounter, k.cdc)) // delete from recent and power weighted validator groups if the validator // exists and add validator with zero power to the validator updates diff --git a/x/stake/keeper_keys.go b/x/stake/keeper_keys.go index c34d40480..eb641b883 100644 --- a/x/stake/keeper_keys.go +++ b/x/stake/keeper_keys.go @@ -34,12 +34,12 @@ func GetCandidateKey(addr sdk.Address) []byte { } // get the key for the validator used in the power-store -func GetValidatorKey(addr sdk.Address, power sdk.Rat, height int64, counter int64, cdc *wire.Codec) []byte { +func GetValidatorKey(addr sdk.Address, power sdk.Rat, height int64, counter int16, cdc *wire.Codec) []byte { powerBytes := []byte(power.ToLeftPadded(maxDigitsForAccount)) // power big-endian (more powerful validators first) heightBytes := make([]byte, binary.MaxVarintLen64) binary.BigEndian.PutUint64(heightBytes, ^uint64(height)) // invert height (older validators first) - counterBytes := make([]byte, binary.MaxVarintLen64) - binary.BigEndian.PutUint64(counterBytes, ^uint64(counter)) // invert counter (first txns have priority) + counterBytes := make([]byte, 2) + binary.BigEndian.PutUint16(counterBytes, ^uint16(counter)) // invert counter (first txns have priority) return append(ValidatorsKey, append(powerBytes, append(heightBytes, append(counterBytes, addr.Bytes()...)...)...)...) } diff --git a/x/stake/keeper_test.go b/x/stake/keeper_test.go index 442bc2c5e..c42f7182b 100644 --- a/x/stake/keeper_test.go +++ b/x/stake/keeper_test.go @@ -289,7 +289,19 @@ func TestGetValidators(t *testing.T) { // candidate 3 was set before candidate 4 require.Equal(t, candidates[3].Address, validators[1].Address, "%v", validators) - // simulate scenario from https://github.com/cosmos/cosmos-sdk/issues/582#issuecomment-380757108 + /* + A candidate which leaves the validator set due to a decrease in voting power, + then increases to the original voting power, does not get its spot back in the + case of a tie. + + ref https://github.com/cosmos/cosmos-sdk/issues/582#issuecomment-380757108 + */ + candidates[4].Assets = sdk.NewRat(301) + keeper.setCandidate(ctx, candidates[4]) + validators = keeper.GetValidators(ctx) + require.Equal(t, uint16(len(validators)), params.MaxValidators) + require.Equal(t, candidates[0].Address, validators[0].Address, "%v", validators) + require.Equal(t, candidates[4].Address, validators[1].Address, "%v", validators) ctx = ctx.WithBlockHeight(40) // candidate 4 kicked out temporarily candidates[4].Assets = sdk.NewRat(200) @@ -307,9 +319,14 @@ func TestGetValidators(t *testing.T) { require.Equal(t, candidates[3].Address, validators[1].Address, "%v", validators) candidate, exists := keeper.GetCandidate(ctx, candidates[4].Address) require.Equal(t, exists, true) - require.Equal(t, candidate.ValidatorHeight, int64(40)) + require.Equal(t, candidate.ValidatorBondHeight, int64(40)) - // first transaction wins, https://github.com/cosmos/cosmos-sdk/issues/582#issuecomment-381250392 + /* + If two candidates both increase to the same voting power in the same block, + the one with the first transaction should take precedence (become a validator). + + ref https://github.com/cosmos/cosmos-sdk/issues/582#issuecomment-381250392 + */ candidates[0].Assets = sdk.NewRat(2000) keeper.setCandidate(ctx, candidates[0]) candidates[1].Assets = sdk.NewRat(1000) @@ -630,7 +647,7 @@ func TestIsRecentValidator(t *testing.T) { require.Equal(t, 2, len(validators)) assert.Equal(t, candidatesIn[0].validator(), validators[0]) c1ValWithCounter := candidatesIn[1].validator() - c1ValWithCounter.Counter = int64(1) + c1ValWithCounter.Counter = int16(1) assert.Equal(t, c1ValWithCounter, validators[1]) // test a basic retrieve of something that should be a recent validator diff --git a/x/stake/types.go b/x/stake/types.go index 64f1e3dc2..be48afe3e 100644 --- a/x/stake/types.go +++ b/x/stake/types.go @@ -59,14 +59,14 @@ const ( // exchange rate. Voting power can be calculated as total bonds multiplied by // exchange rate. type Candidate struct { - Status CandidateStatus `json:"status"` // Bonded status - Address sdk.Address `json:"owner"` // Sender of BondTx - UnbondTx returns here - PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate - Assets sdk.Rat `json:"assets"` // total shares of a global hold pools - Liabilities sdk.Rat `json:"liabilities"` // total shares issued to a candidate's delegators - Description Description `json:"description"` // Description terms for the candidate - ValidatorHeight int64 `json:"validator_height"` // Earliest height at current voting power - ValidatorCounter int64 `json:"validator_counter"` // Block-local tx index of validator change + Status CandidateStatus `json:"status"` // Bonded status + Address sdk.Address `json:"owner"` // Sender of BondTx - UnbondTx returns here + PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate + Assets sdk.Rat `json:"assets"` // total shares of a global hold pools + Liabilities sdk.Rat `json:"liabilities"` // total shares issued to a candidate's delegators + Description Description `json:"description"` // Description terms for the candidate + ValidatorBondHeight int64 `json:"validator_bond_height"` // Earliest height as a bonded validator + ValidatorBondCounter int16 `json:"validator_bond_counter"` // Block-local tx index of validator change } // Candidates - list of Candidates @@ -75,14 +75,14 @@ type Candidates []Candidate // NewCandidate - initialize a new candidate func NewCandidate(address sdk.Address, pubKey crypto.PubKey, description Description) Candidate { return Candidate{ - Status: Unbonded, - Address: address, - PubKey: pubKey, - Assets: sdk.ZeroRat, - Liabilities: sdk.ZeroRat, - Description: description, - ValidatorHeight: int64(0), - ValidatorCounter: int64(0), + Status: Unbonded, + Address: address, + PubKey: pubKey, + Assets: sdk.ZeroRat, + Liabilities: sdk.ZeroRat, + Description: description, + ValidatorBondHeight: int64(0), + ValidatorBondCounter: int16(0), } } @@ -118,8 +118,8 @@ func (c Candidate) validator() Validator { Address: c.Address, PubKey: c.PubKey, Power: c.Assets, - Height: c.ValidatorHeight, - Counter: c.ValidatorCounter, + Height: c.ValidatorBondHeight, + Counter: c.ValidatorBondCounter, } } @@ -133,8 +133,8 @@ type Validator struct { Address sdk.Address `json:"address"` PubKey crypto.PubKey `json:"pub_key"` Power sdk.Rat `json:"voting_power"` - Height int64 `json:"height"` // Earliest height at current voting power - Counter int64 `json:"counter"` // Block-local tx index for resolving equal voting power & height + Height int64 `json:"height"` // Earliest height as a validator + Counter int16 `json:"counter"` // Block-local tx index for resolving equal voting power & height } // abci validator from stake validator type From 46626745807906f6dc0fc2bb6b3d3a9c3e8a47aa Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 19 Apr 2018 14:30:14 +0200 Subject: [PATCH 42/71] Add Golint to CircleCI --- .circleci/config.yml | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 47cb5661d..1dc5c1b53 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -27,6 +27,11 @@ jobs: command: | export PATH="$GOBIN:$PATH" make get_vendor_deps + - run: + name: linter + command: | + export PATH="$GOBIN:$PATH" + go get -u github.com/tendermint/lint/golint - run: name: binaries command: | @@ -46,6 +51,24 @@ jobs: paths: - /go/src/github.com/cosmos/cosmos-sdk + lint: + <<: *defaults + parallelism: 4 + steps: + - attach_workspace: + at: /tmp/workspace + - restore_cache: + key: v1-pkg-cache + - restore_cache: + key: v1-tree-{{ .Environment.CIRCLE_SHA1 }} + - run: + name: Lint source + command: | + export PATH="$GOBIN:$PATH" + for pkg in $(go list github.com/cosmos/cosmos-sdk/... | grep -v /vendor/); do + test -z "$(golint $pkg | tee /dev/stderr)" + done + test_cover: <<: *defaults parallelism: 4 @@ -96,10 +119,12 @@ workflows: test-suite: jobs: - setup_dependencies + - lint: + requires: + - setup_dependencies - test_cover: requires: - setup_dependencies - upload_coverage: requires: - test_cover - From 266ea5ce82a25963ac3bdee2e1e5abde22ef38e6 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sun, 4 Mar 2018 00:37:01 -0500 Subject: [PATCH 43/71] docs cleanup --- docs/{ => old}/basecoin/basics.rst | 0 docs/{ => old}/basecoin/extensions.rst | 0 docs/{sdk => old}/glossary.rst | 0 docs/{ => old}/ibc.rst | 0 docs/{x => old}/replay-protection.rst | 0 docs/{ => old}/staking/intro.rst | 0 docs/{ => old}/staking/key-management.rst | 0 docs/{ => old}/staking/local-testnet.rst | 0 docs/{ => old}/staking/public-testnet.rst | 0 docs/{ => sdk}/apps.md | 2 +- docs/sdk/install.rst | 17 ++++++----------- 11 files changed, 7 insertions(+), 12 deletions(-) rename docs/{ => old}/basecoin/basics.rst (100%) rename docs/{ => old}/basecoin/extensions.rst (100%) rename docs/{sdk => old}/glossary.rst (100%) rename docs/{ => old}/ibc.rst (100%) rename docs/{x => old}/replay-protection.rst (100%) rename docs/{ => old}/staking/intro.rst (100%) rename docs/{ => old}/staking/key-management.rst (100%) rename docs/{ => old}/staking/local-testnet.rst (100%) rename docs/{ => old}/staking/public-testnet.rst (100%) rename docs/{ => sdk}/apps.md (97%) diff --git a/docs/basecoin/basics.rst b/docs/old/basecoin/basics.rst similarity index 100% rename from docs/basecoin/basics.rst rename to docs/old/basecoin/basics.rst diff --git a/docs/basecoin/extensions.rst b/docs/old/basecoin/extensions.rst similarity index 100% rename from docs/basecoin/extensions.rst rename to docs/old/basecoin/extensions.rst diff --git a/docs/sdk/glossary.rst b/docs/old/glossary.rst similarity index 100% rename from docs/sdk/glossary.rst rename to docs/old/glossary.rst diff --git a/docs/ibc.rst b/docs/old/ibc.rst similarity index 100% rename from docs/ibc.rst rename to docs/old/ibc.rst diff --git a/docs/x/replay-protection.rst b/docs/old/replay-protection.rst similarity index 100% rename from docs/x/replay-protection.rst rename to docs/old/replay-protection.rst diff --git a/docs/staking/intro.rst b/docs/old/staking/intro.rst similarity index 100% rename from docs/staking/intro.rst rename to docs/old/staking/intro.rst diff --git a/docs/staking/key-management.rst b/docs/old/staking/key-management.rst similarity index 100% rename from docs/staking/key-management.rst rename to docs/old/staking/key-management.rst diff --git a/docs/staking/local-testnet.rst b/docs/old/staking/local-testnet.rst similarity index 100% rename from docs/staking/local-testnet.rst rename to docs/old/staking/local-testnet.rst diff --git a/docs/staking/public-testnet.rst b/docs/old/staking/public-testnet.rst similarity index 100% rename from docs/staking/public-testnet.rst rename to docs/old/staking/public-testnet.rst diff --git a/docs/apps.md b/docs/sdk/apps.md similarity index 97% rename from docs/apps.md rename to docs/sdk/apps.md index 29fb905cb..01210cb66 100644 --- a/docs/apps.md +++ b/docs/sdk/apps.md @@ -15,7 +15,7 @@ while defining as little about that state machine as possible (staying true to t BaseApp requires stores to be mounted via capabilities keys - handlers can only access stores they're given the key for. The BaseApp ensures all stores are properly loaded, cached, and committed. One mounted store is considered the "main" - it holds the latest block header, from which we can find and load the -most recent state. +most recent state ([TODO](https://github.com/cosmos/cosmos-sdk/issues/522)). BaseApp distinguishes between two handler types - the `AnteHandler` and the `MsgHandler`. The former is a global validity check (checking nonces, sigs and sufficient balances to pay fees, diff --git a/docs/sdk/install.rst b/docs/sdk/install.rst index c5a82475a..b4c0ad5da 100644 --- a/docs/sdk/install.rst +++ b/docs/sdk/install.rst @@ -6,7 +6,8 @@ version of the code, please head to our `downloads `__ page to get a pre-compiled binary for your platform. -Usually, Cosmos SDK can be installed like a normal Go program: +Usually, Cosmos SDK can be installed to +`$GOPATH/src/github.com/cosmos/cosmos-sdk` like a normal Go program: :: @@ -23,13 +24,7 @@ repo, the correct way to install is: git pull origin master make all -This will create the ``basecoin`` binary in ``$GOPATH/bin``. -``make all`` implies ``make get_vendor_deps`` and uses ``dep`` to -install the correct version of all dependencies. It also tests the code, -including some cli tests to make sure your binary behaves properly. - -If you need another branch, make sure to run ``git checkout `` -before ``make all``. And if you switch branches a lot, especially -touching other tendermint repos, you may need to ``make fresh`` -sometimes so dep doesn't get confused with all the branches and -versions lying around. +This will create the ``basecoind`` and ``basecli`` binaries locally in +``./build/bin``. ``make all`` implies ``make get_vendor_deps`` and uses +``glide`` to install the correct version of all dependencies. It also tests the +code, including some cli tests to make sure your binary behaves properly. From f386946d4cae7da38bd06dc13618c42842f6769f Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Fri, 30 Mar 2018 11:30:25 -0700 Subject: [PATCH 44/71] docs update part 1 --- docs/old/staking/intro.rst | 171 ++++++++++++++++++++++++++++--------- 1 file changed, 132 insertions(+), 39 deletions(-) diff --git a/docs/old/staking/intro.rst b/docs/old/staking/intro.rst index ca1d002f5..a8f4ea078 100644 --- a/docs/old/staking/intro.rst +++ b/docs/old/staking/intro.rst @@ -1,77 +1,166 @@ -Using Gaia -========== +Using The Staking Module +======================== -This project is a demonstration of the Cosmos Hub with staking functionality; it is -designed to get validator acquianted with staking concepts and procedure. +This project is a demonstration of the Cosmos Hub staking functionality; it is +designed to get validator acquianted with staking concepts and procedures. 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. +This example covers initial setup of a two-node testnet between a server in the cloud and a local machine. Begin this tutorial from a cloud machine that you've ``ssh``'d into. + Install ------- -The ``gaia`` tooling is an extension of the Cosmos-SDK; to install: +The ``basecoind`` and ``basecli`` binaries: :: - go get github.com/cosmos/gaia - cd $GOPATH/src/github.com/cosmos/gaia + go get github.com/cosmos/cosmos-sdk + cd $GOPATH/src/github.com/cosmos/cosmos-sdk make get_vendor_deps make install -It has three primary commands: +Let's jump right into it. First, we initialize some default files: :: - 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 + basecoind init -and a handful of flags that are highlighted only as necessary. +which will output: -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 the `cosmos UI `__. + I[03-30|11:20:13.365] Found private validator module=main path=/root/.basecoind/config/priv_validator.json + I[03-30|11:20:13.365] Found genesis file module=main path=/root/.basecoind/config/genesis.json + Secret phrase to access coins: + citizen hungry tennis noise park hire glory exercise link glow dolphin labor design grit apple abandon -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. -that you've setup or joined a testnet. +This tell us we have a ``priv_validator.json`` and ``genesis.json`` in the ``~/.basecoind/config`` directory. A ``config.toml`` was also created in the same directory. It is a good idea to get familiar with those files. Write down the seed. -Generating Keys ---------------- +The next thing we'll need to is add the key from ``priv_validator.json`` to the ``basecli`` key manager. For this we need a seed and a password: -Review the `key management tutorial <../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. +:: + + basecli keys add alice --recover + +which will give you three prompts: + +:: + + Enter a passphrase for your key: + Repeat the passphrase: + Enter your recovery seed phrase: + +create a password and copy in your seed phrase. The name and address of the key will be output: + +:: + + alice 67997DD03D527EB439B7193F2B813B05B219CC02 + +You can see all available keys with: + +:: + + basecli keys list + +See the `key management tutorial <../key-management.html>`__ for more information on managing keys. 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. +Next, we start the daemon (do this in another window): -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. +:: + + basecoind start + +and you'll see blocks start streaming through. + +For this example, we're doing the above on a cloud machine. The next steps should be done on your local machine or another server in the cloud, which will join the running testnet then bond/unbond. + +Accounts +-------- + +We have: + +- ``alice`` the initial validator (in the cloud) +- ``bob`` receives tokens from ``alice`` then declares candidacy (from local machine) +- ``charlie`` will bond and unbond to ``bob`` (from local machine) + +Remember that ``alice`` was already created. On your second machine, install the binaries and create two new keys: + +:: + + basecli keys add bob + basecli keys add charlie + +both of which will prompt you for a password. Now we need to copy the ``genesis.json`` and ``config.toml`` from the first machine (with ``alice``) to the second machine. This is a good time to look at both these files. + +The ``genesis.json`` should look something like: + +:: + + { + "app_hash": "", + "app_state": { + "accounts": [ + { + "address": "1FEADCDC8CCB22244769B9CC93C1F6D7489FC5AF", + "coins": [ + { + "denom": "mycoin", + "amount": 9007199254740992 + } + ] + } + ] + }, + "chain_id": "test-chain-EsYka3", + "genesis_time": "0001-01-01T00:00:00Z", + "validators": [ + { + "pub_key": { + "type": "ed25519", + "data": "57B89D41F18FE3FE69250B44693A7D68DE4E03EC563F54C27F9A86CE8B81A4B7" + }, + "power": 10, + "name": "" + } + ] + } + +To notice is that the ``accounts`` field has a an address and a whole bunch of "mycoin". This is ``alice``'s address (todo: dbl check). Under ``validators`` we see the ``pub_key.data`` field, which will match the same field in the ``priv_validator.json`` file. + +The ``config.toml`` is long so let's focus on one field: + +:: + + # Comma separated list of seed nodes to connect to + seeds = "" + +On the ``alice`` cloud machine, we don't need to do anything here. Instead, we need its IP address. After copying this file (and the ``genesis.json`` to your local machine, you'll want to put the IP in the ``seeds = "138.197.161.74"`` field, in this case, we have a made-up IP. For joining testnets with many nodes, you can add more comma-seperated IPs to the list. + + +Now that your files are all setup, it's time to join the network. On your local machine, run: + +:: + + basecoind start + +and your new node will connect to the running validator (``alice``). Sending Tokens -------------- -We'll have ``alice`` who is currently quite rich, send some ``fermions`` to ``bob``: +We'll have ``alice`` send some ``mycoin`` to ``bob``, who has now joined the network: :: - gaia client tx send --amount=1000fermion --sequence=1 --name=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 + basecli send --amount=1000fermion --seq=0 --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: +where the ``--seq`` 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: :: @@ -101,11 +190,13 @@ where the ``--sequence`` flag is to be incremented for each transaction, the ``- "height": 2963 } +TODO: check the above with current actual output. + Check out ``bob``'s account, which should now have 992 fermions: :: - gaia client query account 5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 + basecli account 5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 Adding a Second Validator ------------------------- @@ -114,6 +205,8 @@ Next, let's add the second node as a validator. First, we need the pub_key data: +** need to make bob a priv_Val above! + :: cat $HOME/.gaia2/priv_validator.json @@ -130,7 +223,7 @@ Now ``bob`` can declare candidacy to that pubkey: :: - gaia client tx declare-candidacy --amount=10fermion --name=bob --pubkey= --moniker=bobby + basecli declare-candidacy --amount=10mycoin --name=bob --pubkey= --moniker=bobby with an output like: From 6a7dc0966f2ca7676c61a51431319ef8dbf25c25 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Tue, 3 Apr 2018 05:09:24 -0700 Subject: [PATCH 45/71] docs: update binary --- docs/old/staking/intro.rst | 40 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/old/staking/intro.rst b/docs/old/staking/intro.rst index a8f4ea078..3a8973df1 100644 --- a/docs/old/staking/intro.rst +++ b/docs/old/staking/intro.rst @@ -65,8 +65,6 @@ You can see all available keys with: basecli keys list -See the `key management tutorial <../key-management.html>`__ for more information on managing keys. - Setup Testnet ------------- @@ -158,9 +156,9 @@ We'll have ``alice`` send some ``mycoin`` to ``bob``, who has now joined the net :: - basecli send --amount=1000fermion --seq=0 --name=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 + basecli send --amount=1000mycoin --seq=0 --name=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 -where the ``--seq`` 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: +where the ``--seq`` flag is to be incremented for each transaction, the ``--name`` flag is the sender (alice), and the ``--to`` flag takes ``bob``'s address. You'll see something like: :: @@ -192,12 +190,16 @@ where the ``--seq`` flag is to be incremented for each transaction, the ``--name TODO: check the above with current actual output. -Check out ``bob``'s account, which should now have 992 fermions: +Check out ``bob``'s account, which should now have 1000 mycoin: :: basecli account 5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 + + + + Adding a Second Validator ------------------------- @@ -205,7 +207,7 @@ Next, let's add the second node as a validator. First, we need the pub_key data: -** need to make bob a priv_Val above! +** need to make bob a priv_Val above? :: @@ -240,11 +242,11 @@ with an output like: } -We should see ``bob``'s account balance decrease by 10 fermions: +We should see ``bob``'s account balance decrease by 10 mycoin: :: - gaia client query account 5D93A6059B6592833CBC8FA3DA90EE0382198985 + basecli account 5D93A6059B6592833CBC8FA3DA90EE0382198985 To confirm for certain the new validator is active, ask the tendermint node: @@ -256,7 +258,7 @@ 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``. +Now that ``bob`` has declared candidacy, which essentially bonded 10 mycoin and made him a validator, we're going to get ``charlie`` to delegate some coins to ``bob``. Delegating ---------- @@ -265,13 +267,13 @@ First let's have ``alice`` send some coins to ``charlie``: :: - gaia client tx send --amount=1000fermion --sequence=2 --name=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF + basecli tx --amount=1000mycoin --sequence=2 --name=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF -Then ``charlie`` will delegate some fermions to ``bob``: +Then ``charlie`` will delegate some mycoin to ``bob``: :: - gaia client tx delegate --amount=10fermion --name=charlie --pubkey= + basecli tx delegate --amount=10mycoin --name=charlie --pubkey= You'll see output like: @@ -287,13 +289,13 @@ You'll see output like: "height": 51585 } -And that's it. You can query ``charlie``'s account to see the decrease in fermions. +And that's it. You can query ``charlie``'s account to see the decrease in mycoin. To get more information about the candidate, try: :: - gaia client query candidate --pubkey= + basecli query candidate --pubkey= and you'll see output similar to: @@ -326,7 +328,7 @@ It's also possible the query the delegator's bond like so: :: - gaia client query delegator-bond --delegator-address 48F74F48281C89E5E4BE9092F735EA519768E8EF --pubkey 52D6FCD8C92A97F7CCB01205ADF310A18411EA8FDCC10E65BF2FCDB05AD1689B + basecli query delegator-bond --delegator-address 48F74F48281C89E5E4BE9092F735EA519768E8EF --pubkey 52D6FCD8C92A97F7CCB01205ADF310A18411EA8FDCC10E65BF2FCDB05AD1689B with an output similar to: @@ -355,9 +357,7 @@ your VotingPower reduce and your account balance increase. :: - gaia client tx unbond --amount=5fermion --name=charlie --pubkey= - gaia client query account 48F74F48281C89E5E4BE9092F735EA519768E8EF + basecli unbond --amount=5mycoin --name=charlie --pubkey= + basecli 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. +See the bond decrease with ``basecli query delegator-bond`` like above. From 15011eaf2277b14455866d2012d2a4f6ec16208d Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 11 Apr 2018 10:14:34 -0400 Subject: [PATCH 46/71] docs: use correct binary --- docs/old/staking/intro.rst | 52 ++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/docs/old/staking/intro.rst b/docs/old/staking/intro.rst index 3a8973df1..d6f046aba 100644 --- a/docs/old/staking/intro.rst +++ b/docs/old/staking/intro.rst @@ -13,7 +13,7 @@ This example covers initial setup of a two-node testnet between a server in the Install ------- -The ``basecoind`` and ``basecli`` binaries: +The ``gaiad`` and ``gaiacli`` binaries: :: @@ -26,24 +26,24 @@ Let's jump right into it. First, we initialize some default files: :: - basecoind init + gaiad init which will output: :: - I[03-30|11:20:13.365] Found private validator module=main path=/root/.basecoind/config/priv_validator.json - I[03-30|11:20:13.365] Found genesis file module=main path=/root/.basecoind/config/genesis.json + I[03-30|11:20:13.365] Found private validator module=main path=/root/.gaiad/config/priv_validator.json + I[03-30|11:20:13.365] Found genesis file module=main path=/root/.gaiad/config/genesis.json Secret phrase to access coins: citizen hungry tennis noise park hire glory exercise link glow dolphin labor design grit apple abandon -This tell us we have a ``priv_validator.json`` and ``genesis.json`` in the ``~/.basecoind/config`` directory. A ``config.toml`` was also created in the same directory. It is a good idea to get familiar with those files. Write down the seed. +This tell us we have a ``priv_validator.json`` and ``genesis.json`` in the ``~/.gaiad/config`` directory. A ``config.toml`` was also created in the same directory. It is a good idea to get familiar with those files. Write down the seed. -The next thing we'll need to is add the key from ``priv_validator.json`` to the ``basecli`` key manager. For this we need a seed and a password: +The next thing we'll need to is add the key from ``priv_validator.json`` to the ``gaiacli`` key manager. For this we need a seed and a password: :: - basecli keys add alice --recover + gaiacli keys add alice --recover which will give you three prompts: @@ -63,7 +63,7 @@ You can see all available keys with: :: - basecli keys list + gaiacli keys list Setup Testnet ------------- @@ -72,7 +72,7 @@ Next, we start the daemon (do this in another window): :: - basecoind start + gaiad start and you'll see blocks start streaming through. @@ -91,8 +91,8 @@ Remember that ``alice`` was already created. On your second machine, install the :: - basecli keys add bob - basecli keys add charlie + gaiacli keys add bob + gaiacli keys add charlie both of which will prompt you for a password. Now we need to copy the ``genesis.json`` and ``config.toml`` from the first machine (with ``alice``) to the second machine. This is a good time to look at both these files. @@ -145,7 +145,7 @@ Now that your files are all setup, it's time to join the network. On your local :: - basecoind start + gaiad start and your new node will connect to the running validator (``alice``). @@ -156,7 +156,7 @@ We'll have ``alice`` send some ``mycoin`` to ``bob``, who has now joined the net :: - basecli send --amount=1000mycoin --seq=0 --name=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 + gaiacli send --amount=1000mycoin --seq=0 --name=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 where the ``--seq`` flag is to be incremented for each transaction, the ``--name`` flag is the sender (alice), and the ``--to`` flag takes ``bob``'s address. You'll see something like: @@ -194,15 +194,13 @@ Check out ``bob``'s account, which should now have 1000 mycoin: :: - basecli account 5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 - - - - + gaiacli account 5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 Adding a Second Validator ------------------------- +**This section is wrong/needs to be updated** + Next, let's add the second node as a validator. First, we need the pub_key data: @@ -225,7 +223,7 @@ Now ``bob`` can declare candidacy to that pubkey: :: - basecli declare-candidacy --amount=10mycoin --name=bob --pubkey= --moniker=bobby + gaiacli declare-candidacy --amount=10mycoin --name=bob --pubkey= --moniker=bobby with an output like: @@ -246,7 +244,7 @@ We should see ``bob``'s account balance decrease by 10 mycoin: :: - basecli account 5D93A6059B6592833CBC8FA3DA90EE0382198985 + gaiacli account 5D93A6059B6592833CBC8FA3DA90EE0382198985 To confirm for certain the new validator is active, ask the tendermint node: @@ -267,13 +265,13 @@ First let's have ``alice`` send some coins to ``charlie``: :: - basecli tx --amount=1000mycoin --sequence=2 --name=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF + gaiacli tx --amount=1000mycoin --sequence=2 --name=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF Then ``charlie`` will delegate some mycoin to ``bob``: :: - basecli tx delegate --amount=10mycoin --name=charlie --pubkey= + gaiacli tx delegate --amount=10mycoin --name=charlie --pubkey= You'll see output like: @@ -295,7 +293,7 @@ To get more information about the candidate, try: :: - basecli query candidate --pubkey= + gaiacli query candidate --pubkey= and you'll see output similar to: @@ -328,7 +326,7 @@ It's also possible the query the delegator's bond like so: :: - basecli query delegator-bond --delegator-address 48F74F48281C89E5E4BE9092F735EA519768E8EF --pubkey 52D6FCD8C92A97F7CCB01205ADF310A18411EA8FDCC10E65BF2FCDB05AD1689B + gaiacli query delegator-bond --delegator-address 48F74F48281C89E5E4BE9092F735EA519768E8EF --pubkey 52D6FCD8C92A97F7CCB01205ADF310A18411EA8FDCC10E65BF2FCDB05AD1689B with an output similar to: @@ -357,7 +355,7 @@ your VotingPower reduce and your account balance increase. :: - basecli unbond --amount=5mycoin --name=charlie --pubkey= - basecli account 48F74F48281C89E5E4BE9092F735EA519768E8EF + gaiacli unbond --amount=5mycoin --name=charlie --pubkey= + gaiacli account 48F74F48281C89E5E4BE9092F735EA519768E8EF -See the bond decrease with ``basecli query delegator-bond`` like above. +See the bond decrease with ``gaiacli query delegator-bond`` like above. From d7d09f3feab5b7d6bfd4eccdcd2cef8f7d59cd8d Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 11 Apr 2018 10:47:55 -0400 Subject: [PATCH 47/71] docs: cleanup --- docs/conf.py | 2 +- docs/index.rst | 25 +++++++++---------------- docs/sdk/install.rst | 20 +++++++------------- 3 files changed, 17 insertions(+), 30 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 3af51ef95..f0fa0a634 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -47,7 +47,7 @@ master_doc = 'index' # General information about the project. project = u'Cosmos-SDK' -copyright = u'2017, The Authors' +copyright = u'2018, The Authors' author = u'The Authors' # The version info for the project you're documenting, acts as replacement for diff --git a/docs/index.rst b/docs/index.rst index 80d5dd48d..23dd1e87a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -21,7 +21,7 @@ SDK sdk/overview.rst sdk/install.rst - sdk/glossary.rst +.. old/glossary.rst # not completely up to date but has good content .. Basecoin .. -------- @@ -29,19 +29,17 @@ SDK .. .. toctree:: :maxdepth: 2 -.. basecoin/basics.rst -.. basecoin/extensions.rst +.. old/basecoin/basics.rst # has a decent getting-start tutorial that's relatively up to date, should be consolidated with the other getting started doc Extensions ---------- -Replay Protection -~~~~~~~~~~~~~~~~~ +.. old/basecoin/extensions.rst # probably not worth salvaging -.. toctree:: - :maxdepth: 1 +.. Replay Protection +.. ~~~~~~~~~~~~~~~~~ - x/replay-protection.rst +.. old/replay-protection.rst # not sure if worth salvaging Staking @@ -55,12 +53,7 @@ Staking staking/local-testnet.rst staking/public-testnet.rst -Extras ------- +.. IBC +.. --- -.. One maxdepth for now - -.. toctree:: - :maxdepth: 1 - - ibc.rst +.. old/ibc.rst # needs to be updated diff --git a/docs/sdk/install.rst b/docs/sdk/install.rst index b4c0ad5da..33c176913 100644 --- a/docs/sdk/install.rst +++ b/docs/sdk/install.rst @@ -1,17 +1,12 @@ Install ======= -If you aren't used to compile go programs and just want the released -version of the code, please head to our -`downloads `__ page to get a -pre-compiled binary for your platform. - -Usually, Cosmos SDK can be installed to +Cosmos SDK can be installed to `$GOPATH/src/github.com/cosmos/cosmos-sdk` like a normal Go program: :: - go get -u github.com/cosmos/cosmos-sdk + go get github.com/cosmos/cosmos-sdk If the dependencies have been updated with breaking changes, or if another branch is required, ``dep`` is used for dependency management. @@ -21,10 +16,9 @@ repo, the correct way to install is: :: cd $GOPATH/src/github.com/cosmos/cosmos-sdk - git pull origin master - make all + make get_vendor_deps + make install + make install_examples -This will create the ``basecoind`` and ``basecli`` binaries locally in -``./build/bin``. ``make all`` implies ``make get_vendor_deps`` and uses -``glide`` to install the correct version of all dependencies. It also tests the -code, including some cli tests to make sure your binary behaves properly. +This will install ``gaiad`` and ``gaiacli`` and four example binaries: +``basecoind``, ``basecli``, ``democoind``, and ``democli``. From 4c0a5a6c209fd28fe8349a6781c42e2a49916a3d Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 11 Apr 2018 10:53:50 -0400 Subject: [PATCH 48/71] docs: move back updated intro --- docs/{old => }/staking/intro.rst | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/{old => }/staking/intro.rst (100%) diff --git a/docs/old/staking/intro.rst b/docs/staking/intro.rst similarity index 100% rename from docs/old/staking/intro.rst rename to docs/staking/intro.rst From c3cabbf78622e1e50744946802b63b9c4072e849 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 11 Apr 2018 11:25:17 -0400 Subject: [PATCH 49/71] docs: add testnet doc from @kidinamoto01 --- docs/staking/testnet.rst | 211 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 docs/staking/testnet.rst diff --git a/docs/staking/testnet.rst b/docs/staking/testnet.rst new file mode 100644 index 000000000..b18adf5eb --- /dev/null +++ b/docs/staking/testnet.rst @@ -0,0 +1,211 @@ +# Cosmos Testnet Setup + +## Installment + +Requirement : + + [Go 1.9+](https://golang.org/dl/) + + [dep](https://github.com/golang/dep) + +### STEPS + +**Get Source Code** + +``` +go get github.com/cosmos/cosmos-sdk +``` + +Now we can fetch the correct versions of each dependency by running: + +``` +cd $GOPATH/src/github.com/cosmos/cosmos-sdk +git fetch --all +git checkout develop +make get_tools +make get_vendor_deps +make install +make install_examples +``` + +The latest cosmos-sdk should now be installed. Verify that everything is OK by running: + +``` +gaiad version +``` +You should see: + +``` +0.15.0-rc1-9d90c6b +``` + +And also: + +``` +basecli version +``` + +You should see: + +``` +0.15.0-rc1-9d90c6b +``` + +### Local-Test Example + +Here is a quick example to get you off your feet: + +First, generate a new key with a name, and save the address: +``` +MYNAME= +basecli keys new $MYNAME +basecli keys list +MYADDR= +``` +Now initialize a gaia chain: +``` +gaiad init --home=$HOME/.gaiad1 +``` + +you should see seed phrase for genesis account in the output & config & data folder int the home directory + +In the config folder, there will be the following file: config.toml , genesis.json, node_key.json ,priv_validator.json + +The genesis file should look like this: + +``` +{ + "genesis_time": "0001-01-01T00:00:00Z", + "chain_id": "test-chain-0TRiTa", + "validators": [ + { + "pub_key": { + "type": "AC26791624DE60", + "value": "" + }, + "power": 10, + "name": "" + } + ], + "app_hash": "", + "app_state": { + "accounts": [ + { + "address": "", + "coins": [ + { + "denom": "steak", + "amount": 9007199254740992 + } + ] + } + ] + } +} +``` + +**Note: ** We need to change the denomination of token from default to `steak` in genesis file. + +Then, recover the genesis account with `basecli` + +``` +basecli keys add --recover +``` + +By now, you have set up the first node. This is great! + +We can add a second node on our local machine by initiating a node in a new directory, and copying in the genesis. + +``` +gaiad init --home=$HOME/.gaiad2 +``` + +Replace the genesis file and toml file to another folder + +``` +cp $HOME/.gaiad/config/genesis.json $HOME/.gaiad2/config +cp $HOME/.gaiad/config/config.toml $HOME/.gaiad2/config +``` + +Get the node id of first node. +``` +gaiad show_node_id --home=$HOME/.gaiad1 +``` +We need to also modify $HOME/.gaiad2/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" +persistent_peers = "@0.0.0.0:46656" +``` +Great, now that we've initialized the chains, we can start both nodes in the background: +``` +gaiad start --home=$HOME/.gaiad1 &> gaia1.log & +NODE1_PID=$! +gaia start --home=$HOME/.gaiad2 &> gaia2.log & +NODE2_PID=$! +``` +Note we save the PID so we can later kill the processes. Of course, you can peak at your logs with tail gaia1.log, or follow them for a bit with tail -f gaia1.log. +Nice. We can also lookup the validator set: + +``` +basecli validatorset +``` +There is only **one** validator now. Let's add another one! +First, we need to create a new account: + +``` +basecli keys new +``` +Check that we now have two accounts: +``` +basecli keys list +``` +Then, we try to transfer some `strak` to another account: +``` +basecli send --amount=1000steak --to=$MYADDR2 --name=$NAME --chain-id= --node=tcp://localhost:46657 --sequence=0 +``` +**Note** We need to be careful with the `chain-id` & `sequence` + +Check the balance & sequence by : +``` +basecli account $MYADDR +``` +We can see the balance of $MYADDR2 is 1000 now. + +Findally, let's bind the validator in `$HOME/gaiad2`, get the pubkey first +``` +cat $HOME/.gaiad2/config/priv_validator.json | jq .pub_key.value +``` + +Go to [this website](http://tomeko.net/online_tools/base64.php?lang=en) to change pubkey from base64 to Hex. +Ok, now we can bond some coins to that pubkey: +``` +basecli bond --stake=1steak --validator= --sequence=0 --chain-id= --name=test +``` +Nice. We can see there are two validators: + +``` +basecli validatorset +``` +Check the balance of $MYADDR2 to see the difference: it has 1 less `steak`! +``` +basecli account $MYADDR2 +``` +To confirm for certain the new validator is active, check tendermint: +``` +curl localhost:46657/validators +``` +Finally, to relinquish all your power, unbond some coins. You should see your VotingPower reduce and your account balance increase. +``` +basecli unbond --sequence=# --chain-id= --name=test +``` + From 90d03a81b0a54032b64499bfb74697037aaed484 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 11 Apr 2018 11:44:44 -0400 Subject: [PATCH 50/71] docs: rst-ify testnet doc --- docs/sdk/install.rst | 24 +++ docs/staking/testnet.rst | 316 +++++++++++++++++++-------------------- 2 files changed, 175 insertions(+), 165 deletions(-) diff --git a/docs/sdk/install.rst b/docs/sdk/install.rst index 33c176913..213c49a37 100644 --- a/docs/sdk/install.rst +++ b/docs/sdk/install.rst @@ -22,3 +22,27 @@ repo, the correct way to install is: This will install ``gaiad`` and ``gaiacli`` and four example binaries: ``basecoind``, ``basecli``, ``democoind``, and ``democli``. + +Verify that everything is OK by running: + +:: + + gaiad version + +you should see: + +:: + + 0.15.0-rc1-9d90c6b + +then with: + +:: + + basecli version + +you should see: + +:: + + 0.15.0-rc1-9d90c6b diff --git a/docs/staking/testnet.rst b/docs/staking/testnet.rst index b18adf5eb..eabe18bb6 100644 --- a/docs/staking/testnet.rst +++ b/docs/staking/testnet.rst @@ -1,211 +1,197 @@ -# Cosmos Testnet Setup +Testnet Setup +============= -## Installment +Install +------- -Requirement : +See the `installation guide <../sdk/install.html>`__ for details on installation. - [Go 1.9+](https://golang.org/dl/) - - [dep](https://github.com/golang/dep) - -### STEPS - -**Get Source Code** - -``` -go get github.com/cosmos/cosmos-sdk -``` - -Now we can fetch the correct versions of each dependency by running: - -``` -cd $GOPATH/src/github.com/cosmos/cosmos-sdk -git fetch --all -git checkout develop -make get_tools -make get_vendor_deps -make install -make install_examples -``` - -The latest cosmos-sdk should now be installed. Verify that everything is OK by running: - -``` -gaiad version -``` -You should see: - -``` -0.15.0-rc1-9d90c6b -``` - -And also: - -``` -basecli version -``` - -You should see: - -``` -0.15.0-rc1-9d90c6b -``` ### Local-Test Example Here is a quick example to get you off your feet: First, generate a new key with a name, and save the address: -``` -MYNAME= -basecli keys new $MYNAME -basecli keys list -MYADDR= -``` + +:: + + MYNAME= + basecli keys new $MYNAME + basecli keys list + MYADDR= + + Now initialize a gaia chain: -``` -gaiad init --home=$HOME/.gaiad1 -``` -you should see seed phrase for genesis account in the output & config & data folder int the home directory +:: + gaiad init --home=$HOME/.gaiad1 -In the config folder, there will be the following file: config.toml , genesis.json, node_key.json ,priv_validator.json +you should see seed phrase for genesis account in the output & config & data folder in the home directory. + +In the config folder, there will be the following files: ``config.toml``, ``genesis.json``, ``node_key.json``, and ``priv_validator.json``. The genesis file should look like this: -``` -{ - "genesis_time": "0001-01-01T00:00:00Z", - "chain_id": "test-chain-0TRiTa", - "validators": [ +:: + { - "pub_key": { - "type": "AC26791624DE60", - "value": "" - }, - "power": 10, - "name": "" - } - ], - "app_hash": "", - "app_state": { - "accounts": [ - { - "address": "", - "coins": [ + "genesis_time": "0001-01-01T00:00:00Z", + "chain_id": "test-chain-0TRiTa", + "validators": [ + { + "pub_key": { + "type": "AC26791624DE60", + "value": "" + }, + "power": 10, + "name": "" + } + ], + "app_hash": "", + "app_state": { + "accounts": [ { - "denom": "steak", - "amount": 9007199254740992 + "address": "", + "coins": [ + { + "denom": "steak", + "amount": 9007199254740992 + } + ] } ] } - ] - } -} -``` + } -**Note: ** We need to change the denomination of token from default to `steak` in genesis file. -Then, recover the genesis account with `basecli` +**Note:** We need to change the denomination of token from default to ``steak`` in genesis file. -``` -basecli keys add --recover -``` +Then, recover the genesis account with ``basecli``: + +:: + + basecli keys add --recover By now, you have set up the first node. This is great! -We can add a second node on our local machine by initiating a node in a new directory, and copying in the genesis. +We can add a second node on our local machine by initiating a node in a new directory, and copying in the ``genesis.json``: -``` -gaiad init --home=$HOME/.gaiad2 -``` +:: -Replace the genesis file and toml file to another folder + gaiad init --home=$HOME/.gaiad2 -``` -cp $HOME/.gaiad/config/genesis.json $HOME/.gaiad2/config -cp $HOME/.gaiad/config/config.toml $HOME/.gaiad2/config -``` +and replace the ``genesis.json`` and ``config.toml`` file: + +:: + + cp $HOME/.gaiad/config/genesis.json $HOME/.gaiad2/config + cp $HOME/.gaiad/config/config.toml $HOME/.gaiad2/config + +then, get the node id of first node: + +:: + + gaiad show_node_id --home=$HOME/.gaiad1 -Get the node id of first node. -``` -gaiad show_node_id --home=$HOME/.gaiad1 -``` We need to also modify $HOME/.gaiad2/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" +:: + + 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" + persistent_peers = "@0.0.0.0:46656" + -[p2p] -laddr = "tcp://0.0.0.0:46666" -persistent_peers = "@0.0.0.0:46656" -``` Great, now that we've initialized the chains, we can start both nodes in the background: -``` -gaiad start --home=$HOME/.gaiad1 &> gaia1.log & -NODE1_PID=$! -gaia start --home=$HOME/.gaiad2 &> gaia2.log & -NODE2_PID=$! -``` -Note we save the PID so we can later kill the processes. Of course, you can peak at your logs with tail gaia1.log, or follow them for a bit with tail -f gaia1.log. + +:: + + gaiad start --home=$HOME/.gaiad1 &> gaia1.log & + NODE1_PID=$! + gaia start --home=$HOME/.gaiad2 &> gaia2.log & + NODE2_PID=$! + +Note that we save the PID so we can later kill the processes. You can peak at your logs with ``tail gaia1.log``, or follow them for a bit with ``tail -f gaia1.log``. + Nice. We can also lookup the validator set: -``` -basecli validatorset -``` -There is only **one** validator now. Let's add another one! +:: + + basecli validatorset + +There is only **one** validator now. Let's add another one! + First, we need to create a new account: -``` -basecli keys new -``` +:: + + basecli keys new + Check that we now have two accounts: -``` -basecli keys list -``` -Then, we try to transfer some `strak` to another account: -``` -basecli send --amount=1000steak --to=$MYADDR2 --name=$NAME --chain-id= --node=tcp://localhost:46657 --sequence=0 -``` -**Note** We need to be careful with the `chain-id` & `sequence` -Check the balance & sequence by : -``` -basecli account $MYADDR -``` -We can see the balance of $MYADDR2 is 1000 now. +:: + basecli keys list -Findally, let's bind the validator in `$HOME/gaiad2`, get the pubkey first -``` -cat $HOME/.gaiad2/config/priv_validator.json | jq .pub_key.value -``` +Then, we try to transfer some ``steak`` to another account: + +:: + + basecli send --amount=1000steak --to=$MYADDR2 --name=$NAME --chain-id= --node=tcp://localhost:46657 --sequence=0 + +**Note** We need to be careful with the ``chain-id`` and ``sequence`` + +Check the balance & sequence with: + +:: + + basecli account $MYADDR + +We can see the balance of ``$MYADDR2`` is 1000 now. + +Finally, let's bond the validator in ``$HOME/gaiad2``. Get the pubkey first: + +:: + + cat $HOME/.gaiad2/config/priv_validator.json | jq .pub_key.value + +Go to [this website](http://tomeko.net/online_tools/base64.php?lang=en) to change pubkey from base64 to Hex. -Go to [this website](http://tomeko.net/online_tools/base64.php?lang=en) to change pubkey from base64 to Hex. Ok, now we can bond some coins to that pubkey: -``` -basecli bond --stake=1steak --validator= --sequence=0 --chain-id= --name=test -``` -Nice. We can see there are two validators: -``` -basecli validatorset -``` -Check the balance of $MYADDR2 to see the difference: it has 1 less `steak`! -``` -basecli account $MYADDR2 -``` +:: + + basecli bond --stake=1steak --validator= --sequence=0 --chain-id= --name=test + +Nice. We can see there are now two validators: + +:: + + basecli validatorset + +Check the balance of ``$MYADDR2`` to see the difference: it has 1 less ``steak``! + +:: + basecli account $MYADDR2 + To confirm for certain the new validator is active, check tendermint: -``` -curl localhost:46657/validators -``` -Finally, to relinquish all your power, unbond some coins. You should see your VotingPower reduce and your account balance increase. -``` -basecli unbond --sequence=# --chain-id= --name=test -``` +:: + + curl localhost:46657/validators + +Finally, to relinquish all your power, unbond some coins. You should see your VotingPower reduce and your account balance increase. + +:: + + basecli unbond --sequence=# --chain-id= --name=test + +That's it! From 9924b1cb11b5eaf8984de446bdaedd40289a2d0f Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 11 Apr 2018 11:46:50 -0400 Subject: [PATCH 51/71] docs: build fixes --- docs/conf.py | 2 +- docs/index.rst | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index f0fa0a634..73a0220fd 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -69,7 +69,7 @@ language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'old'] # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' diff --git a/docs/index.rst b/docs/index.rst index 23dd1e87a..3bf1c06ad 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -49,9 +49,10 @@ Staking :maxdepth: 1 staking/intro.rst - staking/key-management.rst - staking/local-testnet.rst - staking/public-testnet.rst + staking/testnet.rst +.. staking/key-management.rst +.. staking/local-testnet.rst +.. staking/public-testnet.rst .. IBC .. --- From f9fc2e88d99701bbae40a07a42024aa871cce6d0 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 11 Apr 2018 11:55:22 -0400 Subject: [PATCH 52/71] lil fixes --- docs/index.rst | 10 ++++------ docs/sdk/install.rst | 2 +- docs/staking/testnet.rst | 18 +++++++----------- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 3bf1c06ad..1dc8eb35f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -14,13 +14,11 @@ Welcome to the Cosmos SDK! SDK --- -.. One maxdepth for now - .. toctree:: :maxdepth: 1 - sdk/overview.rst sdk/install.rst +.. sdk/overview.rst # needs to be updated .. old/glossary.rst # not completely up to date but has good content .. Basecoin @@ -31,8 +29,8 @@ SDK .. old/basecoin/basics.rst # has a decent getting-start tutorial that's relatively up to date, should be consolidated with the other getting started doc -Extensions ----------- +.. Extensions +.. ---------- .. old/basecoin/extensions.rst # probably not worth salvaging @@ -48,8 +46,8 @@ Staking .. toctree:: :maxdepth: 1 - staking/intro.rst staking/testnet.rst +.. staking/intro.rst .. staking/key-management.rst .. staking/local-testnet.rst .. staking/public-testnet.rst diff --git a/docs/sdk/install.rst b/docs/sdk/install.rst index 213c49a37..d0e90b838 100644 --- a/docs/sdk/install.rst +++ b/docs/sdk/install.rst @@ -2,7 +2,7 @@ Install ======= Cosmos SDK can be installed to -`$GOPATH/src/github.com/cosmos/cosmos-sdk` like a normal Go program: +``$GOPATH/src/github.com/cosmos/cosmos-sdk`` like a normal Go program: :: diff --git a/docs/staking/testnet.rst b/docs/staking/testnet.rst index eabe18bb6..a04383690 100644 --- a/docs/staking/testnet.rst +++ b/docs/staking/testnet.rst @@ -1,14 +1,8 @@ Testnet Setup ============= -Install -------- - See the `installation guide <../sdk/install.html>`__ for details on installation. - -### Local-Test Example - Here is a quick example to get you off your feet: First, generate a new key with a name, and save the address: @@ -24,6 +18,7 @@ First, generate a new key with a name, and save the address: Now initialize a gaia chain: :: + gaiad init --home=$HOME/.gaiad1 you should see seed phrase for genesis account in the output & config & data folder in the home directory. @@ -63,8 +58,7 @@ The genesis file should look like this: } } - -**Note:** We need to change the denomination of token from default to ``steak`` in genesis file. +**Note:** We need to change the denomination of token from default to ``steak`` in the genesis file. Then, recover the genesis account with ``basecli``: @@ -80,7 +74,7 @@ We can add a second node on our local machine by initiating a node in a new dire gaiad init --home=$HOME/.gaiad2 -and replace the ``genesis.json`` and ``config.toml`` file: +and replace the ``genesis.json`` and ``config.toml`` files: :: @@ -139,6 +133,7 @@ First, we need to create a new account: Check that we now have two accounts: :: + basecli keys list Then, we try to transfer some ``steak`` to another account: @@ -147,7 +142,7 @@ Then, we try to transfer some ``steak`` to another account: basecli send --amount=1000steak --to=$MYADDR2 --name=$NAME --chain-id= --node=tcp://localhost:46657 --sequence=0 -**Note** We need to be careful with the ``chain-id`` and ``sequence`` +**Note:** We need to be careful with the ``chain-id`` and ``sequence`` Check the balance & sequence with: @@ -163,7 +158,7 @@ Finally, let's bond the validator in ``$HOME/gaiad2``. Get the pubkey first: cat $HOME/.gaiad2/config/priv_validator.json | jq .pub_key.value -Go to [this website](http://tomeko.net/online_tools/base64.php?lang=en) to change pubkey from base64 to Hex. +Go to `this website `__ to change pubkey from base64 to Hex. Ok, now we can bond some coins to that pubkey: @@ -180,6 +175,7 @@ Nice. We can see there are now two validators: Check the balance of ``$MYADDR2`` to see the difference: it has 1 less ``steak``! :: + basecli account $MYADDR2 To confirm for certain the new validator is active, check tendermint: From 0fd69d56ee7fc09af323416ca958d7f0b8731b48 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Thu, 19 Apr 2018 12:14:06 -0400 Subject: [PATCH 53/71] docs: PR comments --- docs/sdk/install.rst | 2 +- docs/staking/intro.rst | 65 ++++++++++++++++++++++++++++++++-------- docs/staking/testnet.rst | 26 ++++++++-------- 3 files changed, 67 insertions(+), 26 deletions(-) diff --git a/docs/sdk/install.rst b/docs/sdk/install.rst index d0e90b838..03b219cb5 100644 --- a/docs/sdk/install.rst +++ b/docs/sdk/install.rst @@ -39,7 +39,7 @@ then with: :: - basecli version + gaiacli version you should see: diff --git a/docs/staking/intro.rst b/docs/staking/intro.rst index d6f046aba..68032c536 100644 --- a/docs/staking/intro.rst +++ b/docs/staking/intro.rst @@ -101,34 +101,75 @@ The ``genesis.json`` should look something like: :: { - "app_hash": "", "app_state": { "accounts": [ { - "address": "1FEADCDC8CCB22244769B9CC93C1F6D7489FC5AF", + "address": "1D9B2356CAADF46D3EE3488E3CCE3028B4283DEE", "coins": [ { - "denom": "mycoin", - "amount": 9007199254740992 + "denom": "fermion", + "amount": 100000 } ] } - ] + ], + "stake": { + "pool": { + "total_supply": 0, + "bonded_shares": { + "num": 0, + "denom": 1 + }, + "unbonded_shares": { + "num": 0, + "denom": 1 + }, + "bonded_pool": 0, + "unbonded_pool": 0, + "inflation_last_time": 0, + "inflation": { + "num": 7, + "denom": 100 + } + }, + "params": { + "inflation_rate_change": { + "num": 13, + "denom": 100 + }, + "inflation_max": { + "num": 20, + "denom": 100 + }, + "inflation_min": { + "num": 7, + "denom": 100 + }, + "goal_bonded": { + "num": 67, + "denom": 100 + }, + "max_validators": 100, + "bond_denom": "fermion" + } + } }, - "chain_id": "test-chain-EsYka3", - "genesis_time": "0001-01-01T00:00:00Z", "validators": [ { "pub_key": { - "type": "ed25519", - "data": "57B89D41F18FE3FE69250B44693A7D68DE4E03EC563F54C27F9A86CE8B81A4B7" + "type": "AC26791624DE60", + "value": "rgpc/ctVld6RpSfwN5yxGBF17R1PwMTdhQ9gKVUZp5g=" }, "power": 10, "name": "" } - ] + ], + "app_hash": "", + "genesis_time": "0001-01-01T00:00:00Z", + "chain_id": "test-chain-Uv1EVU" } + To notice is that the ``accounts`` field has a an address and a whole bunch of "mycoin". This is ``alice``'s address (todo: dbl check). Under ``validators`` we see the ``pub_key.data`` field, which will match the same field in the ``priv_validator.json`` file. The ``config.toml`` is long so let's focus on one field: @@ -156,9 +197,9 @@ We'll have ``alice`` send some ``mycoin`` to ``bob``, who has now joined the net :: - gaiacli send --amount=1000mycoin --seq=0 --name=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 + gaiacli send --amount=1000mycoin --sequence=0 --name=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 --chain-id=test-chain-Uv1EVU -where the ``--seq`` flag is to be incremented for each transaction, the ``--name`` flag is the sender (alice), and the ``--to`` flag takes ``bob``'s address. You'll see something like: +where the ``--sequence`` flag is to be incremented for each transaction, the ``--name`` flag is the sender (alice), and the ``--to`` flag takes ``bob``'s address. You'll see something like: :: diff --git a/docs/staking/testnet.rst b/docs/staking/testnet.rst index a04383690..484ec3b5d 100644 --- a/docs/staking/testnet.rst +++ b/docs/staking/testnet.rst @@ -10,8 +10,8 @@ First, generate a new key with a name, and save the address: :: MYNAME= - basecli keys new $MYNAME - basecli keys list + gaiacli keys new $MYNAME + gaiacli keys list MYADDR= @@ -60,11 +60,11 @@ The genesis file should look like this: **Note:** We need to change the denomination of token from default to ``steak`` in the genesis file. -Then, recover the genesis account with ``basecli``: +Then, recover the genesis account with ``gaiacli``: :: - basecli keys add --recover + gaiacli keys add --recover By now, you have set up the first node. This is great! @@ -120,7 +120,7 @@ Nice. We can also lookup the validator set: :: - basecli validatorset + gaiacli validatorset There is only **one** validator now. Let's add another one! @@ -128,19 +128,19 @@ First, we need to create a new account: :: - basecli keys new + gaiacli keys new Check that we now have two accounts: :: - basecli keys list + gaiacli keys list Then, we try to transfer some ``steak`` to another account: :: - basecli send --amount=1000steak --to=$MYADDR2 --name=$NAME --chain-id= --node=tcp://localhost:46657 --sequence=0 + gaiacli send --amount=1000steak --to=$MYADDR2 --name=$NAME --chain-id= --node=tcp://localhost:46657 --sequence=0 **Note:** We need to be careful with the ``chain-id`` and ``sequence`` @@ -148,7 +148,7 @@ Check the balance & sequence with: :: - basecli account $MYADDR + gaiacli account $MYADDR We can see the balance of ``$MYADDR2`` is 1000 now. @@ -164,19 +164,19 @@ Ok, now we can bond some coins to that pubkey: :: - basecli bond --stake=1steak --validator= --sequence=0 --chain-id= --name=test + gaiacli bond --stake=1steak --validator= --sequence=0 --chain-id= --name=test Nice. We can see there are now two validators: :: - basecli validatorset + gaiacli validatorset Check the balance of ``$MYADDR2`` to see the difference: it has 1 less ``steak``! :: - basecli account $MYADDR2 + gaiacli account $MYADDR2 To confirm for certain the new validator is active, check tendermint: @@ -188,6 +188,6 @@ Finally, to relinquish all your power, unbond some coins. You should see your Vo :: - basecli unbond --sequence=# --chain-id= --name=test + gaiacli unbond --sequence=# --chain-id= --name=test That's it! From 57b150960c226eaee761720cdd5bc14149ee795c Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Thu, 19 Apr 2018 12:25:00 -0400 Subject: [PATCH 54/71] docs: add key generation pseudo code --- docs/index.rst | 3 ++- docs/sdk/key-management.rst | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 docs/sdk/key-management.rst diff --git a/docs/index.rst b/docs/index.rst index 1dc8eb35f..66e3f7cb8 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -18,8 +18,9 @@ SDK :maxdepth: 1 sdk/install.rst + sdk/key-management.rst .. sdk/overview.rst # needs to be updated -.. old/glossary.rst # not completely up to date but has good content +.. old/glossary.rst # not completely up to date but has good content .. Basecoin .. -------- diff --git a/docs/sdk/key-management.rst b/docs/sdk/key-management.rst new file mode 100644 index 000000000..d2b657729 --- /dev/null +++ b/docs/sdk/key-management.rst @@ -0,0 +1,18 @@ +Key Management +============== + +Here we cover many aspects of handling keys within the Cosmos SDK framework. + +Pseudo Code +----------- + +Generating an address for an ed25519 public key (in pseudo code): + +:: + + const TypeDistinguisher = HexToBytes("1624de6220") + + // prepend the TypeDistinguisher as Bytes + SerializedBytes = TypeDistinguisher ++ PubKey.asBytes() + + Address = ripemd160(SerializedBytes) From 5c78c382f9a80910a79076828eb06739d6deef84 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 19 Apr 2018 13:04:40 -0400 Subject: [PATCH 55/71] stdlib linting --- types/stdlib/stdlib.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/types/stdlib/stdlib.go b/types/stdlib/stdlib.go index dd9f4efad..acb786305 100644 --- a/types/stdlib/stdlib.go +++ b/types/stdlib/stdlib.go @@ -7,7 +7,8 @@ import ( wire "github.com/cosmos/cosmos-sdk/wire" ) -type ListMapper interface { // Solidity list like structure +// Solidity list like structure +type ListMapper interface { Len(sdk.Context) int64 Get(sdk.Context, int64, interface{}) Set(sdk.Context, int64, interface{}) @@ -90,6 +91,7 @@ func (lm listMapper) Iterate(ctx sdk.Context, ptr interface{}, fn func(sdk.Conte } } +// mapper interface for queue type QueueMapper interface { Push(sdk.Context, interface{}) Peek(sdk.Context, interface{}) From e149d27f1c7333df52fb01f0c70700fb91373818 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 19 Apr 2018 13:16:09 -0400 Subject: [PATCH 56/71] lint changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d31ce6cbb..26f9d105a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ FEATURES: * Add FeeHandler to ante handler * Gaia stake commands include, DeclareCandidacy, EditCandidacy, Delegate, Unbond * MountStoreWithDB without providing a custom store works. +* Repo is now lint compliant / GoMetaLinter with tendermint-lint integrated into CI BREAKING CHANGES @@ -17,6 +18,9 @@ BREAKING CHANGES * [store] Add `SubspaceIterator` and `ReverseSubspaceIterator` to `KVStore` interface * [basecoin] NewBasecoinApp takes a `dbm.DB` and uses namespaced DBs for substores * All module keepers now require a codespace, see basecoin or democoin for usage +* Many changes to names throughout + * Type as a prefix naming convention applied (ex. BondMsg -> MsgBond) + * Removed redundancy in names (ex. stake.StakeKeeper -> stake.Keeper) BUG FIXES * Gaia now uses stake, ported from github.com/cosmos/gaia From 566563f666e1cbd4c556aa453edb15c0baaf7c1c Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 19 Apr 2018 13:20:45 -0400 Subject: [PATCH 57/71] ci gometalinter, also add linter failing function to test --- .circleci/config.yml | 5 ++--- x/stake/handler.go | 3 +++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1dc5c1b53..825d5e93f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -32,6 +32,7 @@ jobs: command: | export PATH="$GOBIN:$PATH" go get -u github.com/tendermint/lint/golint + go get -u github.com/alecthomas/gometalinter - run: name: binaries command: | @@ -65,9 +66,7 @@ jobs: name: Lint source command: | export PATH="$GOBIN:$PATH" - for pkg in $(go list github.com/cosmos/cosmos-sdk/... | grep -v /vendor/); do - test -z "$(golint $pkg | tee /dev/stderr)" - done + gometalinter --disable-all --enable='golint' --vendor ./... test_cover: <<: *defaults diff --git a/x/stake/handler.go b/x/stake/handler.go index 84eeca3c4..6bdd4b140 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -48,6 +48,9 @@ func NewEndBlocker(k Keeper) sdk.EndBlocker { //_____________________________________________________________________ +func Bloop() { +} + // InitGenesis - store genesis parameters func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) { k.setPool(ctx, data.Pool) From 2a796b6c7a126aa4020727cf7b85bf06a01ad15d Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 19 Apr 2018 13:23:59 -0400 Subject: [PATCH 58/71] remove test linter fail function --- x/stake/handler.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/x/stake/handler.go b/x/stake/handler.go index 6bdd4b140..84eeca3c4 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -48,9 +48,6 @@ func NewEndBlocker(k Keeper) sdk.EndBlocker { //_____________________________________________________________________ -func Bloop() { -} - // InitGenesis - store genesis parameters func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) { k.setPool(ctx, data.Pool) From ad0c776d943f90e8acd52a7367cc992b98c85ef9 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 19 Apr 2018 15:18:31 -0400 Subject: [PATCH 59/71] show_validator now displays HEX by default, declare-candidacy also takes go-amino encoded --- cmd/gaia/cli_test/cli_test.go | 17 ++----- server/tm_cmds.go | 88 ++++++++++++++++------------------- x/stake/commands/tx.go | 39 +++++----------- 3 files changed, 56 insertions(+), 88 deletions(-) diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 0d9a89578..6bda6894b 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -40,8 +40,8 @@ func TestGaiaCLISend(t *testing.T) { executeWrite(t, "gaiacli keys add foo --recover", pass, masterKey) executeWrite(t, "gaiacli keys add bar", pass) - fooAddr, _ := executeGetAddr(t, "gaiacli keys show foo --output=json") - barAddr, _ := executeGetAddr(t, "gaiacli keys show bar --output=json") + fooAddr, _ := executeGetAddrPK(t, "gaiacli keys show foo --output=json") + barAddr, _ := executeGetAddrPK(t, "gaiacli keys show bar --output=json") fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) assert.Equal(t, int64(100000), fooAcc.GetCoins().AmountOf("fermion")) @@ -71,7 +71,7 @@ func TestGaiaCLIDeclareCandidacy(t *testing.T) { defer cmd.Process.Kill() executeWrite(t, "gaiacli keys add foo --recover", pass, masterKey) - fooAddr, fooPubKey := executeGetAddr(t, "gaiacli keys show foo --output=json") + fooAddr, fooPubKey := executeGetAddrPK(t, "gaiacli keys show foo --output=json") fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooAddr, flags)) assert.Equal(t, int64(100000), fooAcc.GetCoins().AmountOf("fermion")) @@ -91,7 +91,7 @@ func TestGaiaCLIDeclareCandidacy(t *testing.T) { assert.Equal(t, candidate.Address.String(), fooAddr) assert.Equal(t, int64(3), candidate.Assets.Evaluate()) - // TODO figure out why this times out with connection refused errors in go-bash + // TODO timeout issues if not connected to the internet // unbond a single share unbondStr := fmt.Sprintf("gaiacli unbond %v", flags) unbondStr += fmt.Sprintf(" --name=%v", "foo") @@ -146,19 +146,12 @@ func executeInit(t *testing.T, cmdStr string) (masterKey, chainID string) { return } -func executeGetAddr(t *testing.T, cmdStr string) (addr, pubKey string) { +func executeGetAddrPK(t *testing.T, cmdStr string) (addr, pubKey string) { out := tests.ExecuteT(t, cmdStr, 2) var info crkeys.Info keys.UnmarshalJSON([]byte(out), &info) pubKey = hex.EncodeToString(info.PubKey.(crypto.PubKeyEd25519).Bytes()) - - // TODO this is really wierd, also error that not 64 characters! - pubKey = strings.TrimLeft(pubKey, "1624de6220") - pubKey = fmt.Sprintf("%064v", pubKey) - - fmt.Printf("debug pubKey: %v\n", pubKey) addr = info.PubKey.Address().String() - fmt.Printf("debug addr: %v\n", addr) return } diff --git a/server/tm_cmds.go b/server/tm_cmds.go index 67504fa6b..dd826ba8c 100644 --- a/server/tm_cmds.go +++ b/server/tm_cmds.go @@ -1,9 +1,11 @@ package server import ( + "encoding/hex" "fmt" "github.com/spf13/cobra" + "github.com/spf13/viper" tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" "github.com/tendermint/tendermint/p2p" @@ -12,73 +14,63 @@ import ( // ShowNodeIDCmd - ported from Tendermint, dump node ID to stdout func ShowNodeIDCmd(ctx *Context) *cobra.Command { - cmd := showNodeID{ctx} return &cobra.Command{ Use: "show_node_id", Short: "Show this node's ID", - RunE: cmd.run, + RunE: func(cmd *cobra.Command, args []string) error { + cfg := ctx.Config + nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile()) + if err != nil { + return err + } + fmt.Println(nodeKey.ID()) + return nil + }, } } -type showNodeID struct { - context *Context -} - -func (s showNodeID) run(cmd *cobra.Command, args []string) error { - cfg := s.context.Config - nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile()) - if err != nil { - return err - } - fmt.Println(nodeKey.ID()) - return nil -} - -//-------------------------------------------------------------------------------- +//________________________________________________________________________________ // ShowValidator - ported from Tendermint, show this node's validator info func ShowValidatorCmd(ctx *Context) *cobra.Command { - cmd := showValidator{ctx} - return &cobra.Command{ + flagJSON := "json" + cmd := cobra.Command{ Use: "show_validator", Short: "Show this node's validator info", - RunE: cmd.run, + RunE: func(cmd *cobra.Command, args []string) error { + + cfg := ctx.Config + privValidator := pvm.LoadOrGenFilePV(cfg.PrivValidatorFile()) + pubKey := privValidator.PubKey + + if viper.GetBool(flagJSON) { + pubKeyJSONBytes, err := cdc.MarshalJSON(pubKey) + if err != nil { + return err + } + fmt.Println(string(pubKeyJSONBytes)) + return nil + } + pubKeyHex := hex.EncodeToString(pubKey.Bytes()) + fmt.Println(pubKeyHex) + return nil + }, } + cmd.Flags().Bool(flagJSON, false, "get machine parseable output") + return &cmd } -type showValidator struct { - context *Context -} - -func (s showValidator) run(cmd *cobra.Command, args []string) error { - cfg := s.context.Config - privValidator := pvm.LoadOrGenFilePV(cfg.PrivValidatorFile()) - pubKeyJSONBytes, err := cdc.MarshalJSON(privValidator.PubKey) - if err != nil { - return err - } - fmt.Println(string(pubKeyJSONBytes)) - return nil -} - -//------------------------------------------------------------------------------ +//________________________________________________________________________________ // UnsafeResetAllCmd - extension of the tendermint command, resets initialization func UnsafeResetAllCmd(ctx *Context) *cobra.Command { - cmd := resetAll{ctx} return &cobra.Command{ Use: "unsafe_reset_all", Short: "Reset all blockchain data", - RunE: cmd.run, + RunE: func(cmd *cobra.Command, args []string) error { + cfg := ctx.Config + tcmd.ResetAll(cfg.DBDir(), cfg.PrivValidatorFile(), ctx.Logger) + return nil + }, } } - -type resetAll struct { - context *Context -} - -func (r resetAll) run(cmd *cobra.Command, args []string) error { - cfg := r.context.Config - tcmd.ResetAll(cfg.DBDir(), cfg.PrivValidatorFile(), r.context.Logger) - return nil -} diff --git a/x/stake/commands/tx.go b/x/stake/commands/tx.go index e04a81885..69fedba54 100644 --- a/x/stake/commands/tx.go +++ b/x/stake/commands/tx.go @@ -30,10 +30,20 @@ func GetCmdDeclareCandidacy(cdc *wire.Codec) *cobra.Command { if err != nil { return err } - pk, err := GetPubKey(viper.GetString(FlagPubKey)) + + pkStr := viper.GetString(FlagPubKey) + if len(pkStr) == 0 { + return fmt.Errorf("must use --pubkey flag") + } + pkBytes, err := hex.DecodeString(pkStr) if err != nil { return err } + pk, err := crypto.PubKeyFromBytes(pkBytes) + if err != nil { + return err + } + if viper.GetString(FlagMoniker) == "" { return fmt.Errorf("please enter a moniker for the validator-candidate using --moniker") } @@ -187,30 +197,3 @@ func GetCmdUnbond(cdc *wire.Codec) *cobra.Command { cmd.Flags().AddFlagSet(fsCandidate) return cmd } - -//______________________________________________________________________________________ - -// create the pubkey from a pubkey string -// TODO move to a better reusable place -func GetPubKey(pubKeyStr string) (pk crypto.PubKey, err error) { - - if len(pubKeyStr) == 0 { - err = fmt.Errorf("must use --pubkey flag") - return - } - if len(pubKeyStr) != 64 { //if len(pkBytes) != 32 { - err = fmt.Errorf("pubkey must be Ed25519 hex encoded string which is 64 characters, this pubkey is %v characters", len(pubKeyStr)) - return - } - - // TODO: bech32 ... - var pkBytes []byte - pkBytes, err = hex.DecodeString(pubKeyStr) - if err != nil { - return - } - var pkEd crypto.PubKeyEd25519 - copy(pkEd[:], pkBytes[:]) - pk = pkEd - return -} From bce7bf6e79ed8784390f6798cdebec95b66ca8f5 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 19 Apr 2018 16:33:17 -0400 Subject: [PATCH 60/71] rm a couple comments --- server/tm_cmds.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/server/tm_cmds.go b/server/tm_cmds.go index dd826ba8c..648e3d80d 100644 --- a/server/tm_cmds.go +++ b/server/tm_cmds.go @@ -29,8 +29,6 @@ func ShowNodeIDCmd(ctx *Context) *cobra.Command { } } -//________________________________________________________________________________ - // ShowValidator - ported from Tendermint, show this node's validator info func ShowValidatorCmd(ctx *Context) *cobra.Command { flagJSON := "json" @@ -60,8 +58,6 @@ func ShowValidatorCmd(ctx *Context) *cobra.Command { return &cmd } -//________________________________________________________________________________ - // UnsafeResetAllCmd - extension of the tendermint command, resets initialization func UnsafeResetAllCmd(ctx *Context) *cobra.Command { return &cobra.Command{ From 0ea1bc7918a7ef129e6c9b7264074a8b4044531d Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 19 Apr 2018 21:09:48 -0400 Subject: [PATCH 61/71] add prepend bytes comment to pubkey hex string --- x/stake/commands/flags.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/stake/commands/flags.go b/x/stake/commands/flags.go index e5b97d62c..4bafd9c65 100644 --- a/x/stake/commands/flags.go +++ b/x/stake/commands/flags.go @@ -29,7 +29,7 @@ var ( ) func init() { - fsPk.String(FlagPubKey, "", "PubKey of the validator-candidate") + fsPk.String(FlagPubKey, "", "Go-Amino encoded hex PubKey of the validator-candidate. For Ed25519 the go-amino prepend hex is 1624de6220") fsAmount.String(FlagAmount, "1fermion", "Amount of coins to bond") fsShares.String(FlagShares, "", "Amount of shares to unbond, either in decimal or keyword MAX (ex. 1.23456789, 99, MAX)") fsDescription.String(FlagMoniker, "", "validator-candidate name") From ca3d3be3af0459782934cb99b9b639869c27d876 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 20 Apr 2018 12:51:47 -0400 Subject: [PATCH 62/71] better key output --- CHANGELOG.md | 1 + client/keys/utils.go | 70 +++++++++++++++++++++-------------- cmd/gaia/cli_test/cli_test.go | 11 ++---- server/tm_cmds.go | 3 +- 4 files changed, 48 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26f9d105a..e4c141631 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ FEATURES: * Gaia stake commands include, DeclareCandidacy, EditCandidacy, Delegate, Unbond * MountStoreWithDB without providing a custom store works. * Repo is now lint compliant / GoMetaLinter with tendermint-lint integrated into CI +* Better key output, pubkey go-amino hex bytes now output by default BREAKING CHANGES diff --git a/client/keys/utils.go b/client/keys/utils.go index d1b3d3f65..f86389a89 100644 --- a/client/keys/utils.go +++ b/client/keys/utils.go @@ -1,8 +1,11 @@ package keys import ( + "encoding/hex" + "encoding/json" "fmt" "path/filepath" + "strings" "github.com/spf13/viper" @@ -16,20 +19,10 @@ import ( // KeyDBName is the directory under root where we store the keys const KeyDBName = "keys" -var ( - // keybase is used to make GetKeyBase a singleton - keybase keys.Keybase -) +// keybase is used to make GetKeyBase a singleton +var keybase keys.Keybase -// used for outputting keys.Info over REST -type KeyOutput struct { - Name string `json:"name"` - Address string `json:"address"` - // TODO add pubkey? - // Pubkey string `json:"pubkey"` -} - -// GetKeyBase initializes a keybase based on the configuration +// initialize a keybase based on the configuration func GetKeyBase() (keys.Keybase, error) { if keybase == nil { rootDir := viper.GetString(cli.HomeFlag) @@ -47,36 +40,57 @@ func SetKeyBase(kb keys.Keybase) { keybase = kb } +// used for outputting keys.Info over REST +type KeyOutput struct { + Name string `json:"name"` + Address string `json:"address"` + PubKey string `json:"pub_key"` +} + +func NewKeyOutput(info keys.Info) KeyOutput { + return KeyOutput{ + Name: info.Name, + Address: info.PubKey.Address().String(), + PubKey: strings.ToUpper(hex.EncodeToString(info.PubKey.Bytes())), + } +} + +func NewKeyOutputs(infos []keys.Info) []KeyOutput { + kos := make([]KeyOutput, len(infos)) + for i, info := range infos { + kos[i] = NewKeyOutput(info) + } + return kos +} + func printInfo(info keys.Info) { + ko := NewKeyOutput(info) switch viper.Get(cli.OutputFlag) { case "text": - addr := info.PubKey.Address().String() - sep := "\t\t" - if len(info.Name) > 7 { - sep = "\t" - } - fmt.Printf("%s%s%s\n", info.Name, sep, addr) + fmt.Printf("NAME:\tADDRESS:\t\t\t\t\tPUBKEY:\n") + fmt.Printf("%s\t%s\t%s\n", ko.Name, ko.Address, ko.PubKey) case "json": - json, err := MarshalJSON(info) + out, err := json.MarshalIndent(ko, "", "\t") if err != nil { - panic(err) // really shouldn't happen... + panic(err) } - fmt.Println(string(json)) + fmt.Println(string(out)) } } func printInfos(infos []keys.Info) { + kos := NewKeyOutputs(infos) switch viper.Get(cli.OutputFlag) { case "text": - fmt.Println("All keys:") - for _, i := range infos { - printInfo(i) + fmt.Printf("NAME:\tADDRESS:\t\t\t\t\tPUBKEY:\n") + for _, ko := range kos { + fmt.Printf("%s\t%s\t%s\n", ko.Name, ko.Address, ko.PubKey) } case "json": - json, err := MarshalJSON(infos) + out, err := json.MarshalIndent(kos, "", "\t") if err != nil { - panic(err) // really shouldn't happen... + panic(err) } - fmt.Println(string(json)) + fmt.Println(string(out)) } } diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 6bda6894b..827c7116b 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -1,7 +1,6 @@ package clitest import ( - "encoding/hex" "encoding/json" "fmt" "strings" @@ -17,8 +16,6 @@ import ( "github.com/cosmos/cosmos-sdk/tests" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/stake" - crypto "github.com/tendermint/go-crypto" - crkeys "github.com/tendermint/go-crypto/keys" ) func TestGaiaCLISend(t *testing.T) { @@ -148,11 +145,9 @@ func executeInit(t *testing.T, cmdStr string) (masterKey, chainID string) { func executeGetAddrPK(t *testing.T, cmdStr string) (addr, pubKey string) { out := tests.ExecuteT(t, cmdStr, 2) - var info crkeys.Info - keys.UnmarshalJSON([]byte(out), &info) - pubKey = hex.EncodeToString(info.PubKey.(crypto.PubKeyEd25519).Bytes()) - addr = info.PubKey.Address().String() - return + var ko keys.KeyOutput + keys.UnmarshalJSON([]byte(out), &ko) + return ko.Address, ko.PubKey } func executeGetAccount(t *testing.T, cmdStr string) auth.BaseAccount { diff --git a/server/tm_cmds.go b/server/tm_cmds.go index 648e3d80d..73dca6651 100644 --- a/server/tm_cmds.go +++ b/server/tm_cmds.go @@ -3,6 +3,7 @@ package server import ( "encoding/hex" "fmt" + "strings" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -49,7 +50,7 @@ func ShowValidatorCmd(ctx *Context) *cobra.Command { fmt.Println(string(pubKeyJSONBytes)) return nil } - pubKeyHex := hex.EncodeToString(pubKey.Bytes()) + pubKeyHex := strings.ToUpper(hex.EncodeToString(pubKey.Bytes())) fmt.Println(pubKeyHex) return nil }, From 3e7481d00fce7cd13faef6241c0e41e2744d3540 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 20 Apr 2018 13:14:01 -0400 Subject: [PATCH 63/71] updated docs for new key work updated docs for new key work --- client/keys/README.md => docs/old/keys.md | 0 docs/staking/intro.rst | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename client/keys/README.md => docs/old/keys.md (100%) diff --git a/client/keys/README.md b/docs/old/keys.md similarity index 100% rename from client/keys/README.md rename to docs/old/keys.md diff --git a/docs/staking/intro.rst b/docs/staking/intro.rst index 68032c536..961136894 100644 --- a/docs/staking/intro.rst +++ b/docs/staking/intro.rst @@ -56,8 +56,8 @@ which will give you three prompts: create a password and copy in your seed phrase. The name and address of the key will be output: :: - - alice 67997DD03D527EB439B7193F2B813B05B219CC02 + NAME: ADDRESS: PUBKEY: + alice 67997DD03D527EB439B7193F2B813B05B219CC02 1624DE6220BB89786C1D597050438C728202436552C6226AB67453CDB2A4D2703402FB52B6 You can see all available keys with: From fbfec1c9cfaa602812055c445263144674d4f453 Mon Sep 17 00:00:00 2001 From: Adrian Brink Date: Sun, 8 Apr 2018 23:13:49 +0800 Subject: [PATCH 64/71] Start prep for IBC standard for Ethereum community --- docs/spec/ibc/ibc.md | 26 ++++++++++++++++++++------ x/ibc/commands/relay.go | 6 +++--- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/docs/spec/ibc/ibc.md b/docs/spec/ibc/ibc.md index dedbdc301..e3f6090f6 100644 --- a/docs/spec/ibc/ibc.md +++ b/docs/spec/ibc/ibc.md @@ -1,10 +1,17 @@ # IBC Specification -IBC(Inter-Blockchain Communication) protocol is used by multiple zones on Cosmos. Using IBC, the zones can send coins or arbitrary data to other zones. +The IBC (Inter Blockchain Communication) protocol specifies how tokens, +non-fungible assets and complex objects can be moved securely between different +zones (independent blockchains). IBC is conceptually similar to TCP/IP in the +sense that anyone can implement it in order to be able to establish IBC +connections with willing clients. + ## Terms -How IBC module treats incoming IBC packets is simillar with how BaseApp treats incoming transactions. Therefore, the components of IBC module have their corresponding pair in BaseApp. +How IBC module treats incoming IBC packets is similar to how BaseApp treats +incoming transactions. Therefore, the components of IBC module have their +corresponding pair in BaseApp. | BaseApp Terms | IBC Terms | | ------------- | ---------- | @@ -12,20 +19,27 @@ How IBC module treats incoming IBC packets is simillar with how BaseApp treats i | Tx | Packet | | Msg | Payload | + ## MVP Specifications ### [MVP1](./mvp1.md) -MVP1 will contain the basic functionalities, including packet generation and packet receivement. There will be no security check for incoming packets. +MVP1 will contain the basic functionalities, including packet generation and +incoming packet processing. There will be no security check for incoming +packets. ### [MVP2](./mvp2.md) -IBC module will be more modular in MVP2. Indivisual modules can register custom handlers to IBC module. +The IBC module will be more modular in MVP2. Individual modules can register +custom handlers on the IBC module. ### [MVP3](./mvp3.md) -Light client verification is added to verify the message from the other chain. Registering chains with their ROT(Root Of Trust) is needed. +Light client verification is added to verify an IBC packet from another chain. +Registering chains with their RoT(Root of Trust) is added as well. ### [MVP4](./mvp4.md) -ACK verification / timeout handler helper functions and messaging queue are implemented to make it failsafe. Callbacks will be registered to the dispatcher to handle failure when they register handlers. +ACK verification / timeout handler helper functions and messaging queues are +implemented to make it safe. Callbacks will be registered to the dispatcher to +handle failure when they register handlers. diff --git a/x/ibc/commands/relay.go b/x/ibc/commands/relay.go index d772735bb..6e4254926 100644 --- a/x/ibc/commands/relay.go +++ b/x/ibc/commands/relay.go @@ -10,10 +10,8 @@ import ( "github.com/tendermint/tmlibs/log" "github.com/cosmos/cosmos-sdk/client/context" - sdk "github.com/cosmos/cosmos-sdk/types" wire "github.com/cosmos/cosmos-sdk/wire" - authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands" "github.com/cosmos/cosmos-sdk/x/ibc" ) @@ -84,7 +82,9 @@ func (c relayCommander) runIBCRelay(cmd *cobra.Command, args []string) { c.loop(fromChainID, fromChainNode, toChainID, toChainNode) } -func (c relayCommander) loop(fromChainID, fromChainNode, toChainID, toChainNode string) { +func (c relayCommander) loop(fromChainID, fromChainNode, toChainID, + toChainNode string) { + ctx := context.NewCoreContextFromViper() // get password passphrase, err := ctx.GetPassphraseFromStdin(ctx.FromAddressName) From b500cfcf44cf10c940643001beacd0f6413b4836 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Sun, 22 Apr 2018 14:47:12 -0700 Subject: [PATCH 65/71] added to Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index daa0361fc..4381eea82 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ PACKAGES=$(shell go list ./... | grep -v '/vendor/') COMMIT_HASH := $(shell git rev-parse --short HEAD) BUILD_FLAGS = -ldflags "-X github.com/cosmos/cosmos-sdk/version.GitCommit=${COMMIT_HASH}" -all: check_tools get_vendor_deps build build_examples test +all: check_tools get_vendor_deps build build_examples install install_examples test ######################################## ### CI From 016a1c8ec9adebc2fbc9dc87fc7c84943001a882 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Sun, 22 Apr 2018 23:36:15 -0700 Subject: [PATCH 66/71] removed seal --- cmd/gaia/app/app.go | 2 +- examples/basecoin/app/app.go | 2 +- examples/democoin/app/app.go | 2 +- x/auth/mapper.go | 29 ----------------------------- x/auth/mapper_test.go | 14 -------------- x/stake/test_common.go | 2 +- 6 files changed, 4 insertions(+), 47 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index e780c08bf..fd981a3b5 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -58,7 +58,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp { app.cdc, app.keyMain, // target store &auth.BaseAccount{}, // prototype - ).Seal() + ) // add handlers app.coinKeeper = bank.NewKeeper(app.accountMapper) diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index e9f5b6e5a..b02f21669 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -61,7 +61,7 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp { cdc, app.capKeyMainStore, // target store &types.AppAccount{}, // prototype - ).Seal() + ) // Add handlers. coinKeeper := bank.NewKeeper(app.accountMapper) diff --git a/examples/democoin/app/app.go b/examples/democoin/app/app.go index 290a04d66..b70f51b5c 100644 --- a/examples/democoin/app/app.go +++ b/examples/democoin/app/app.go @@ -66,7 +66,7 @@ func NewDemocoinApp(logger log.Logger, db dbm.DB) *DemocoinApp { cdc, app.capKeyMainStore, // target store &types.AppAccount{}, // prototype - ).Seal() + ) // Add handlers. coinKeeper := bank.NewKeeper(app.accountMapper) diff --git a/x/auth/mapper.go b/x/auth/mapper.go index ed69034be..b815fada7 100644 --- a/x/auth/mapper.go +++ b/x/auth/mapper.go @@ -9,7 +9,6 @@ import ( ) var _ sdk.AccountMapper = (*accountMapper)(nil) -var _ sdk.AccountMapper = (*sealedAccountMapper)(nil) // Implements sdk.AccountMapper. // This AccountMapper encodes/decodes accounts using the @@ -37,21 +36,6 @@ func NewAccountMapper(cdc *wire.Codec, key sdk.StoreKey, proto sdk.Account) acco } } -// Returns the go-amino codec. You may need to register interfaces -// and concrete types here, if your app's sdk.Account -// implementation includes interface fields. -// NOTE: It is not secure to expose the codec, so check out -// .Seal(). -func (am accountMapper) WireCodec() *wire.Codec { - return am.cdc -} - -// Returns a "sealed" accountMapper. -// The codec is not accessible from a sealedAccountMapper. -func (am accountMapper) Seal() sealedAccountMapper { - return sealedAccountMapper{am} -} - // Implements sdk.AccountMapper. func (am accountMapper) NewAccountWithAddress(ctx sdk.Context, addr sdk.Address) sdk.Account { acc := am.clonePrototype() @@ -78,19 +62,6 @@ func (am accountMapper) SetAccount(ctx sdk.Context, acc sdk.Account) { store.Set(addr, bz) } -//---------------------------------------- -// sealedAccountMapper - -type sealedAccountMapper struct { - accountMapper -} - -// There's no way for external modules to mutate the -// sam.accountMapper.cdc from here, even with reflection. -func (sam sealedAccountMapper) WireCodec() *wire.Codec { - panic("accountMapper is sealed") -} - //---------------------------------------- // misc. diff --git a/x/auth/mapper_test.go b/x/auth/mapper_test.go index 030207db2..2912ddde8 100644 --- a/x/auth/mapper_test.go +++ b/x/auth/mapper_test.go @@ -57,17 +57,3 @@ func TestAccountMapperGetSet(t *testing.T) { assert.NotNil(t, acc) assert.Equal(t, newSequence, acc.GetSequence()) } - -func TestAccountMapperSealed(t *testing.T) { - _, capKey := setupMultiStore() - cdc := wire.NewCodec() - RegisterBaseAccount(cdc) - - // normal mapper exposes the wire codec - mapper := NewAccountMapper(cdc, capKey, &BaseAccount{}) - assert.NotNil(t, mapper.WireCodec()) - - // seal mapper, should panic when we try to get the codec - mapperSealed := mapper.Seal() - assert.Panics(t, func() { mapperSealed.WireCodec() }) -} diff --git a/x/stake/test_common.go b/x/stake/test_common.go index 9d7b13e7c..4a36feb95 100644 --- a/x/stake/test_common.go +++ b/x/stake/test_common.go @@ -138,7 +138,7 @@ func createTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context cdc, // amino codec keyMain, // target store &auth.BaseAccount{}, // prototype - ).Seal() + ) ck := bank.NewKeeper(accountMapper) keeper := NewKeeper(cdc, keyStake, ck, DefaultCodespace) keeper.setPool(ctx, initialPool()) From b7c6713c5c51938768c349f8c66c75c6bd563891 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Sun, 22 Apr 2018 23:40:43 -0700 Subject: [PATCH 67/71] updated Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4c141631..285c7ae8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ BREAKING CHANGES * Many changes to names throughout * Type as a prefix naming convention applied (ex. BondMsg -> MsgBond) * Removed redundancy in names (ex. stake.StakeKeeper -> stake.Keeper) +* Removed SealedAccountMapper BUG FIXES * Gaia now uses stake, ported from github.com/cosmos/gaia From 2672f4a1bbc4a8358dd595b62ccb9c42b5fac12a Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 23 Apr 2018 17:30:54 +0200 Subject: [PATCH 68/71] Add delegator bond query API endpoint --- x/stake/rest/query.go | 79 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 x/stake/rest/query.go diff --git a/x/stake/rest/query.go b/x/stake/rest/query.go new file mode 100644 index 000000000..240f68d96 --- /dev/null +++ b/x/stake/rest/query.go @@ -0,0 +1,79 @@ +package rest + +import ( + "encoding/hex" + "fmt" + "net/http" + + "github.com/gorilla/mux" + "github.com/tendermint/go-crypto/keys" + + "github.com/cosmos/cosmos-sdk/client/context" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/wire" + "github.com/cosmos/cosmos-sdk/x/stake" +) + +// RegisterRoutes - Central function to define routes that get registered by the main application +func RegisterRoutes(r *mux.Router, cdc *wire.Codec, kb keys.Keybase) { + r.HandleFunc("/stake/{delegator}/bonding_status/{candidate}", BondingStatusHandler("stake", cdc, kb)).Methods("GET") +} + +// BondingStatusHandler - http request handler to query delegator bonding status +func BondingStatusHandler(storeName string, cdc *wire.Codec, kb keys.Keybase) func(http.ResponseWriter, *http.Request) { + ctx := context.NewCoreContextFromViper() + return func(w http.ResponseWriter, r *http.Request) { + // read parameters + vars := mux.Vars(r) + delegator := vars["delegator"] + validator := vars["validator"] + + bz, err := hex.DecodeString(delegator) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + delegatorAddr := sdk.Address(bz) + + bz, err = hex.DecodeString(validator) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + candidateAddr := sdk.Address(bz) + + key := stake.GetDelegatorBondKey(delegatorAddr, candidateAddr, cdc) + + res, err := ctx.Query(key, storeName) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(fmt.Sprintf("Couldn't query bond. Error: %s", err.Error()))) + return + } + + // the query will return empty if there is no data for this bond + if len(res) == 0 { + w.WriteHeader(http.StatusNoContent) + return + } + + var bond stake.DelegatorBond + err = cdc.UnmarshalBinary(res, &bond) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(fmt.Sprintf("Couldn't decode bond. Error: %s", err.Error()))) + return + } + + output, err := cdc.MarshalJSON(bond) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + w.Write(output) + } +} From 91b1ee393ce55550757d546dd3750908553ee37a Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 23 Apr 2018 18:17:21 +0200 Subject: [PATCH 69/71] Add ViewSlashKeeper --- x/stake/keeper.go | 2 +- x/stake/view_slash_keeper.go | 29 ++++++++++ x/stake/view_slash_keeper_test.go | 93 +++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 x/stake/view_slash_keeper.go create mode 100644 x/stake/view_slash_keeper_test.go diff --git a/x/stake/keeper.go b/x/stake/keeper.go index 8bfefef84..f1b436314 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -354,7 +354,7 @@ func (k Keeper) clearAccUpdateValidators(ctx sdk.Context) { //_____________________________________________________________________ -// load a delegator bong +// load a delegator bond func (k Keeper) GetDelegatorBond(ctx sdk.Context, delegatorAddr, candidateAddr sdk.Address) (bond DelegatorBond, found bool) { diff --git a/x/stake/view_slash_keeper.go b/x/stake/view_slash_keeper.go new file mode 100644 index 000000000..375c7323b --- /dev/null +++ b/x/stake/view_slash_keeper.go @@ -0,0 +1,29 @@ +package stake + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// keeper to view information & slash validators +// will be used by governance module +type ViewSlashKeeper struct { + keeper Keeper +} + +// NewViewSlashKeeper creates a keeper restricted to +// viewing information & slashing validators +func NewViewSlashKeeper(k Keeper) ViewSlashKeeper { + return ViewSlashKeeper{k} +} + +// load a delegator bond +func (v ViewSlashKeeper) GetDelegatorBond(ctx sdk.Context, + delegatorAddr, candidateAddr sdk.Address) (bond DelegatorBond, found bool) { + return v.keeper.GetDelegatorBond(ctx, delegatorAddr, candidateAddr) +} + +// load n delegator bonds +func (v ViewSlashKeeper) GetDelegatorBonds(ctx sdk.Context, + delegator sdk.Address, maxRetrieve int16) (bonds []DelegatorBond) { + return v.keeper.GetDelegatorBonds(ctx, delegator, maxRetrieve) +} diff --git a/x/stake/view_slash_keeper_test.go b/x/stake/view_slash_keeper_test.go new file mode 100644 index 000000000..2e0e70d3b --- /dev/null +++ b/x/stake/view_slash_keeper_test.go @@ -0,0 +1,93 @@ +package stake + +import ( + "bytes" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// tests GetDelegatorBond, GetDelegatorBonds +func TestViewSlashBond(t *testing.T) { + ctx, _, keeper := createTestInput(t, false, 0) + + //construct the candidates + amts := []int64{9, 8, 7} + var candidates [3]Candidate + for i, amt := range amts { + candidates[i] = Candidate{ + Address: addrVals[i], + PubKey: pks[i], + Assets: sdk.NewRat(amt), + Liabilities: sdk.NewRat(amt), + } + } + + // first add a candidates[0] to delegate too + keeper.setCandidate(ctx, candidates[0]) + + bond1to1 := DelegatorBond{ + DelegatorAddr: addrDels[0], + CandidateAddr: addrVals[0], + Shares: sdk.NewRat(9), + } + + viewSlashKeeper := NewViewSlashKeeper(keeper) + + bondsEqual := func(b1, b2 DelegatorBond) bool { + return bytes.Equal(b1.DelegatorAddr, b2.DelegatorAddr) && + bytes.Equal(b1.CandidateAddr, b2.CandidateAddr) && + b1.Shares == b2.Shares + } + + // check the empty keeper first + _, found := viewSlashKeeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0]) + assert.False(t, found) + + // set and retrieve a record + keeper.setDelegatorBond(ctx, bond1to1) + resBond, found := viewSlashKeeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0]) + assert.True(t, found) + assert.True(t, bondsEqual(bond1to1, resBond)) + + // modify a records, save, and retrieve + bond1to1.Shares = sdk.NewRat(99) + keeper.setDelegatorBond(ctx, bond1to1) + resBond, found = viewSlashKeeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0]) + assert.True(t, found) + assert.True(t, bondsEqual(bond1to1, resBond)) + + // add some more records + keeper.setCandidate(ctx, candidates[1]) + keeper.setCandidate(ctx, candidates[2]) + bond1to2 := DelegatorBond{addrDels[0], addrVals[1], sdk.NewRat(9)} + bond1to3 := DelegatorBond{addrDels[0], addrVals[2], sdk.NewRat(9)} + bond2to1 := DelegatorBond{addrDels[1], addrVals[0], sdk.NewRat(9)} + bond2to2 := DelegatorBond{addrDels[1], addrVals[1], sdk.NewRat(9)} + bond2to3 := DelegatorBond{addrDels[1], addrVals[2], sdk.NewRat(9)} + keeper.setDelegatorBond(ctx, bond1to2) + keeper.setDelegatorBond(ctx, bond1to3) + keeper.setDelegatorBond(ctx, bond2to1) + keeper.setDelegatorBond(ctx, bond2to2) + keeper.setDelegatorBond(ctx, bond2to3) + + // test all bond retrieve capabilities + resBonds := viewSlashKeeper.GetDelegatorBonds(ctx, addrDels[0], 5) + require.Equal(t, 3, len(resBonds)) + assert.True(t, bondsEqual(bond1to1, resBonds[0])) + assert.True(t, bondsEqual(bond1to2, resBonds[1])) + assert.True(t, bondsEqual(bond1to3, resBonds[2])) + resBonds = viewSlashKeeper.GetDelegatorBonds(ctx, addrDels[0], 3) + require.Equal(t, 3, len(resBonds)) + resBonds = viewSlashKeeper.GetDelegatorBonds(ctx, addrDels[0], 2) + require.Equal(t, 2, len(resBonds)) + resBonds = viewSlashKeeper.GetDelegatorBonds(ctx, addrDels[1], 5) + require.Equal(t, 3, len(resBonds)) + assert.True(t, bondsEqual(bond2to1, resBonds[0])) + assert.True(t, bondsEqual(bond2to2, resBonds[1])) + assert.True(t, bondsEqual(bond2to3, resBonds[2])) + +} From 5b1e2a3786df99ad39d98e52143e418042335456 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 23 Apr 2018 18:32:55 +0200 Subject: [PATCH 70/71] Add Height field to DelegatorBond, update appropriately --- x/stake/handler.go | 5 +++++ x/stake/keeper_test.go | 20 +++++++++++++++----- x/stake/types.go | 1 + x/stake/view_slash_keeper_test.go | 11 ++++++----- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/x/stake/handler.go b/x/stake/handler.go index 84eeca3c4..d9f718fe5 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -158,6 +158,9 @@ func delegate(ctx sdk.Context, k Keeper, delegatorAddr sdk.Address, pool, candidate, newShares := pool.candidateAddTokens(candidate, bondAmt.Amount) bond.Shares = bond.Shares.Add(newShares) + // Update bond height + bond.Height = ctx.BlockHeight() + k.setDelegatorBond(ctx, bond) k.setCandidate(ctx, candidate) k.setPool(ctx, pool) @@ -226,6 +229,8 @@ func handleMsgUnbond(ctx sdk.Context, msg MsgUnbond, k Keeper) sdk.Result { k.removeDelegatorBond(ctx, bond) } else { + // Update bond height + bond.Height = ctx.BlockHeight() k.setDelegatorBond(ctx, bond) } diff --git a/x/stake/keeper_test.go b/x/stake/keeper_test.go index c42f7182b..03431a403 100644 --- a/x/stake/keeper_test.go +++ b/x/stake/keeper_test.go @@ -122,6 +122,7 @@ func TestBond(t *testing.T) { bondsEqual := func(b1, b2 DelegatorBond) bool { return bytes.Equal(b1.DelegatorAddr, b2.DelegatorAddr) && bytes.Equal(b1.CandidateAddr, b2.CandidateAddr) && + b1.Height == b2.Height && b1.Shares == b2.Shares } @@ -142,14 +143,23 @@ func TestBond(t *testing.T) { assert.True(t, found) assert.True(t, bondsEqual(bond1to1, resBond)) + // test height + ctx = ctx.WithBlockHeight(10) + keeper.setDelegatorBond(ctx, bond1to1) + resBond, found = keeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0]) + assert.True(t, found) + assert.Equal(t, resBond.Height, 10) + ctx = ctx.WithBlockHeight(0) + keeper.setDelegatorBond(ctx, bond1to1) + // add some more records keeper.setCandidate(ctx, candidates[1]) keeper.setCandidate(ctx, candidates[2]) - bond1to2 := DelegatorBond{addrDels[0], addrVals[1], sdk.NewRat(9)} - bond1to3 := DelegatorBond{addrDels[0], addrVals[2], sdk.NewRat(9)} - bond2to1 := DelegatorBond{addrDels[1], addrVals[0], sdk.NewRat(9)} - bond2to2 := DelegatorBond{addrDels[1], addrVals[1], sdk.NewRat(9)} - bond2to3 := DelegatorBond{addrDels[1], addrVals[2], sdk.NewRat(9)} + bond1to2 := DelegatorBond{addrDels[0], addrVals[1], sdk.NewRat(9), 0} + bond1to3 := DelegatorBond{addrDels[0], addrVals[2], sdk.NewRat(9), 1} + bond2to1 := DelegatorBond{addrDels[1], addrVals[0], sdk.NewRat(9), 2} + bond2to2 := DelegatorBond{addrDels[1], addrVals[1], sdk.NewRat(9), 3} + bond2to3 := DelegatorBond{addrDels[1], addrVals[2], sdk.NewRat(9), 4} keeper.setDelegatorBond(ctx, bond1to2) keeper.setDelegatorBond(ctx, bond1to3) keeper.setDelegatorBond(ctx, bond2to1) diff --git a/x/stake/types.go b/x/stake/types.go index be48afe3e..8f9e87cbb 100644 --- a/x/stake/types.go +++ b/x/stake/types.go @@ -164,4 +164,5 @@ type DelegatorBond struct { DelegatorAddr sdk.Address `json:"delegator_addr"` CandidateAddr sdk.Address `json:"candidate_addr"` Shares sdk.Rat `json:"shares"` + Height int64 `json:"height"` // Last height bond updated } diff --git a/x/stake/view_slash_keeper_test.go b/x/stake/view_slash_keeper_test.go index 2e0e70d3b..a8b0e1071 100644 --- a/x/stake/view_slash_keeper_test.go +++ b/x/stake/view_slash_keeper_test.go @@ -40,6 +40,7 @@ func TestViewSlashBond(t *testing.T) { bondsEqual := func(b1, b2 DelegatorBond) bool { return bytes.Equal(b1.DelegatorAddr, b2.DelegatorAddr) && bytes.Equal(b1.CandidateAddr, b2.CandidateAddr) && + b1.Height == b2.Height && b1.Shares == b2.Shares } @@ -63,11 +64,11 @@ func TestViewSlashBond(t *testing.T) { // add some more records keeper.setCandidate(ctx, candidates[1]) keeper.setCandidate(ctx, candidates[2]) - bond1to2 := DelegatorBond{addrDels[0], addrVals[1], sdk.NewRat(9)} - bond1to3 := DelegatorBond{addrDels[0], addrVals[2], sdk.NewRat(9)} - bond2to1 := DelegatorBond{addrDels[1], addrVals[0], sdk.NewRat(9)} - bond2to2 := DelegatorBond{addrDels[1], addrVals[1], sdk.NewRat(9)} - bond2to3 := DelegatorBond{addrDels[1], addrVals[2], sdk.NewRat(9)} + bond1to2 := DelegatorBond{addrDels[0], addrVals[1], sdk.NewRat(9), 0} + bond1to3 := DelegatorBond{addrDels[0], addrVals[2], sdk.NewRat(9), 1} + bond2to1 := DelegatorBond{addrDels[1], addrVals[0], sdk.NewRat(9), 2} + bond2to2 := DelegatorBond{addrDels[1], addrVals[1], sdk.NewRat(9), 3} + bond2to3 := DelegatorBond{addrDels[1], addrVals[2], sdk.NewRat(9), 4} keeper.setDelegatorBond(ctx, bond1to2) keeper.setDelegatorBond(ctx, bond1to3) keeper.setDelegatorBond(ctx, bond2to1) From 86b79b9c842a9062cf5da17ccde5f01e482dd305 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 23 Apr 2018 18:41:36 +0200 Subject: [PATCH 71/71] Fix testcases & update changelog --- CHANGELOG.md | 1 + x/stake/handler_test.go | 5 +++++ x/stake/keeper_test.go | 9 --------- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4c141631..4de7af20a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ BREAKING CHANGES * Remove go-wire, use go-amino * Gaia simple-staking bond and unbond functions replaced +* [stake] Delegator bonds now store the height at which they were updated * [store] Add `SubspaceIterator` and `ReverseSubspaceIterator` to `KVStore` interface * [basecoin] NewBasecoinApp takes a `dbm.DB` and uses namespaced DBs for substores * All module keepers now require a codespace, see basecoin or democoin for usage diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index 538c664e9..1240e4e6c 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -76,7 +76,10 @@ func TestIncrementsMsgDelegate(t *testing.T) { // just send the same msgbond multiple times msgDelegate := newTestMsgDelegate(delegatorAddr, candidateAddr, bondAmount) + for i := 0; i < 5; i++ { + ctx = ctx.WithBlockHeight(int64(i)) + got := handleMsgDelegate(ctx, msgDelegate, keeper) require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) @@ -90,6 +93,8 @@ func TestIncrementsMsgDelegate(t *testing.T) { expLiabilities := int64(i+2) * bondAmount // (1 self delegation) expDelegatorAcc := initBond - expBond + require.Equal(t, bond.Height, int64(i), "Incorrect bond height") + gotBond := bond.Shares.Evaluate() gotLiabilities := candidate.Liabilities.Evaluate() gotDelegatorAcc := accMapper.GetAccount(ctx, delegatorAddr).GetCoins().AmountOf(params.BondDenom) diff --git a/x/stake/keeper_test.go b/x/stake/keeper_test.go index 03431a403..e3edfbf9e 100644 --- a/x/stake/keeper_test.go +++ b/x/stake/keeper_test.go @@ -143,15 +143,6 @@ func TestBond(t *testing.T) { assert.True(t, found) assert.True(t, bondsEqual(bond1to1, resBond)) - // test height - ctx = ctx.WithBlockHeight(10) - keeper.setDelegatorBond(ctx, bond1to1) - resBond, found = keeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0]) - assert.True(t, found) - assert.Equal(t, resBond.Height, 10) - ctx = ctx.WithBlockHeight(0) - keeper.setDelegatorBond(ctx, bond1to1) - // add some more records keeper.setCandidate(ctx, candidates[1]) keeper.setCandidate(ctx, candidates[2])