From 0be655b122e0505fd8353a8f0988618d6bf5ae56 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 6 Apr 2018 18:08:29 +0200 Subject: [PATCH 01/14] Automatically determine chainID, throw error if not provided (closes #810) --- client/context/viper.go | 22 +++++++++++++++++++++- client/core/core.go | 3 +++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/client/context/viper.go b/client/context/viper.go index 750a37c616..4264776df0 100644 --- a/client/context/viper.go +++ b/client/context/viper.go @@ -1,9 +1,13 @@ package context import ( + "encoding/json" "github.com/spf13/viper" + "io/ioutil" + tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" rpcclient "github.com/tendermint/tendermint/rpc/client" + tmtypes "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/core" @@ -15,8 +19,24 @@ func NewCoreContextFromViper() core.CoreContext { if nodeURI != "" { rpc = rpcclient.NewHTTP(nodeURI, "/websocket") } + chainID := viper.GetString(client.FlagChainID) + // if chain ID is not specified manually, read chain ID from genesis file if present + if chainID == "" { + cfg, err := tcmd.ParseConfig() + if err == nil { + genesisFile := cfg.GenesisFile() + bz, err := ioutil.ReadFile(genesisFile) + if err == nil { + var doc tmtypes.GenesisDoc + err = json.Unmarshal(bz, &doc) + if err == nil { + chainID = doc.ChainID + } + } + } + } return core.CoreContext{ - ChainID: viper.GetString(client.FlagChainID), + ChainID: chainID, Height: viper.GetInt64(client.FlagHeight), TrustNode: viper.GetBool(client.FlagTrustNode), FromAddressName: viper.GetString(client.FlagName), diff --git a/client/core/core.go b/client/core/core.go index a5c7b340c7..a39472c040 100644 --- a/client/core/core.go +++ b/client/core/core.go @@ -91,6 +91,9 @@ func (ctx CoreContext) SignAndBuild(name, passphrase string, msg sdk.Msg, cdc *w // build the Sign Messsage from the Standard Message chainID := ctx.ChainID + if chainID == "" { + return nil, errors.Errorf("Chain ID required but not specified") + } sequence := ctx.Sequence signMsg := sdk.StdSignMsg{ ChainID: chainID, From ec98545a1b55bd8b70b9b95c1ead5b345a05b319 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 9 Apr 2018 16:06:24 +0200 Subject: [PATCH 02/14] Default to next sequence number (closes #807) --- client/context/viper.go | 2 ++ client/core/context.go | 14 ++++++++++++++ client/core/core.go | 18 ++++++++++++++++++ x/bank/commands/sendtx.go | 17 ++++++++++++++++- 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/client/context/viper.go b/client/context/viper.go index 4264776df0..9a1cd5d0d4 100644 --- a/client/context/viper.go +++ b/client/context/viper.go @@ -43,5 +43,7 @@ func NewCoreContextFromViper() core.CoreContext { NodeURI: nodeURI, Sequence: viper.GetInt64(client.FlagSequence), Client: rpc, + Decoder: nil, + AccountStore: "main", } } diff --git a/client/core/context.go b/client/core/context.go index 3d7f400a8e..d56af5a816 100644 --- a/client/core/context.go +++ b/client/core/context.go @@ -2,6 +2,8 @@ package core import ( rpcclient "github.com/tendermint/tendermint/rpc/client" + + sdk "github.com/cosmos/cosmos-sdk/types" ) type CoreContext struct { @@ -12,6 +14,8 @@ type CoreContext struct { FromAddressName string Sequence int64 Client rpcclient.Client + Decoder sdk.AccountDecoder + AccountStore string } func (c CoreContext) WithChainID(chainID string) CoreContext { @@ -48,3 +52,13 @@ func (c CoreContext) WithClient(client rpcclient.Client) CoreContext { c.Client = client return c } + +func (c CoreContext) WithDecoder(decoder sdk.AccountDecoder) CoreContext { + c.Decoder = decoder + return c +} + +func (c CoreContext) WithAccountStore(accountStore string) CoreContext { + c.AccountStore = accountStore + return c +} diff --git a/client/core/core.go b/client/core/core.go index a39472c040..e28e6c3928 100644 --- a/client/core/core.go +++ b/client/core/core.go @@ -140,6 +140,24 @@ func (ctx CoreContext) SignBuildBroadcast(name string, msg sdk.Msg, cdc *wire.Co return ctx.BroadcastTx(txBytes) } +func (c CoreContext) NextSequence(address []byte) (int64, error) { + if c.Decoder == nil { + return 0, errors.New("AccountDecoder required but not provided") + } + + res, err := c.Query(address, c.AccountStore) + if err != nil { + return 0, err + } + + account, err := c.Decoder(res) + if err != nil { + panic(err) + } + + return account.GetSequence(), nil +} + // get passphrase from std input func (ctx CoreContext) GetPassphraseFromStdin(name string) (pass string, err error) { buf := client.BufferStdin() diff --git a/x/bank/commands/sendtx.go b/x/bank/commands/sendtx.go index aa0e17a910..17bf268700 100644 --- a/x/bank/commands/sendtx.go +++ b/x/bank/commands/sendtx.go @@ -10,6 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" + authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands" "github.com/cosmos/cosmos-sdk/x/bank" ) @@ -36,7 +37,7 @@ type Commander struct { } func (c Commander) sendTxCmd(cmd *cobra.Command, args []string) error { - ctx := context.NewCoreContextFromViper() + ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(c.Cdc)) // get the from address from, err := ctx.GetFromAddress() @@ -62,6 +63,20 @@ func (c Commander) sendTxCmd(cmd *cobra.Command, args []string) error { // build message msg := BuildMsg(from, to, coins) + // default to next sequence number if none provided + if viper.GetInt64(client.FlagSequence) == 0 { + from, err := ctx.GetFromAddress() + if err != nil { + return err + } + seq, err := ctx.NextSequence(from) + if err != nil { + return err + } + fmt.Printf("Defaulting to next sequence number: %d\n", seq) + ctx = ctx.WithSequence(seq) + } + // build and sign the transaction, then broadcast to Tendermint res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, c.Cdc) if err != nil { From bd626ba94e4f0c113fac29a5702b552a5cf43f34 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 9 Apr 2018 17:59:01 +0200 Subject: [PATCH 03/14] Helper function --- client/context/viper.go | 16 ++++++++++++++++ x/bank/commands/sendtx.go | 14 +++----------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/client/context/viper.go b/client/context/viper.go index 9a1cd5d0d4..115311f11d 100644 --- a/client/context/viper.go +++ b/client/context/viper.go @@ -2,6 +2,7 @@ package context import ( "encoding/json" + "fmt" "github.com/spf13/viper" "io/ioutil" @@ -47,3 +48,18 @@ func NewCoreContextFromViper() core.CoreContext { AccountStore: "main", } } + +// Automatically set sequence number +func AutoSequence(ctx core.CoreContext) (core.CoreContext, error) { + from, err := ctx.GetFromAddress() + if err != nil { + return ctx, err + } + seq, err := ctx.NextSequence(from) + if err != nil { + return ctx, err + } + fmt.Printf("Defaulting to next sequence number: %d\n", seq) + ctx = ctx.WithSequence(seq) + return ctx, nil +} diff --git a/x/bank/commands/sendtx.go b/x/bank/commands/sendtx.go index 17bf268700..a37e969a63 100644 --- a/x/bank/commands/sendtx.go +++ b/x/bank/commands/sendtx.go @@ -64,17 +64,9 @@ func (c Commander) sendTxCmd(cmd *cobra.Command, args []string) error { msg := BuildMsg(from, to, coins) // default to next sequence number if none provided - if viper.GetInt64(client.FlagSequence) == 0 { - from, err := ctx.GetFromAddress() - if err != nil { - return err - } - seq, err := ctx.NextSequence(from) - if err != nil { - return err - } - fmt.Printf("Defaulting to next sequence number: %d\n", seq) - ctx = ctx.WithSequence(seq) + ctx, err = context.AutoSequence(ctx) + if err != nil { + return err } // build and sign the transaction, then broadcast to Tendermint From 7383c99026215ce17409bbd3507a3240df8c329a Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 9 Apr 2018 18:14:33 +0200 Subject: [PATCH 04/14] Add AutoSequence to all transaction-sending commands --- client/context/viper.go | 20 +++++++------ examples/democoin/x/cool/commands/tx.go | 17 ++++++++++-- examples/democoin/x/pow/commands/tx.go | 9 +++++- x/ibc/commands/ibctx.go | 9 +++++- x/simplestake/commands/commands.go | 10 ++++++- x/stake/commands/tx.go | 37 ++++++++++++++++++++++--- 6 files changed, 84 insertions(+), 18 deletions(-) diff --git a/client/context/viper.go b/client/context/viper.go index 115311f11d..acc6b391c7 100644 --- a/client/context/viper.go +++ b/client/context/viper.go @@ -51,15 +51,17 @@ func NewCoreContextFromViper() core.CoreContext { // Automatically set sequence number func AutoSequence(ctx core.CoreContext) (core.CoreContext, error) { - from, err := ctx.GetFromAddress() - if err != nil { - return ctx, err + if !viper.IsSet(client.FlagSequence) { + from, err := ctx.GetFromAddress() + if err != nil { + return ctx, err + } + seq, err := ctx.NextSequence(from) + if err != nil { + return ctx, err + } + fmt.Printf("Defaulting to next sequence number: %d\n", seq) + ctx = ctx.WithSequence(seq) } - seq, err := ctx.NextSequence(from) - if err != nil { - return ctx, err - } - fmt.Printf("Defaulting to next sequence number: %d\n", seq) - ctx = ctx.WithSequence(seq) return ctx, nil } diff --git a/examples/democoin/x/cool/commands/tx.go b/examples/democoin/x/cool/commands/tx.go index 8deaac405d..8ce009f0ff 100644 --- a/examples/democoin/x/cool/commands/tx.go +++ b/examples/democoin/x/cool/commands/tx.go @@ -10,6 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/wire" + authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands" "github.com/cosmos/cosmos-sdk/examples/democoin/x/cool" ) @@ -24,7 +25,7 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command { return errors.New("You must provide an answer") } - ctx := context.NewCoreContextFromViper() + ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) // get the from address from the name flag from, err := ctx.GetFromAddress() @@ -38,6 +39,12 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command { // get account name name := viper.GetString(client.FlagName) + // default to next sequence number if none provided + ctx, err = context.AutoSequence(ctx) + if err != nil { + return err + } + // build and sign the transaction, then broadcast to Tendermint res, err := ctx.SignBuildBroadcast(name, msg, cdc) if err != nil { @@ -60,7 +67,7 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command { return errors.New("You must provide an answer") } - ctx := context.NewCoreContextFromViper() + ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) // get the from address from the name flag from, err := ctx.GetFromAddress() @@ -71,6 +78,12 @@ 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.AutoSequence(ctx) + if err != nil { + return err + } + // create the message msg := cool.NewSetTrendMsg(from, args[0]) diff --git a/examples/democoin/x/pow/commands/tx.go b/examples/democoin/x/pow/commands/tx.go index badbe39092..abd5d27ebf 100644 --- a/examples/democoin/x/pow/commands/tx.go +++ b/examples/democoin/x/pow/commands/tx.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/examples/democoin/x/pow" "github.com/cosmos/cosmos-sdk/wire" + authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands" ) func MineCmd(cdc *wire.Codec) *cobra.Command { @@ -24,7 +25,7 @@ func MineCmd(cdc *wire.Codec) *cobra.Command { // get from address and parse arguments - ctx := context.NewCoreContextFromViper() + ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) from, err := ctx.GetFromAddress() if err != nil { @@ -53,6 +54,12 @@ func MineCmd(cdc *wire.Codec) *cobra.Command { // get account name name := ctx.FromAddressName + // default to next sequence number if none provided + ctx, err = context.AutoSequence(ctx) + if err != nil { + return err + } + // build and sign the transaction, then broadcast to Tendermint res, err := ctx.SignBuildBroadcast(name, msg, cdc) if err != nil { diff --git a/x/ibc/commands/ibctx.go b/x/ibc/commands/ibctx.go index 689a983181..ee0ac02eea 100644 --- a/x/ibc/commands/ibctx.go +++ b/x/ibc/commands/ibctx.go @@ -13,6 +13,7 @@ import ( 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" ) @@ -39,7 +40,7 @@ type sendCommander struct { } func (c sendCommander) sendIBCTransfer(cmd *cobra.Command, args []string) error { - ctx := context.NewCoreContextFromViper() + ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(c.cdc)) // get the from address from, err := ctx.GetFromAddress() @@ -53,6 +54,12 @@ func (c sendCommander) sendIBCTransfer(cmd *cobra.Command, args []string) error return err } + // default to next sequence number if none provided + ctx, err = context.AutoSequence(ctx) + if err != nil { + return err + } + // get password res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, c.cdc) if err != nil { diff --git a/x/simplestake/commands/commands.go b/x/simplestake/commands/commands.go index b2a057beed..0e8a7a9bb4 100644 --- a/x/simplestake/commands/commands.go +++ b/x/simplestake/commands/commands.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" + authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands" "github.com/cosmos/cosmos-sdk/x/simplestake" ) @@ -94,7 +95,14 @@ func (co commander) unbondTxCmd(cmd *cobra.Command, args []string) error { } func (co commander) sendMsg(msg sdk.Msg) error { - ctx := context.NewCoreContextFromViper() + ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(co.cdc)) + + // default to next sequence number if none provided + ctx, err := context.AutoSequence(ctx) + if err != nil { + return err + } + res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, co.cdc) if err != nil { return err diff --git a/x/stake/commands/tx.go b/x/stake/commands/tx.go index d1a399e19c..1b9063a65b 100644 --- a/x/stake/commands/tx.go +++ b/x/stake/commands/tx.go @@ -14,6 +14,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" + authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands" "github.com/cosmos/cosmos-sdk/x/stake" ) @@ -92,7 +93,14 @@ func GetCmdDeclareCandidacy(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgDeclareCandidacy(candidateAddr, pk, amount, description) // build and sign the transaction, then broadcast to Tendermint - ctx := context.NewCoreContextFromViper() + ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) + + // default to next sequence number if none provided + ctx, err = context.AutoSequence(ctx) + if err != nil { + return err + } + res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc) if err != nil { return err @@ -129,7 +137,14 @@ func GetCmdEditCandidacy(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgEditCandidacy(candidateAddr, description) // build and sign the transaction, then broadcast to Tendermint - ctx := context.NewCoreContextFromViper() + ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) + + // default to next sequence number if none provided + ctx, err = context.AutoSequence(ctx) + if err != nil { + return err + } + res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc) if err != nil { return err @@ -165,7 +180,14 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgDelegate(delegatorAddr, candidateAddr, amount) // build and sign the transaction, then broadcast to Tendermint - ctx := context.NewCoreContextFromViper() + ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) + + // default to next sequence number if none provided + ctx, err = context.AutoSequence(ctx) + if err != nil { + return err + } + res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc) if err != nil { return err @@ -212,7 +234,14 @@ func GetCmdUnbond(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgUnbond(delegatorAddr, candidateAddr, sharesStr) // build and sign the transaction, then broadcast to Tendermint - ctx := context.NewCoreContextFromViper() + ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) + + // default to next sequence number if none provided + ctx, err = context.AutoSequence(ctx) + if err != nil { + return err + } + res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, cdc) if err != nil { return err From c7b680a545937ba8b614eb24f09c77f0a33aa06f Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 10 Apr 2018 11:15:34 +0200 Subject: [PATCH 05/14] Address PR comments --- client/context/viper.go | 63 +++++++++++++++---------- client/core/context.go | 9 ++++ examples/democoin/x/cool/commands/tx.go | 4 +- examples/democoin/x/pow/commands/tx.go | 2 +- x/bank/commands/sendtx.go | 2 +- x/ibc/commands/ibctx.go | 2 +- x/simplestake/commands/commands.go | 2 +- x/stake/commands/tx.go | 8 ++-- 8 files changed, 57 insertions(+), 35 deletions(-) diff --git a/client/context/viper.go b/client/context/viper.go index acc6b391c7..193fe9baa6 100644 --- a/client/context/viper.go +++ b/client/context/viper.go @@ -14,6 +14,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/core" ) +// NewCoreContextFromViper - return a new context with parameters from the command line func NewCoreContextFromViper() core.CoreContext { nodeURI := viper.GetString(client.FlagNode) var rpc rpcclient.Client @@ -21,19 +22,11 @@ func NewCoreContextFromViper() core.CoreContext { rpc = rpcclient.NewHTTP(nodeURI, "/websocket") } chainID := viper.GetString(client.FlagChainID) - // if chain ID is not specified manually, read chain ID from genesis file if present + // if chain ID is not specified manually, read default chain ID if chainID == "" { - cfg, err := tcmd.ParseConfig() - if err == nil { - genesisFile := cfg.GenesisFile() - bz, err := ioutil.ReadFile(genesisFile) - if err == nil { - var doc tmtypes.GenesisDoc - err = json.Unmarshal(bz, &doc) - if err == nil { - chainID = doc.ChainID - } - } + def, err := defaultChainID() + if err != nil { + chainID = def } } return core.CoreContext{ @@ -49,19 +42,39 @@ func NewCoreContextFromViper() core.CoreContext { } } -// Automatically set sequence number -func AutoSequence(ctx core.CoreContext) (core.CoreContext, error) { - if !viper.IsSet(client.FlagSequence) { - from, err := ctx.GetFromAddress() - if err != nil { - return ctx, err - } - seq, err := ctx.NextSequence(from) - if err != nil { - return ctx, err - } - fmt.Printf("Defaulting to next sequence number: %d\n", seq) - ctx = ctx.WithSequence(seq) +// read chain ID from genesis file, if present +func defaultChainID() (string, error) { + cfg, err := tcmd.ParseConfig() + if err != nil { + return "", err } + genesisFile := cfg.GenesisFile() + bz, err := ioutil.ReadFile(genesisFile) + if err != nil { + return "", err + } + var doc tmtypes.GenesisDoc + err = json.Unmarshal(bz, &doc) + if err != nil { + return "", err + } + return doc.ChainID, nil +} + +// EnsureSequence - automatically set sequence number if none provided +func EnsureSequence(ctx core.CoreContext) (core.CoreContext, error) { + if viper.IsSet(client.FlagSequence) { + return ctx, nil + } + from, err := ctx.GetFromAddress() + if err != nil { + return ctx, err + } + seq, err := ctx.NextSequence(from) + if err != nil { + return ctx, err + } + fmt.Printf("Defaulting to next sequence number: %d\n", seq) + ctx = ctx.WithSequence(seq) return ctx, nil } diff --git a/client/core/context.go b/client/core/context.go index d56af5a816..34376ece4f 100644 --- a/client/core/context.go +++ b/client/core/context.go @@ -18,46 +18,55 @@ type CoreContext struct { AccountStore string } +// WithChainID - return a copy of the context with an updated chainID func (c CoreContext) WithChainID(chainID string) CoreContext { c.ChainID = chainID return c } +// WithHeight - eturn a copy of the context with an updated height func (c CoreContext) WithHeight(height int64) CoreContext { c.Height = height return c } +// WithTrustNode - return a copy of the context with an updated TrustNode flag func (c CoreContext) WithTrustNode(trustNode bool) CoreContext { c.TrustNode = trustNode return c } +// WithNodeURI - return a copy of the context with an updated node URI func (c CoreContext) WithNodeURI(nodeURI string) CoreContext { c.NodeURI = nodeURI return c } +// WithFromAddressName - return a copy of the context with an updated from address func (c CoreContext) WithFromAddressName(fromAddressName string) CoreContext { c.FromAddressName = fromAddressName return c } +// WithSequence - return a copy of the context with an updated sequence number func (c CoreContext) WithSequence(sequence int64) CoreContext { c.Sequence = sequence return c } +// WithClient - return a copy of the context with an updated RPC client instance func (c CoreContext) WithClient(client rpcclient.Client) CoreContext { c.Client = client return c } +// WithDecoder - return a copy of the context with an updated Decoder func (c CoreContext) WithDecoder(decoder sdk.AccountDecoder) CoreContext { c.Decoder = decoder return c } +// WithAccountStore - return a copy of the context with an updated AccountStore func (c CoreContext) WithAccountStore(accountStore string) CoreContext { c.AccountStore = accountStore return c diff --git a/examples/democoin/x/cool/commands/tx.go b/examples/democoin/x/cool/commands/tx.go index 8ce009f0ff..88c5e4e68a 100644 --- a/examples/democoin/x/cool/commands/tx.go +++ b/examples/democoin/x/cool/commands/tx.go @@ -40,7 +40,7 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command { name := viper.GetString(client.FlagName) // default to next sequence number if none provided - ctx, err = context.AutoSequence(ctx) + ctx, err = context.EnsureSequence(ctx) if err != nil { return err } @@ -79,7 +79,7 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command { name := viper.GetString(client.FlagName) // default to next sequence number if none provided - ctx, err = context.AutoSequence(ctx) + ctx, err = context.EnsureSequence(ctx) if err != nil { return err } diff --git a/examples/democoin/x/pow/commands/tx.go b/examples/democoin/x/pow/commands/tx.go index abd5d27ebf..5fa11a4766 100644 --- a/examples/democoin/x/pow/commands/tx.go +++ b/examples/democoin/x/pow/commands/tx.go @@ -55,7 +55,7 @@ func MineCmd(cdc *wire.Codec) *cobra.Command { name := ctx.FromAddressName // default to next sequence number if none provided - ctx, err = context.AutoSequence(ctx) + ctx, err = context.EnsureSequence(ctx) if err != nil { return err } diff --git a/x/bank/commands/sendtx.go b/x/bank/commands/sendtx.go index a37e969a63..56048262d7 100644 --- a/x/bank/commands/sendtx.go +++ b/x/bank/commands/sendtx.go @@ -64,7 +64,7 @@ func (c Commander) sendTxCmd(cmd *cobra.Command, args []string) error { msg := BuildMsg(from, to, coins) // default to next sequence number if none provided - ctx, err = context.AutoSequence(ctx) + ctx, err = context.EnsureSequence(ctx) if err != nil { return err } diff --git a/x/ibc/commands/ibctx.go b/x/ibc/commands/ibctx.go index ee0ac02eea..d17b40b21e 100644 --- a/x/ibc/commands/ibctx.go +++ b/x/ibc/commands/ibctx.go @@ -55,7 +55,7 @@ func (c sendCommander) sendIBCTransfer(cmd *cobra.Command, args []string) error } // default to next sequence number if none provided - ctx, err = context.AutoSequence(ctx) + ctx, err = context.EnsureSequence(ctx) if err != nil { return err } diff --git a/x/simplestake/commands/commands.go b/x/simplestake/commands/commands.go index 0e8a7a9bb4..ba66020283 100644 --- a/x/simplestake/commands/commands.go +++ b/x/simplestake/commands/commands.go @@ -98,7 +98,7 @@ 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.AutoSequence(ctx) + ctx, err := context.EnsureSequence(ctx) if err != nil { return err } diff --git a/x/stake/commands/tx.go b/x/stake/commands/tx.go index 1b9063a65b..5cc9747b61 100644 --- a/x/stake/commands/tx.go +++ b/x/stake/commands/tx.go @@ -96,7 +96,7 @@ func GetCmdDeclareCandidacy(cdc *wire.Codec) *cobra.Command { ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) // default to next sequence number if none provided - ctx, err = context.AutoSequence(ctx) + ctx, err = context.EnsureSequence(ctx) if err != nil { return err } @@ -140,7 +140,7 @@ func GetCmdEditCandidacy(cdc *wire.Codec) *cobra.Command { ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) // default to next sequence number if none provided - ctx, err = context.AutoSequence(ctx) + ctx, err = context.EnsureSequence(ctx) if err != nil { return err } @@ -183,7 +183,7 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) // default to next sequence number if none provided - ctx, err = context.AutoSequence(ctx) + ctx, err = context.EnsureSequence(ctx) if err != nil { return err } @@ -237,7 +237,7 @@ func GetCmdUnbond(cdc *wire.Codec) *cobra.Command { ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) // default to next sequence number if none provided - ctx, err = context.AutoSequence(ctx) + ctx, err = context.EnsureSequence(ctx) if err != nil { return err } From 22372bfffdec0cb6016b72b6f8c122e9868916a7 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 10 Apr 2018 12:39:47 +0200 Subject: [PATCH 06/14] Add basic Dockerfile to build all binaries and export gaiad --- .dockerignore | 5 +++++ Dockerfile | 51 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 36 insertions(+), 20 deletions(-) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..404f6c39fb --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +Dockerfile +Vagrantfile + +build/ +coverage.txt diff --git a/Dockerfile b/Dockerfile index 79b078d91c..6fe01a15db 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,28 +1,39 @@ -FROM alpine:3.5 +# Simple usage with a mounted data directory: +# > docker build -t gaia . +# > docker run -v $HOME/.gaiad:/root/.gaiad gaia init +# > docker run -v $HOME/.gaiad:/root/.gaiad gaia start -# BCHOME is where your genesis.json, key.json and other files including state are stored. -ENV BCHOME /basecoin +FROM alpine:edge -# Create a basecoin user and group first so the IDs get set the same way, even -# as the rest of this may change over time. -RUN addgroup basecoin && \ - adduser -S -G basecoin basecoin +# Install minimum necessary dependencies -RUN mkdir -p $BCHOME && \ - chown -R basecoin:basecoin $BCHOME -WORKDIR $BCHOME +ENV PACKAGES go glide make git libc-dev bash +RUN apk add --no-cache $PACKAGES -# Expose the basecoin home directory as a volume since there's mutable state in there. -VOLUME $BCHOME +# Set up GOPATH & PATH -# jq and curl used for extracting `pub_key` from private validator while -# deploying tendermint with Kubernetes. It is nice to have bash so the users -# could execute bash commands. -RUN apk add --no-cache bash curl jq +ENV GOPATH /root/go +ENV BASE_PATH $GOPATH/src/github.com/cosmos +ENV REPO_PATH $BASE_PATH/cosmos-sdk +ENV WORKDIR /cosmos/ +ENV PATH $GOPATH/bin:$PATH -COPY basecoin /usr/bin/basecoin +# Link expected Go repo path -ENTRYPOINT ["basecoin"] +RUN mkdir -p $WORKDIR $GOPATH/pkg $ $GOPATH/bin $BASE_PATH && ln -sf $WORKDIR $REPO_PATH -# By default you will get the basecoin with local MerkleEyes and in-proc Tendermint. -CMD ["start", "--dir=${BCHOME}"] +# Add source files + +ADD . $WORKDIR + +# Build cosmos-sdk + +RUN cd $REPO_PATH && make get_tools && make get_vendor_deps && make all && make install + +# Remove packages + +RUN apk del $PACKAGES + +# Set entrypoint + +ENTRYPOINT ["/root/go/bin/gaiad"] From 442e67730026f99e6991e32d11a20b83eee6e7a6 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 10 Apr 2018 17:04:27 +0200 Subject: [PATCH 07/14] add CacheContext --- types/context.go | 11 +++++++++-- types/context_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/types/context.go b/types/context.go index 3c90b016a2..85eb9e493f 100644 --- a/types/context.go +++ b/types/context.go @@ -16,12 +16,13 @@ The intent of Context is for it to be an immutable object that can be cloned and updated cheaply with WithValue() and passed forward to the next decorator or handler. For example, - func MsgHandler(ctx Context, tx Tx) Result { + func MsgHandler(context Context, tx Tx) Result { ... - ctx = ctx.WithValue(key, value) + context = context.WithValue(key, value) ... } */ + type Context struct { context.Context pst *thePast @@ -171,6 +172,12 @@ func (c Context) WithTxBytes(txBytes []byte) Context { return c.withValue(contextKeyTxBytes, txBytes) } +func (c Context) CacheContext() (Context, func()) { + cms := c.multiStore().CacheMultiStore() + cc := c.WithMultiStore(cms) + return cc, cms.Write +} + //---------------------------------------- // thePast diff --git a/types/context_test.go b/types/context_test.go index 36d8099b95..b40e79dc2a 100644 --- a/types/context_test.go +++ b/types/context_test.go @@ -3,6 +3,11 @@ package types_test import ( "testing" + "github.com/stretchr/testify/assert" + + dbm "github.com/tendermint/tmlibs/db" + + "github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/types" abci "github.com/tendermint/abci/types" ) @@ -18,3 +23,39 @@ func TestContextGetOpShouldNeverPanic(t *testing.T) { _, _ = ctx.GetOp(index) } } + +func defaultContext(key types.StoreKey) types.Context { + db := dbm.NewMemDB() + cms := store.NewCommitMultiStore(db) + cms.MountStoreWithDB(key, types.StoreTypeIAVL, db) + cms.LoadLatestVersion() + ctx := types.NewContext(cms, abci.Header{}, false, nil) + return ctx +} + +func TestCacheContext(t *testing.T) { + key := types.NewKVStoreKey(t.Name()) + k1 := []byte("hello") + v1 := []byte("world") + k2 := []byte("key") + v2 := []byte("value") + + ctx := defaultContext(key) + store := ctx.KVStore(key) + store.Set(k1, v1) + assert.Equal(t, v1, store.Get(k1)) + assert.Nil(t, store.Get(k2)) + + cctx, write := ctx.CacheContext() + cstore := cctx.KVStore(key) + assert.Equal(t, v1, cstore.Get(k1)) + assert.Nil(t, cstore.Get(k2)) + + cstore.Set(k2, v2) + assert.Equal(t, v2, cstore.Get(k2)) + assert.Nil(t, store.Get(k2)) + + write() + + assert.Equal(t, v2, store.Get(k2)) +} From 8ed15f7e9d33d1127107c1f445311fe50dbfac08 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 10 Apr 2018 17:06:02 +0200 Subject: [PATCH 08/14] typo --- types/context.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/context.go b/types/context.go index 85eb9e493f..a6d6b3c3b3 100644 --- a/types/context.go +++ b/types/context.go @@ -16,9 +16,9 @@ The intent of Context is for it to be an immutable object that can be cloned and updated cheaply with WithValue() and passed forward to the next decorator or handler. For example, - func MsgHandler(context Context, tx Tx) Result { + func MsgHandler(ctx Context, tx Tx) Result { ... - context = context.WithValue(key, value) + ctx = context.WithValue(key, value) ... } */ From 1c8094c6bde1a137422be2a77480e91154011781 Mon Sep 17 00:00:00 2001 From: Joon Date: Tue, 10 Apr 2018 17:07:54 +0200 Subject: [PATCH 09/14] Update context.go --- types/context.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/context.go b/types/context.go index a6d6b3c3b3..1ec81ca0ec 100644 --- a/types/context.go +++ b/types/context.go @@ -18,7 +18,7 @@ next decorator or handler. For example, func MsgHandler(ctx Context, tx Tx) Result { ... - ctx = context.WithValue(key, value) + ctx = ctx.WithValue(key, value) ... } */ From 8dd612c38aa815c5ba63819b29e46e63e0dc7713 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 10 Apr 2018 18:48:47 +0200 Subject: [PATCH 10/14] Address PR comments --- Dockerfile | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6fe01a15db..a788aa6416 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,10 +5,8 @@ FROM alpine:edge -# Install minimum necessary dependencies - +# Set up dependencies ENV PACKAGES go glide make git libc-dev bash -RUN apk add --no-cache $PACKAGES # Set up GOPATH & PATH @@ -20,20 +18,17 @@ ENV PATH $GOPATH/bin:$PATH # Link expected Go repo path -RUN mkdir -p $WORKDIR $GOPATH/pkg $ $GOPATH/bin $BASE_PATH && ln -sf $WORKDIR $REPO_PATH +RUN mkdir -p $WORKDIR $GOPATH/pkg $ $GOPATH/bin $BASE_PATH # Add source files -ADD . $WORKDIR +ADD . $REPO_PATH -# Build cosmos-sdk - -RUN cd $REPO_PATH && make get_tools && make get_vendor_deps && make all && make install - -# Remove packages - -RUN apk del $PACKAGES +# Install minimum necessary dependencies, build Cosmos SDK, remove packages +RUN apk add --no-cache $PACKAGES && \ + cd $REPO_PATH && make get_tools && make get_vendor_deps && make all && make install && \ + apk del $PACKAGES # Set entrypoint -ENTRYPOINT ["/root/go/bin/gaiad"] +ENTRYPOINT ["gaiad"] From bdc7fe56bac8bf4e1d74d505b792d4b7117284a1 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 10 Apr 2018 15:44:49 -0400 Subject: [PATCH 11/14] cachecontext comments and changelog update --- CHANGELOG.md | 4 ++++ types/context.go | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79cb396c6e..2801c932b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ BREAKING CHANGES * Remove go-wire, use go-amino * [store] Add `SubspaceIterator` and `ReverseSubspaceIterator` to `KVStore` interface +FEATURES: + +* Add CacheContext + ## 0.14.1 (April 9, 2018) BUG FIXES diff --git a/types/context.go b/types/context.go index 1ec81ca0ec..8c91175bc6 100644 --- a/types/context.go +++ b/types/context.go @@ -22,7 +22,6 @@ next decorator or handler. For example, ... } */ - type Context struct { context.Context pst *thePast @@ -172,9 +171,11 @@ func (c Context) WithTxBytes(txBytes []byte) Context { return c.withValue(contextKeyTxBytes, txBytes) } -func (c Context) CacheContext() (Context, func()) { +// Cache the multistore and return a new cached context. The cached context is +// written to the context when writeCache is called. +func (c Context) CacheContext() (cc Context, writeCache func()) { cms := c.multiStore().CacheMultiStore() - cc := c.WithMultiStore(cms) + cc = c.WithMultiStore(cms) return cc, cms.Write } From c741be16cea679808fbaa9181be08bbae03952de Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 10 Apr 2018 17:45:23 -0400 Subject: [PATCH 12/14] next sequence comment, CHANGELOG updates --- CHANGELOG.md | 4 ++++ client/core/core.go | 1 + 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52feff7fc3..1b31535273 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ BREAKING CHANGES * Remove go-wire, use go-amino +FEATURES: + +* Add auto sequencing to client + ## 0.14.1 (April 9, 2018) BUG FIXES diff --git a/client/core/core.go b/client/core/core.go index e28e6c3928..2a1b2736a2 100644 --- a/client/core/core.go +++ b/client/core/core.go @@ -140,6 +140,7 @@ func (ctx CoreContext) SignBuildBroadcast(name string, msg sdk.Msg, cdc *wire.Co return ctx.BroadcastTx(txBytes) } +// get the next sequence for the account address func (c CoreContext) NextSequence(address []byte) (int64, error) { if c.Decoder == nil { return 0, errors.New("AccountDecoder required but not provided") From 24f3a3a71c8fdc3b333e99a201accbdbcba39603 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 11 Apr 2018 11:25:52 +0200 Subject: [PATCH 13/14] Recreate RPC client on WithNodeURI --- client/core/context.go | 1 + 1 file changed, 1 insertion(+) diff --git a/client/core/context.go b/client/core/context.go index 3d7f400a8e..77d2dc549b 100644 --- a/client/core/context.go +++ b/client/core/context.go @@ -31,6 +31,7 @@ func (c CoreContext) WithTrustNode(trustNode bool) CoreContext { func (c CoreContext) WithNodeURI(nodeURI string) CoreContext { c.NodeURI = nodeURI + c.Client = rpcclient.NewHTTP(nodeURI, "/websocket") return c } From 25d0fb593cdf431f19678fd91c74a4d071162438 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 11 Apr 2018 17:47:56 +0200 Subject: [PATCH 14/14] Address PR comments --- client/context/viper.go | 10 +--------- client/core/context.go | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/client/context/viper.go b/client/context/viper.go index 193fe9baa6..c3b0369d98 100644 --- a/client/context/viper.go +++ b/client/context/viper.go @@ -1,10 +1,8 @@ package context import ( - "encoding/json" "fmt" "github.com/spf13/viper" - "io/ioutil" tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" rpcclient "github.com/tendermint/tendermint/rpc/client" @@ -48,13 +46,7 @@ func defaultChainID() (string, error) { if err != nil { return "", err } - genesisFile := cfg.GenesisFile() - bz, err := ioutil.ReadFile(genesisFile) - if err != nil { - return "", err - } - var doc tmtypes.GenesisDoc - err = json.Unmarshal(bz, &doc) + doc, err := tmtypes.GenesisDocFromFile(cfg.GenesisFile()) if err != nil { return "", err } diff --git a/client/core/context.go b/client/core/context.go index 7f8d764324..fac60b553b 100644 --- a/client/core/context.go +++ b/client/core/context.go @@ -24,7 +24,7 @@ func (c CoreContext) WithChainID(chainID string) CoreContext { return c } -// WithHeight - eturn a copy of the context with an updated height +// WithHeight - return a copy of the context with an updated height func (c CoreContext) WithHeight(height int64) CoreContext { c.Height = height return c