From 04c2071824bcb9c78b1d306d23f8ee70aed2f38e Mon Sep 17 00:00:00 2001 From: Sherry Ma Date: Fri, 22 Jun 2018 17:48:52 +0800 Subject: [PATCH 01/53] Change the value of tag --address-validator When doing gaiacli stake delegate/unbond/delegation, --address-validator should get the address of the validator, not the validator pubkey. --- cmd/gaia/testnets/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/gaia/testnets/README.md b/cmd/gaia/testnets/README.md index 5b6df83ad..8cce4822c 100644 --- a/cmd/gaia/testnets/README.md +++ b/cmd/gaia/testnets/README.md @@ -320,7 +320,7 @@ On the testnet, we delegate `steak` instead of `atom`. Here's how you can bond t gaiacli stake delegate \ --amount=10steak \ --address-delegator= \ - --address-validator=$(gaiad tendermint show_validator) \ + --address-validator= \ --name= \ --chain-id=gaia-6002 ``` @@ -336,7 +336,7 @@ If for any reason the validator misbehaves, or you want to unbond a certain amou ```bash gaiacli stake unbond \ --address-delegator= \ - --address-validator=$(gaiad tendermint show_validator) \ + --address-validator= \ --shares=MAX \ --name= \ --chain-id=gaia-6002 @@ -349,7 +349,7 @@ gaiacli account gaiacli stake delegation \ --address-delegator= \ - --address-validator=$(gaiad tendermint show_validator) \ + --address-validator= \ --chain-id=gaia-6002 ``` From 1a67dc5d7cdc9d02a29038b96e4c7c7e3fcf34d1 Mon Sep 17 00:00:00 2001 From: Sherry Ma Date: Fri, 22 Jun 2018 18:37:15 +0800 Subject: [PATCH 02/53] Changed decode delegator address function In delegation query, the function to decode the address of delegator should be using Bech32 but not Hex --- x/stake/client/cli/query.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/stake/client/cli/query.go b/x/stake/client/cli/query.go index 727cddcde..9ec1edc25 100644 --- a/x/stake/client/cli/query.go +++ b/x/stake/client/cli/query.go @@ -117,7 +117,7 @@ func GetCmdQueryDelegation(storeName string, cdc *wire.Codec) *cobra.Command { return err } - delAddr, err := sdk.GetValAddressHex(viper.GetString(FlagAddressDelegator)) + delAddr, err := sdk.GetAccAddressBech32(viper.GetString(FlagAddressDelegator)) if err != nil { return err } From 94a3ce4c83afeaa5e3fcc069e889ffcf67b4f321 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Fri, 29 Jun 2018 10:45:11 -0700 Subject: [PATCH 03/53] docs: Explain the expected return type within the store (#1452) --- x/stake/keeper/key.go | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index 667f5f681..3be009e22 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -35,30 +35,35 @@ var ( const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch -// get the key for the validator with address +// get the key for the validator with address. +// the value at this key is of type stake/types.Validator func GetValidatorKey(ownerAddr sdk.Address) []byte { return append(ValidatorsKey, ownerAddr.Bytes()...) } -// get the key for the validator with pubkey +// get the key for the validator with pubkey. +// the value at this key should the address for a stake/types.Validator func GetValidatorByPubKeyIndexKey(pubkey crypto.PubKey) []byte { return append(ValidatorsByPubKeyIndexKey, pubkey.Bytes()...) } -// get the key for the current validator group, ordered like tendermint +// get the key for the current validator group, ordered like tendermint. +// the value at this key is the address of the owner of a validator func GetValidatorsBondedIndexKey(ownerAddr sdk.Address) []byte { return append(ValidatorsBondedIndexKey, ownerAddr.Bytes()...) } -// get the power which is the key for the validator used in the power-store +// get the validator by power index. power index is the key used in the power-store, +// and represents the relative power ranking of the validator. +// the value at this key is of type address, the address being the Address +// of the corresponding validator. func GetValidatorsByPowerIndexKey(validator types.Validator, pool types.Pool) []byte { - // NOTE the address doesn't need to be stored because counter bytes must always be different - return GetValidatorPowerRank(validator, pool) + return getValidatorPowerRank(validator, pool) } -// get the power of a validator -func GetValidatorPowerRank(validator types.Validator, pool types.Pool) []byte { +// get the power ranking of a validator +func getValidatorPowerRank(validator types.Validator, pool types.Pool) []byte { power := validator.EquivalentBondedShares(pool) powerBytes := []byte(power.ToLeftPadded(maxDigitsForAccount)) // power big-endian (more powerful validators first) @@ -71,7 +76,7 @@ func GetValidatorPowerRank(validator types.Validator, pool types.Pool) []byte { revokedBytes[0] = byte(0x00) } - // TODO ensure that the key will be a readable string.. probably should add seperators and have + // TODO ensure that the key will be a readable string.. probably should add separators and have // heightBytes and counterBytes represent strings like powerBytes does heightBytes := make([]byte, binary.MaxVarintLen64) binary.BigEndian.PutUint64(heightBytes, ^uint64(validator.BondHeight)) // invert height (older validators first) @@ -84,14 +89,16 @@ func GetValidatorPowerRank(validator types.Validator, pool types.Pool) []byte { append(heightBytes, counterBytes...)...)...)...) } -// get the key for the accumulated update validators +// get the key for the accumulated update validators. +// The value at this key is of type stake/types.Validator func GetTendermintUpdatesKey(ownerAddr sdk.Address) []byte { return append(TendermintUpdatesKey, ownerAddr.Bytes()...) } //________________________________________________________________________________ -// get the key for delegator bond with validator +// get the key for delegator bond with validator. +// The value at this key is of type stake/types.Delegation func GetDelegationKey(delegatorAddr, validatorAddr sdk.Address, cdc *wire.Codec) []byte { return append(GetDelegationsKey(delegatorAddr, cdc), validatorAddr.Bytes()...) } @@ -104,12 +111,14 @@ func GetDelegationsKey(delegatorAddr sdk.Address, cdc *wire.Codec) []byte { //________________________________________________________________________________ -// get the key for an unbonding delegation +// get the key for an unbonding delegation by delegator and validator addr. +// The value at this key is of type stake/types.UnbondingDelegation func GetUBDKey(delegatorAddr, validatorAddr sdk.Address, cdc *wire.Codec) []byte { return append(GetUBDsKey(delegatorAddr, cdc), validatorAddr.Bytes()...) } // get the index-key for an unbonding delegation, stored by validator-index +// The value at this key is a key for the corresponding unbonding delegation. func GetUBDByValIndexKey(delegatorAddr, validatorAddr sdk.Address, cdc *wire.Codec) []byte { return append(GetUBDsByValIndexKey(validatorAddr, cdc), delegatorAddr.Bytes()...) } @@ -122,7 +131,7 @@ func GetUBDsKey(delegatorAddr sdk.Address, cdc *wire.Codec) []byte { return append(UnbondingDelegationKey, res...) } -// get the prefix keyspace for the indexs of unbonding delegations for a validator +// get the prefix keyspace for the indexes of unbonding delegations for a validator func GetUBDsByValIndexKey(validatorAddr sdk.Address, cdc *wire.Codec) []byte { res := cdc.MustMarshalBinary(&validatorAddr) return append(UnbondingDelegationByValIndexKey, res...) @@ -131,6 +140,7 @@ func GetUBDsByValIndexKey(validatorAddr sdk.Address, cdc *wire.Codec) []byte { //________________________________________________________________________________ // get the key for a redelegation +// The value at this key is of type stake/types.RedelegationKey func GetREDKey(delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.Address, cdc *wire.Codec) []byte { @@ -143,6 +153,7 @@ func GetREDKey(delegatorAddr, validatorSrcAddr, } // get the index-key for a redelegation, stored by source-validator-index +// The value at this key is a key for the corresponding redelegation. func GetREDByValSrcIndexKey(delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.Address, cdc *wire.Codec) []byte { @@ -155,6 +166,7 @@ func GetREDByValSrcIndexKey(delegatorAddr, validatorSrcAddr, } // get the index-key for a redelegation, stored by destination-validator-index +// The value at this key is a key for the corresponding redelegation. func GetREDByValDstIndexKey(delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.Address, cdc *wire.Codec) []byte { From 819eedd28161d2c00277fe9713cdab26c26b2fb4 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Sat, 30 Jun 2018 01:27:58 -0700 Subject: [PATCH 04/53] gaiacli: Improve error messages for `send` command Now provides better error messages when the account you're sending from has no money, or it has insufficient funds. (Avoids making the user interpret ABCI errors) closes #1489 --- CHANGELOG.md | 1 + x/auth/client/cli/account.go | 3 ++- x/bank/client/cli/sendtx.go | 28 ++++++++++++++++++++++++++-- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0b543247..bdb425db3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ FEATURES - You can now use a Ledger with `gaiacli --ledger` for all key-related commands - Ledger keys can be named and tracked locally in the key DB * [gaiacli] added an --async flag to the cli to deliver transactions without waiting for a tendermint response +* [gaiacli] improve error messages on `send` and `account` commands FIXES * [gaia] Added self delegation for validators in the genesis creation diff --git a/x/auth/client/cli/account.go b/x/auth/client/cli/account.go index ccc1e277b..47980a64c 100644 --- a/x/auth/client/cli/account.go +++ b/x/auth/client/cli/account.go @@ -1,6 +1,7 @@ package cli import ( + "errors" "fmt" "github.com/spf13/cobra" @@ -54,7 +55,7 @@ func GetAccountCmd(storeName string, cdc *wire.Codec, decoder auth.AccountDecode // Check if account was found if res == nil { - return sdk.ErrUnknownAddress("No account with address " + addr + + return errors.New("No account with address " + addr + " was found in the state.\nAre you sure there has been a transaction involving it?") } diff --git a/x/bank/client/cli/sendtx.go b/x/bank/client/cli/sendtx.go index d3f7377fa..e3ce4c4d2 100644 --- a/x/bank/client/cli/sendtx.go +++ b/x/bank/client/cli/sendtx.go @@ -1,6 +1,7 @@ package cli import ( + "errors" "fmt" "github.com/spf13/cobra" @@ -9,6 +10,7 @@ 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/auth" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" "github.com/cosmos/cosmos-sdk/x/bank/client" ) @@ -19,7 +21,7 @@ const ( flagAsync = "async" ) -// SendTxCommand will create a send tx and sign it with the given key +// SendTxCmd will create a send tx and sign it with the given key func SendTxCmd(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "send", @@ -33,19 +35,41 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command { return err } + fromAcc, err := ctx.QueryStore(auth.AddressStoreKey(from), ctx.AccountStore) + if err != nil { + return err + } + + bech32From := sdk.MustBech32ifyAcc(from) + // Check if account was found + if fromAcc == nil { + return errors.New("No account with address " + bech32From + + " was found in the state.\nAre you sure there has been a transaction involving it?") + } + toStr := viper.GetString(flagTo) to, err := sdk.GetAccAddressBech32(toStr) if err != nil { return err } - // parse coins + // parse coins trying to be sent amount := viper.GetString(flagAmount) coins, err := sdk.ParseCoins(amount) if err != nil { return err } + // ensure account has enough coins + account, err := ctx.Decoder(fromAcc) + if err != nil { + return err + } + if !account.GetCoins().IsGTE(coins) { + return errors.New("Address " + bech32From + + " doesn't have enough coins to pay for this transaction.") + } + // build and sign the transaction, then broadcast to Tendermint msg := client.BuildMsg(from, to, coins) From ab4661f88b0676f969e0cb4c9b58193158adfd68 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 2 Jul 2018 18:16:47 -0400 Subject: [PATCH 05/53] bug somewhere here --- x/stake/client/cli/query.go | 12 +-- x/stake/client/cli/tx.go | 2 +- x/stake/client/rest/query.go | 6 +- x/stake/keeper/delegation.go | 54 +++++++----- x/stake/keeper/delegation_test.go | 22 ++++- x/stake/keeper/key.go | 141 +++++++++++++++++++----------- x/stake/keeper/sdk_types.go | 2 +- 7 files changed, 155 insertions(+), 84 deletions(-) diff --git a/x/stake/client/cli/query.go b/x/stake/client/cli/query.go index c162717ef..661dce31d 100644 --- a/x/stake/client/cli/query.go +++ b/x/stake/client/cli/query.go @@ -122,7 +122,7 @@ func GetCmdQueryDelegation(storeName string, cdc *wire.Codec) *cobra.Command { return err } - key := stake.GetDelegationKey(delAddr, valAddr, cdc) + key := stake.GetDelegationKey(delAddr, valAddr) ctx := context.NewCoreContextFromViper() res, err := ctx.QueryStore(key, storeName) if err != nil { @@ -169,7 +169,7 @@ func GetCmdQueryDelegations(storeName string, cdc *wire.Codec) *cobra.Command { if err != nil { return err } - key := stake.GetDelegationsKey(delegatorAddr, cdc) + key := stake.GetDelegationsKey(delegatorAddr) ctx := context.NewCoreContextFromViper() resKVs, err := ctx.QuerySubspace(cdc, key, storeName) if err != nil { @@ -214,7 +214,7 @@ func GetCmdQueryUnbondingDelegation(storeName string, cdc *wire.Codec) *cobra.Co return err } - key := stake.GetUBDKey(delAddr, valAddr, cdc) + key := stake.GetUBDKey(delAddr, valAddr) ctx := context.NewCoreContextFromViper() res, err := ctx.QueryStore(key, storeName) if err != nil { @@ -261,7 +261,7 @@ func GetCmdQueryUnbondingDelegations(storeName string, cdc *wire.Codec) *cobra.C if err != nil { return err } - key := stake.GetUBDsKey(delegatorAddr, cdc) + key := stake.GetUBDsKey(delegatorAddr) ctx := context.NewCoreContextFromViper() resKVs, err := ctx.QuerySubspace(cdc, key, storeName) if err != nil { @@ -309,7 +309,7 @@ func GetCmdQueryRedelegation(storeName string, cdc *wire.Codec) *cobra.Command { return err } - key := stake.GetREDKey(delAddr, valSrcAddr, valDstAddr, cdc) + key := stake.GetREDKey(delAddr, valSrcAddr, valDstAddr) ctx := context.NewCoreContextFromViper() res, err := ctx.QueryStore(key, storeName) if err != nil { @@ -356,7 +356,7 @@ func GetCmdQueryRedelegations(storeName string, cdc *wire.Codec) *cobra.Command if err != nil { return err } - key := stake.GetREDsKey(delegatorAddr, cdc) + key := stake.GetREDsKey(delegatorAddr) ctx := context.NewCoreContextFromViper() resKVs, err := ctx.QuerySubspace(cdc, key, storeName) if err != nil { diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index b0fa2e524..068c19ce2 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -238,7 +238,7 @@ func getShares(storeName string, cdc *wire.Codec, sharesAmountStr, sharesPercent } // make a query to get the existing delegation shares - key := stake.GetDelegationKey(delegatorAddr, validatorAddr, cdc) + key := stake.GetDelegationKey(delegatorAddr, validatorAddr) ctx := context.NewCoreContextFromViper() resQuery, err := ctx.QueryStore(key, storeName) if err != nil { diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index afa9e3bf0..12ef882e5 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -60,7 +60,7 @@ func delegationHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerF return } - key := stake.GetDelegationKey(delegatorAddr, validatorAddr, cdc) + key := stake.GetDelegationKey(delegatorAddr, validatorAddr) res, err := ctx.QueryStore(key, storeName) if err != nil { @@ -117,7 +117,7 @@ func ubdHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerFunc { return } - key := stake.GetUBDKey(delegatorAddr, validatorAddr, cdc) + key := stake.GetUBDKey(delegatorAddr, validatorAddr) res, err := ctx.QueryStore(key, storeName) if err != nil { @@ -182,7 +182,7 @@ func redHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerFunc { return } - key := stake.GetREDKey(delegatorAddr, validatorSrcAddr, validatorDstAddr, cdc) + key := stake.GetREDKey(delegatorAddr, validatorSrcAddr, validatorDstAddr) res, err := ctx.QueryStore(key, storeName) if err != nil { diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 514939e17..8ede4b55e 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -2,6 +2,7 @@ package keeper import ( "bytes" + "fmt" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" @@ -12,7 +13,7 @@ func (k Keeper) GetDelegation(ctx sdk.Context, delegatorAddr, validatorAddr sdk.Address) (delegation types.Delegation, found bool) { store := ctx.KVStore(k.storeKey) - delegatorBytes := store.Get(GetDelegationKey(delegatorAddr, validatorAddr, k.cdc)) + delegatorBytes := store.Get(GetDelegationKey(delegatorAddr, validatorAddr)) if delegatorBytes == nil { return delegation, false } @@ -46,7 +47,7 @@ func (k Keeper) GetDelegations(ctx sdk.Context, delegator sdk.Address, maxRetrieve int16) (delegations []types.Delegation) { store := ctx.KVStore(k.storeKey) - delegatorPrefixKey := GetDelegationsKey(delegator, k.cdc) + delegatorPrefixKey := GetDelegationsKey(delegator) iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) //smallest to largest delegations = make([]types.Delegation, maxRetrieve) @@ -69,13 +70,13 @@ func (k Keeper) GetDelegations(ctx sdk.Context, delegator sdk.Address, func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { store := ctx.KVStore(k.storeKey) b := k.cdc.MustMarshalBinary(delegation) - store.Set(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr, k.cdc), b) + store.Set(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr), b) } // remove the delegation func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) { store := ctx.KVStore(k.storeKey) - store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr, k.cdc)) + store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr)) } //_____________________________________________________________________________________ @@ -85,7 +86,7 @@ func (k Keeper) GetUnbondingDelegation(ctx sdk.Context, DelegatorAddr, ValidatorAddr sdk.Address) (ubd types.UnbondingDelegation, found bool) { store := ctx.KVStore(k.storeKey) - ubdKey := GetUBDKey(DelegatorAddr, ValidatorAddr, k.cdc) + ubdKey := GetUBDKey(DelegatorAddr, ValidatorAddr) bz := store.Get(ubdKey) if bz == nil { return ubd, false @@ -98,13 +99,13 @@ func (k Keeper) GetUnbondingDelegation(ctx sdk.Context, // load all unbonding delegations from a particular validator func (k Keeper) GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr sdk.Address) (unbondingDelegations []types.UnbondingDelegation) { store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, GetUBDsByValIndexKey(valAddr, k.cdc)) + iterator := sdk.KVStorePrefixIterator(store, GetUBDsByValIndexKey(valAddr)) i := 0 for ; ; i++ { if !iterator.Valid() { break } - unbondingKey := iterator.Value() + unbondingKey := GetUBDKeyFromValIndexKey(iterator.Key()) unbondingBytes := store.Get(unbondingKey) var unbondingDelegation types.UnbondingDelegation k.cdc.MustUnmarshalBinary(unbondingBytes, &unbondingDelegation) @@ -119,17 +120,17 @@ func (k Keeper) GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr sd func (k Keeper) SetUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDelegation) { store := ctx.KVStore(k.storeKey) bz := k.cdc.MustMarshalBinary(ubd) - ubdKey := GetUBDKey(ubd.DelegatorAddr, ubd.ValidatorAddr, k.cdc) + ubdKey := GetUBDKey(ubd.DelegatorAddr, ubd.ValidatorAddr) store.Set(ubdKey, bz) - store.Set(GetUBDByValIndexKey(ubd.DelegatorAddr, ubd.ValidatorAddr, k.cdc), ubdKey) + store.Set(GetUBDByValIndexKey(ubd.DelegatorAddr, ubd.ValidatorAddr), []byte{}) } // remove the unbonding delegation object and associated index func (k Keeper) RemoveUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDelegation) { store := ctx.KVStore(k.storeKey) - ubdKey := GetUBDKey(ubd.DelegatorAddr, ubd.ValidatorAddr, k.cdc) + ubdKey := GetUBDKey(ubd.DelegatorAddr, ubd.ValidatorAddr) store.Delete(ubdKey) - store.Delete(GetUBDByValIndexKey(ubd.DelegatorAddr, ubd.ValidatorAddr, k.cdc)) + store.Delete(GetUBDByValIndexKey(ubd.DelegatorAddr, ubd.ValidatorAddr)) } //_____________________________________________________________________________________ @@ -139,7 +140,7 @@ func (k Keeper) GetRedelegation(ctx sdk.Context, DelegatorAddr, ValidatorSrcAddr, ValidatorDstAddr sdk.Address) (red types.Redelegation, found bool) { store := ctx.KVStore(k.storeKey) - redKey := GetREDKey(DelegatorAddr, ValidatorSrcAddr, ValidatorDstAddr, k.cdc) + redKey := GetREDKey(DelegatorAddr, ValidatorSrcAddr, ValidatorDstAddr) bz := store.Get(redKey) if bz == nil { return red, false @@ -152,13 +153,23 @@ func (k Keeper) GetRedelegation(ctx sdk.Context, // load all redelegations from a particular validator func (k Keeper) GetRedelegationsFromValidator(ctx sdk.Context, valAddr sdk.Address) (redelegations []types.Redelegation) { store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, GetREDsFromValSrcIndexKey(valAddr, k.cdc)) + iterator := sdk.KVStorePrefixIterator(store, GetREDsFromValSrcIndexKey(valAddr)) i := 0 for ; ; i++ { + fmt.Printf("debug i: %v\n", i) if !iterator.Valid() { break } - redelegationKey := iterator.Value() + redelegationKeyOrig := iterator.Value() + redelegationBytes2 := store.Get(redelegationKeyOrig) + var redelegation2 types.Redelegation + k.cdc.MustUnmarshalBinary(redelegationBytes2, &redelegation2) + fmt.Printf("debug orig redelegation2: %v\n", redelegation2) + + redelegationKey := GetREDKeyFromValSrcIndexKey(iterator.Key()) + fmt.Printf("debug orig redelegationKey: %v\n", redelegationKeyOrig) + fmt.Printf("debug redelegationKey: %v\n", redelegationKey) + fmt.Printf("debug iteratorKey: %v\n", iterator.Key()) redelegationBytes := store.Get(redelegationKey) var redelegation types.Redelegation k.cdc.MustUnmarshalBinary(redelegationBytes, &redelegation) @@ -174,7 +185,7 @@ func (k Keeper) HasReceivingRedelegation(ctx sdk.Context, DelegatorAddr, ValidatorDstAddr sdk.Address) bool { store := ctx.KVStore(k.storeKey) - prefix := GetREDsByDelToValDstIndexKey(DelegatorAddr, ValidatorDstAddr, k.cdc) + prefix := GetREDsByDelToValDstIndexKey(DelegatorAddr, ValidatorDstAddr) iterator := sdk.KVStorePrefixIterator(store, prefix) //smallest to largest found := false @@ -190,19 +201,20 @@ func (k Keeper) HasReceivingRedelegation(ctx sdk.Context, func (k Keeper) SetRedelegation(ctx sdk.Context, red types.Redelegation) { store := ctx.KVStore(k.storeKey) bz := k.cdc.MustMarshalBinary(red) - redKey := GetREDKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr, k.cdc) + redKey := GetREDKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr) + fmt.Printf("debug redKey: %v\n", redKey) store.Set(redKey, bz) - store.Set(GetREDByValSrcIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr, k.cdc), redKey) - store.Set(GetREDByValDstIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr, k.cdc), redKey) + store.Set(GetREDByValSrcIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr), redKey) //[]byte{}) + store.Set(GetREDByValDstIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr), redKey) // []byte{}) } // remove a redelegation object and associated index func (k Keeper) RemoveRedelegation(ctx sdk.Context, red types.Redelegation) { store := ctx.KVStore(k.storeKey) - redKey := GetREDKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr, k.cdc) + redKey := GetREDKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr) store.Delete(redKey) - store.Delete(GetREDByValSrcIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr, k.cdc)) - store.Delete(GetREDByValDstIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr, k.cdc)) + store.Delete(GetREDByValSrcIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr)) + store.Delete(GetREDByValDstIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr)) } //_____________________________________________________________________________________ diff --git a/x/stake/keeper/delegation_test.go b/x/stake/keeper/delegation_test.go index eb318df4d..4b5d12e09 100644 --- a/x/stake/keeper/delegation_test.go +++ b/x/stake/keeper/delegation_test.go @@ -1,6 +1,7 @@ package keeper import ( + "fmt" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -201,19 +202,38 @@ func TestRedelegation(t *testing.T) { keeper.SetRedelegation(ctx, rd) resBond, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) require.True(t, found) - require.True(t, rd.Equal(resBond)) + + fmt.Println("zoo0") + redelegations := keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resBond)) + + fmt.Println("zoo1") + redelegations = keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resBond)) + fmt.Println("zoo2") // check if has the redelegation has = keeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1]) require.True(t, has) + fmt.Println("hoolahoop") // modify a records, save, and retrieve rd.SharesSrc = sdk.NewRat(21) rd.SharesDst = sdk.NewRat(21) + keeper.SetRedelegation(ctx, rd) + resBond, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) require.True(t, found) require.True(t, rd.Equal(resBond)) + fmt.Println("hippo2") + + redelegations = keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resBond)) + fmt.Println("zzzzzzzzzzzzzzzzzzebra") // delete a record keeper.RemoveRedelegation(ctx, rd) diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index 3be009e22..c0f8c8b29 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -6,7 +6,6 @@ import ( "github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/x/stake/types" ) @@ -29,34 +28,39 @@ var ( UnbondingDelegationKey = []byte{0x0B} // key for an unbonding-delegation UnbondingDelegationByValIndexKey = []byte{0x0C} // prefix for each key for an unbonding-delegation, by validator owner RedelegationKey = []byte{0x0D} // key for a redelegation - RedelegationByValSrcIndexKey = []byte{0x0E} // prefix for each key for an redelegation, by validator owner - RedelegationByValDstIndexKey = []byte{0x0F} // prefix for each key for an redelegation, by validator owner + RedelegationByValSrcIndexKey = []byte{0x0E} // prefix for each key for an redelegation, by source validator owner + RedelegationByValDstIndexKey = []byte{0x0F} // prefix for each key for an redelegation, by destination validator owner ) const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch // get the key for the validator with address. -// the value at this key is of type stake/types.Validator +// VALUE: stake/types.Validator func GetValidatorKey(ownerAddr sdk.Address) []byte { return append(ValidatorsKey, ownerAddr.Bytes()...) } // get the key for the validator with pubkey. -// the value at this key should the address for a stake/types.Validator +// VALUE: validator owner address ([]byte) func GetValidatorByPubKeyIndexKey(pubkey crypto.PubKey) []byte { return append(ValidatorsByPubKeyIndexKey, pubkey.Bytes()...) } -// get the key for the current validator group, ordered like tendermint. -// the value at this key is the address of the owner of a validator +// get the key for the current validator group +// VALUE: none (key rearrangement with GetValKeyFromValBondedIndexKey) func GetValidatorsBondedIndexKey(ownerAddr sdk.Address) []byte { return append(ValidatorsBondedIndexKey, ownerAddr.Bytes()...) } +// rearrange the ValBondedIndexKey to get the ValidatorKey +func GetValKeyFromValBondedIndexKey(IndexKey []byte) []byte { + addr := IndexKey[1:] // remove prefix bytes + return GetValidatorKey(addr) +} + // get the validator by power index. power index is the key used in the power-store, // and represents the relative power ranking of the validator. -// the value at this key is of type address, the address being the Address -// of the corresponding validator. +// VALUE: validator owner address ([]byte) func GetValidatorsByPowerIndexKey(validator types.Validator, pool types.Pool) []byte { // NOTE the address doesn't need to be stored because counter bytes must always be different return getValidatorPowerRank(validator, pool) @@ -68,7 +72,6 @@ func getValidatorPowerRank(validator types.Validator, pool types.Pool) []byte { power := validator.EquivalentBondedShares(pool) powerBytes := []byte(power.ToLeftPadded(maxDigitsForAccount)) // power big-endian (more powerful validators first) - // TODO ensure that the key will be a readable string.. probably should add seperators and have revokedBytes := make([]byte, 1) if validator.Revoked { revokedBytes[0] = byte(0x01) @@ -76,7 +79,6 @@ func getValidatorPowerRank(validator types.Validator, pool types.Pool) []byte { revokedBytes[0] = byte(0x00) } - // TODO ensure that the key will be a readable string.. probably should add separators and have // heightBytes and counterBytes represent strings like powerBytes does heightBytes := make([]byte, binary.MaxVarintLen64) binary.BigEndian.PutUint64(heightBytes, ^uint64(validator.BondHeight)) // invert height (older validators first) @@ -90,62 +92,77 @@ func getValidatorPowerRank(validator types.Validator, pool types.Pool) []byte { } // get the key for the accumulated update validators. -// The value at this key is of type stake/types.Validator +// VALUE: none (key rearrangement used) func GetTendermintUpdatesKey(ownerAddr sdk.Address) []byte { return append(TendermintUpdatesKey, ownerAddr.Bytes()...) } +// rearrange the ValBondedIndexKey to get the ValidatorKey +func GetValKeyFromTUIndexKey(IndexKey []byte) []byte { + addr := IndexKey[1:] // remove prefix bytes + return GetValidatorKey(addr) +} + //________________________________________________________________________________ // get the key for delegator bond with validator. -// The value at this key is of type stake/types.Delegation -func GetDelegationKey(delegatorAddr, validatorAddr sdk.Address, cdc *wire.Codec) []byte { - return append(GetDelegationsKey(delegatorAddr, cdc), validatorAddr.Bytes()...) +// VALUE: stake/types.Delegation +func GetDelegationKey(delegatorAddr, validatorAddr sdk.Address) []byte { + return append(GetDelegationsKey(delegatorAddr), validatorAddr.Bytes()...) } // get the prefix for a delegator for all validators -func GetDelegationsKey(delegatorAddr sdk.Address, cdc *wire.Codec) []byte { - res := cdc.MustMarshalBinary(&delegatorAddr) - return append(DelegationKey, res...) +func GetDelegationsKey(delegatorAddr sdk.Address) []byte { + return append(DelegationKey, delegatorAddr.Bytes()...) } //________________________________________________________________________________ // get the key for an unbonding delegation by delegator and validator addr. -// The value at this key is of type stake/types.UnbondingDelegation -func GetUBDKey(delegatorAddr, validatorAddr sdk.Address, cdc *wire.Codec) []byte { - return append(GetUBDsKey(delegatorAddr, cdc), validatorAddr.Bytes()...) +// VALUE: stake/types.UnbondingDelegation +func GetUBDKey(delegatorAddr, validatorAddr sdk.Address) []byte { + return append(GetUBDsKey(delegatorAddr), validatorAddr.Bytes()...) } // get the index-key for an unbonding delegation, stored by validator-index -// The value at this key is a key for the corresponding unbonding delegation. -func GetUBDByValIndexKey(delegatorAddr, validatorAddr sdk.Address, cdc *wire.Codec) []byte { - return append(GetUBDsByValIndexKey(validatorAddr, cdc), delegatorAddr.Bytes()...) +// VALUE: none (key rearrangement used) +func GetUBDByValIndexKey(delegatorAddr, validatorAddr sdk.Address) []byte { + return append(GetUBDsByValIndexKey(validatorAddr), delegatorAddr.Bytes()...) +} + +// rearrange the ValIndexKey to get the UBDKey +func GetUBDKeyFromValIndexKey(IndexKey []byte) []byte { + addrs := IndexKey[1:] // remove prefix bytes + split := len(addrs) / 2 + if (len(addrs) % 2) != 0 { + panic("key length not even") + } + valAddr := addrs[:split] + delAddr := addrs[split:] + return GetUBDKey(delAddr, valAddr) } //______________ // get the prefix for all unbonding delegations from a delegator -func GetUBDsKey(delegatorAddr sdk.Address, cdc *wire.Codec) []byte { - res := cdc.MustMarshalBinary(&delegatorAddr) - return append(UnbondingDelegationKey, res...) +func GetUBDsKey(delegatorAddr sdk.Address) []byte { + return append(UnbondingDelegationKey, delegatorAddr.Bytes()...) } // get the prefix keyspace for the indexes of unbonding delegations for a validator -func GetUBDsByValIndexKey(validatorAddr sdk.Address, cdc *wire.Codec) []byte { - res := cdc.MustMarshalBinary(&validatorAddr) - return append(UnbondingDelegationByValIndexKey, res...) +func GetUBDsByValIndexKey(validatorAddr sdk.Address) []byte { + return append(UnbondingDelegationByValIndexKey, validatorAddr.Bytes()...) } //________________________________________________________________________________ // get the key for a redelegation -// The value at this key is of type stake/types.RedelegationKey +// VALUE: stake/types.RedelegationKey func GetREDKey(delegatorAddr, validatorSrcAddr, - validatorDstAddr sdk.Address, cdc *wire.Codec) []byte { + validatorDstAddr sdk.Address) []byte { return append( - GetREDsKey(delegatorAddr, cdc), + GetREDsKey(delegatorAddr), append( validatorSrcAddr.Bytes(), validatorDstAddr.Bytes()...)..., @@ -153,12 +170,12 @@ func GetREDKey(delegatorAddr, validatorSrcAddr, } // get the index-key for a redelegation, stored by source-validator-index -// The value at this key is a key for the corresponding redelegation. +// VALUE: none (key rearrangement used) func GetREDByValSrcIndexKey(delegatorAddr, validatorSrcAddr, - validatorDstAddr sdk.Address, cdc *wire.Codec) []byte { + validatorDstAddr sdk.Address) []byte { return append( - GetREDsFromValSrcIndexKey(validatorSrcAddr, cdc), + GetREDsFromValSrcIndexKey(validatorSrcAddr), append( delegatorAddr.Bytes(), validatorDstAddr.Bytes()...)..., @@ -166,44 +183,66 @@ func GetREDByValSrcIndexKey(delegatorAddr, validatorSrcAddr, } // get the index-key for a redelegation, stored by destination-validator-index -// The value at this key is a key for the corresponding redelegation. +// VALUE: none (key rearrangement used) func GetREDByValDstIndexKey(delegatorAddr, validatorSrcAddr, - validatorDstAddr sdk.Address, cdc *wire.Codec) []byte { + validatorDstAddr sdk.Address) []byte { return append( - GetREDsToValDstIndexKey(validatorDstAddr, cdc), + GetREDsToValDstIndexKey(validatorDstAddr), append( delegatorAddr.Bytes(), validatorSrcAddr.Bytes()...)..., ) } +// rearrange the ValSrcIndexKey to get the REDKey +func GetREDKeyFromValSrcIndexKey(IndexKey []byte) []byte { + addrs := IndexKey[1:] // remove prefix bytes + split := len(addrs) / 3 + if (len(addrs) % 3) != 0 { + panic("unexpected key length") + } + valSrcAddr := addrs[:split] + delAddr := addrs[split : 2*split] + valDstAddr := addrs[2*split:] + return GetREDKey(delAddr, valSrcAddr, valDstAddr) +} + +// rearrange the ValDstIndexKey to get the REDKey +func GetREDKeyFromValDstIndexKey(IndexKey []byte) []byte { + addrs := IndexKey[1:] // remove prefix bytes + split := len(addrs) / 3 + if (len(addrs) % 3) != 0 { + panic("unexpected key length") + } + valDstAddr := addrs[:split] + delAddr := addrs[split : 2*split] + valSrcAddr := addrs[2*split:] + return GetREDKey(delAddr, valSrcAddr, valDstAddr) +} + //______________ // get the prefix keyspace for redelegations from a delegator -func GetREDsKey(delegatorAddr sdk.Address, cdc *wire.Codec) []byte { - res := cdc.MustMarshalBinary(&delegatorAddr) - return append(RedelegationKey, res...) +func GetREDsKey(delegatorAddr sdk.Address) []byte { + return append(RedelegationKey, delegatorAddr.Bytes()...) } // get the prefix keyspace for all redelegations redelegating away from a source validator -func GetREDsFromValSrcIndexKey(validatorSrcAddr sdk.Address, cdc *wire.Codec) []byte { - res := cdc.MustMarshalBinary(&validatorSrcAddr) - return append(RedelegationByValSrcIndexKey, res...) +func GetREDsFromValSrcIndexKey(validatorSrcAddr sdk.Address) []byte { + return append(RedelegationByValSrcIndexKey, validatorSrcAddr.Bytes()...) } // get the prefix keyspace for all redelegations redelegating towards a destination validator -func GetREDsToValDstIndexKey(validatorDstAddr sdk.Address, cdc *wire.Codec) []byte { - res := cdc.MustMarshalBinary(&validatorDstAddr) - return append(RedelegationByValDstIndexKey, res...) +func GetREDsToValDstIndexKey(validatorDstAddr sdk.Address) []byte { + return append(RedelegationByValDstIndexKey, validatorDstAddr.Bytes()...) } // get the prefix keyspace for all redelegations redelegating towards a destination validator // from a particular delegator func GetREDsByDelToValDstIndexKey(delegatorAddr sdk.Address, - validatorDstAddr sdk.Address, cdc *wire.Codec) []byte { - + validatorDstAddr sdk.Address) []byte { return append( - GetREDsToValDstIndexKey(validatorDstAddr, cdc), + GetREDsToValDstIndexKey(validatorDstAddr), delegatorAddr.Bytes()...) } diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index 55ad658a2..1e4782c86 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -87,7 +87,7 @@ func (k Keeper) Delegation(ctx sdk.Context, addrDel sdk.Address, addrVal sdk.Add // iterate through the active validator set and perform the provided function func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.Address, fn func(index int64, delegation sdk.Delegation) (stop bool)) { store := ctx.KVStore(k.storeKey) - key := GetDelegationsKey(delAddr, k.cdc) + key := GetDelegationsKey(delAddr) iterator := sdk.KVStorePrefixIterator(store, key) i := int64(0) for ; iterator.Valid(); iterator.Next() { From b3d6a59c619a9779a2bb3b9d39c7ae857e710da1 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 2 Jul 2018 18:58:52 -0400 Subject: [PATCH 06/53] ... --- x/stake/keeper/delegation.go | 20 +++++++------- x/stake/keeper/delegation_test.go | 44 ++++++++++++++++++++++++------- x/stake/keeper/key.go | 4 +++ 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 8ede4b55e..0fe4406c3 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -154,26 +154,24 @@ func (k Keeper) GetRedelegation(ctx sdk.Context, func (k Keeper) GetRedelegationsFromValidator(ctx sdk.Context, valAddr sdk.Address) (redelegations []types.Redelegation) { store := ctx.KVStore(k.storeKey) iterator := sdk.KVStorePrefixIterator(store, GetREDsFromValSrcIndexKey(valAddr)) - i := 0 - for ; ; i++ { - fmt.Printf("debug i: %v\n", i) + for { if !iterator.Valid() { break } - redelegationKeyOrig := iterator.Value() - redelegationBytes2 := store.Get(redelegationKeyOrig) - var redelegation2 types.Redelegation - k.cdc.MustUnmarshalBinary(redelegationBytes2, &redelegation2) - fmt.Printf("debug orig redelegation2: %v\n", redelegation2) - redelegationKey := GetREDKeyFromValSrcIndexKey(iterator.Key()) - fmt.Printf("debug orig redelegationKey: %v\n", redelegationKeyOrig) + fmt.Println("called") + //redelegationKey := iterator.Value() + iKey := iterator.Key() + redelegationKey := GetREDKeyFromValSrcIndexKey(iKey) + fmt.Printf("debug iteratorValue: %v\n", iterator.Value()) + fmt.Printf("debug iteratorKey: %v\n", iKey) fmt.Printf("debug redelegationKey: %v\n", redelegationKey) - fmt.Printf("debug iteratorKey: %v\n", iterator.Key()) + redelegationBytes := store.Get(redelegationKey) var redelegation types.Redelegation k.cdc.MustUnmarshalBinary(redelegationBytes, &redelegation) redelegations = append(redelegations, redelegation) + iterator.Next() } iterator.Close() diff --git a/x/stake/keeper/delegation_test.go b/x/stake/keeper/delegation_test.go index 4b5d12e09..90cfb8f37 100644 --- a/x/stake/keeper/delegation_test.go +++ b/x/stake/keeper/delegation_test.go @@ -180,6 +180,40 @@ func TestUnbondDelegation(t *testing.T) { require.Equal(t, int64(4), pool.BondedTokens) } +// tests Get/Set/Remove/Has UnbondingDelegation +func TestGetRedelegationsFromValidator(t *testing.T) { + ctx, _, keeper := CreateTestInput(t, false, 0) + + rd := types.Redelegation{ + DelegatorAddr: addrDels[0], + ValidatorSrcAddr: addrVals[0], + ValidatorDstAddr: addrVals[1], + CreationHeight: 0, + MinTime: 0, + SharesSrc: sdk.NewRat(5), + SharesDst: sdk.NewRat(5), + } + + // set and retrieve a record + keeper.SetRedelegation(ctx, rd) + resBond, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) + require.True(t, found) + fmt.Printf("debug addrDels[0]: %v\n", addrDels[0]) + fmt.Printf("debug addrVals[0]: %v\n", addrVals[0]) + fmt.Printf("debug addrVals[1]: %v\n", addrVals[1]) + + fmt.Println("zoo0") + redelegations := keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resBond)) + + fmt.Println("zoo1") + redelegations = keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resBond)) + fmt.Println("zoo2") +} + // tests Get/Set/Remove/Has UnbondingDelegation func TestRedelegation(t *testing.T) { ctx, _, keeper := CreateTestInput(t, false, 0) @@ -203,21 +237,13 @@ func TestRedelegation(t *testing.T) { resBond, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) require.True(t, found) - fmt.Println("zoo0") redelegations := keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) require.Equal(t, 1, len(redelegations)) require.True(t, redelegations[0].Equal(resBond)) - fmt.Println("zoo1") - redelegations = keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) - require.Equal(t, 1, len(redelegations)) - require.True(t, redelegations[0].Equal(resBond)) - fmt.Println("zoo2") - // check if has the redelegation has = keeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1]) require.True(t, has) - fmt.Println("hoolahoop") // modify a records, save, and retrieve rd.SharesSrc = sdk.NewRat(21) @@ -228,12 +254,10 @@ func TestRedelegation(t *testing.T) { resBond, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) require.True(t, found) require.True(t, rd.Equal(resBond)) - fmt.Println("hippo2") redelegations = keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) require.Equal(t, 1, len(redelegations)) require.True(t, redelegations[0].Equal(resBond)) - fmt.Println("zzzzzzzzzzzzzzzzzzebra") // delete a record keeper.RemoveRedelegation(ctx, rd) diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index c0f8c8b29..248ee9db0 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -2,6 +2,7 @@ package keeper import ( "encoding/binary" + "fmt" "github.com/tendermint/tendermint/crypto" @@ -205,6 +206,9 @@ func GetREDKeyFromValSrcIndexKey(IndexKey []byte) []byte { valSrcAddr := addrs[:split] delAddr := addrs[split : 2*split] valDstAddr := addrs[2*split:] + fmt.Printf("debug delAddr: %v\n", delAddr) + fmt.Printf("debug valSrcAddr: %v\n", valSrcAddr) + fmt.Printf("debug valDstAddr: %v\n", valDstAddr) return GetREDKey(delAddr, valSrcAddr, valDstAddr) } From 2355e5ae6e1ad4d65ffa4434d5bcd1ad3461bf1d Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 2 Jul 2018 20:05:52 -0400 Subject: [PATCH 07/53] ... --- x/stake/keeper/key.go | 2 +- x/stake/types/delegation.go | 43 +++++++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index 248ee9db0..4b9eb5662 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -206,7 +206,7 @@ func GetREDKeyFromValSrcIndexKey(IndexKey []byte) []byte { valSrcAddr := addrs[:split] delAddr := addrs[split : 2*split] valDstAddr := addrs[2*split:] - fmt.Printf("debug delAddr: %v\n", delAddr) + fmt.Printf("debug delAddr: %v\n", delAddr) fmt.Printf("debug valSrcAddr: %v\n", valSrcAddr) fmt.Printf("debug valDstAddr: %v\n", valDstAddr) return GetREDKey(delAddr, valSrcAddr, valDstAddr) diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index eb38a50a7..c945468fd 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -13,8 +13,13 @@ import ( type Delegation struct { DelegatorAddr sdk.Address `json:"delegator_addr"` ValidatorAddr sdk.Address `json:"validator_addr"` - Shares sdk.Rat `json:"shares"` - Height int64 `json:"height"` // Last height bond updated + DelegationValue +} + +// delegation store value +type DelegationValue struct { + Shares sdk.Rat `json:"shares"` + Height int64 `json:"height"` // Last height bond updated } // two are equal @@ -57,12 +62,17 @@ func (d Delegation) HumanReadableString() (string, error) { // element stored to represent the passive unbonding queue type UnbondingDelegation struct { - DelegatorAddr sdk.Address `json:"delegator_addr"` // delegator - ValidatorAddr sdk.Address `json:"validator_addr"` // validator unbonding from owner addr - CreationHeight int64 `json:"creation_height"` // height which the unbonding took place - MinTime int64 `json:"min_time"` // unix time for unbonding completion - InitialBalance sdk.Coin `json:"initial_balance"` // atoms initially scheduled to receive at completion - Balance sdk.Coin `json:"balance"` // atoms to receive at completion + DelegatorAddr sdk.Address `json:"delegator_addr"` // delegator + ValidatorAddr sdk.Address `json:"validator_addr"` // validator unbonding from owner addr + UBDValue +} + +// UBD store value +type UBDValue struct { + CreationHeight int64 `json:"creation_height"` // height which the unbonding took place + MinTime int64 `json:"min_time"` // unix time for unbonding completion + InitialBalance sdk.Coin `json:"initial_balance"` // atoms initially scheduled to receive at completion + Balance sdk.Coin `json:"balance"` // atoms to receive at completion } // nolint @@ -100,12 +110,17 @@ type Redelegation struct { DelegatorAddr sdk.Address `json:"delegator_addr"` // delegator ValidatorSrcAddr sdk.Address `json:"validator_src_addr"` // validator redelegation source owner addr ValidatorDstAddr sdk.Address `json:"validator_dst_addr"` // validator redelegation destination owner addr - CreationHeight int64 `json:"creation_height"` // height which the redelegation took place - MinTime int64 `json:"min_time"` // unix time for redelegation completion - InitialBalance sdk.Coin `json:"initial_balance"` // initial balance when redelegation started - Balance sdk.Coin `json:"balance"` // current balance - SharesSrc sdk.Rat `json:"shares_src"` // amount of source shares redelegating - SharesDst sdk.Rat `json:"shares_dst"` // amount of destination shares redelegating + REDValue +} + +// Redelegation store value +type REDValue struct { + CreationHeight int64 `json:"creation_height"` // height which the redelegation took place + MinTime int64 `json:"min_time"` // unix time for redelegation completion + InitialBalance sdk.Coin `json:"initial_balance"` // initial balance when redelegation started + Balance sdk.Coin `json:"balance"` // current balance + SharesSrc sdk.Rat `json:"shares_src"` // amount of source shares redelegating + SharesDst sdk.Rat `json:"shares_dst"` // amount of destination shares redelegating } // nolint From aa243565ce70893f5cfa5328e51d5c08a518f96b Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 2 Jul 2018 20:09:57 -0400 Subject: [PATCH 08/53] fix appending over key --- x/stake/keeper/delegation.go | 1 + x/stake/keeper/key.go | 25 +++++++++++++++++-------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 0fe4406c3..ded603abd 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -162,6 +162,7 @@ func (k Keeper) GetRedelegationsFromValidator(ctx sdk.Context, valAddr sdk.Addre fmt.Println("called") //redelegationKey := iterator.Value() iKey := iterator.Key() + fmt.Println("LEN IT", len(iKey)) redelegationKey := GetREDKeyFromValSrcIndexKey(iKey) fmt.Printf("debug iteratorValue: %v\n", iterator.Value()) fmt.Printf("debug iteratorKey: %v\n", iKey) diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index 248ee9db0..b831de5f2 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -162,12 +162,13 @@ func GetUBDsByValIndexKey(validatorAddr sdk.Address) []byte { func GetREDKey(delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.Address) []byte { - return append( - GetREDsKey(delegatorAddr), - append( - validatorSrcAddr.Bytes(), - validatorDstAddr.Bytes()...)..., - ) + fmt.Println("KEY", delegatorAddr.Bytes()) + key := make([]byte, len(delegatorAddr.Bytes())) + copy(key, delegatorAddr.Bytes()) + + return append(append( + GetREDsKey(key), validatorSrcAddr.Bytes()...), + validatorDstAddr.Bytes()...) } // get the index-key for a redelegation, stored by source-validator-index @@ -206,10 +207,18 @@ func GetREDKeyFromValSrcIndexKey(IndexKey []byte) []byte { valSrcAddr := addrs[:split] delAddr := addrs[split : 2*split] valDstAddr := addrs[2*split:] - fmt.Printf("debug delAddr: %v\n", delAddr) + fmt.Printf("debug indexKey: %v\n", IndexKey) fmt.Printf("debug valSrcAddr: %v\n", valSrcAddr) + fmt.Printf("debug delAddr: %v\n", delAddr) fmt.Printf("debug valDstAddr: %v\n", valDstAddr) - return GetREDKey(delAddr, valSrcAddr, valDstAddr) + redKey := GetREDKey(delAddr, valSrcAddr, valDstAddr) + fmt.Println("------") + fmt.Printf("debug indexKey: %v\n", IndexKey) + fmt.Printf("debug valSrcAddr: %v\n", valSrcAddr) + fmt.Printf("debug delAddr: %v\n", delAddr) + fmt.Printf("debug valDstAddr: %v\n", valDstAddr) + fmt.Println("") + return redKey } // rearrange the ValDstIndexKey to get the REDKey From 6f3b4c18056fe32520edf985e3d5d492c54780c7 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 2 Jul 2018 20:58:22 -0400 Subject: [PATCH 09/53] keys cleanup --- x/stake/keeper/delegation.go | 21 +++-------- x/stake/keeper/delegation_test.go | 8 ----- x/stake/keeper/key.go | 27 +++++++------- x/stake/keeper/sdk_types.go | 2 +- x/stake/keeper/validator.go | 8 ++--- x/stake/types/delegation.go | 58 +++++++++++++++++++------------ 6 files changed, 57 insertions(+), 67 deletions(-) diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index ded603abd..bb8170a6a 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -2,7 +2,6 @@ package keeper import ( "bytes" - "fmt" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" @@ -100,8 +99,7 @@ func (k Keeper) GetUnbondingDelegation(ctx sdk.Context, func (k Keeper) GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr sdk.Address) (unbondingDelegations []types.UnbondingDelegation) { store := ctx.KVStore(k.storeKey) iterator := sdk.KVStorePrefixIterator(store, GetUBDsByValIndexKey(valAddr)) - i := 0 - for ; ; i++ { + for { if !iterator.Valid() { break } @@ -158,21 +156,11 @@ func (k Keeper) GetRedelegationsFromValidator(ctx sdk.Context, valAddr sdk.Addre if !iterator.Valid() { break } - - fmt.Println("called") - //redelegationKey := iterator.Value() - iKey := iterator.Key() - fmt.Println("LEN IT", len(iKey)) - redelegationKey := GetREDKeyFromValSrcIndexKey(iKey) - fmt.Printf("debug iteratorValue: %v\n", iterator.Value()) - fmt.Printf("debug iteratorKey: %v\n", iKey) - fmt.Printf("debug redelegationKey: %v\n", redelegationKey) - + redelegationKey := GetREDKeyFromValSrcIndexKey(iterator.Key()) redelegationBytes := store.Get(redelegationKey) var redelegation types.Redelegation k.cdc.MustUnmarshalBinary(redelegationBytes, &redelegation) redelegations = append(redelegations, redelegation) - iterator.Next() } iterator.Close() @@ -201,10 +189,9 @@ func (k Keeper) SetRedelegation(ctx sdk.Context, red types.Redelegation) { store := ctx.KVStore(k.storeKey) bz := k.cdc.MustMarshalBinary(red) redKey := GetREDKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr) - fmt.Printf("debug redKey: %v\n", redKey) store.Set(redKey, bz) - store.Set(GetREDByValSrcIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr), redKey) //[]byte{}) - store.Set(GetREDByValDstIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr), redKey) // []byte{}) + store.Set(GetREDByValSrcIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr), []byte{}) + store.Set(GetREDByValDstIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr), []byte{}) } // remove a redelegation object and associated index diff --git a/x/stake/keeper/delegation_test.go b/x/stake/keeper/delegation_test.go index 90cfb8f37..a7cb566f1 100644 --- a/x/stake/keeper/delegation_test.go +++ b/x/stake/keeper/delegation_test.go @@ -1,7 +1,6 @@ package keeper import ( - "fmt" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -198,20 +197,14 @@ func TestGetRedelegationsFromValidator(t *testing.T) { keeper.SetRedelegation(ctx, rd) resBond, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) require.True(t, found) - fmt.Printf("debug addrDels[0]: %v\n", addrDels[0]) - fmt.Printf("debug addrVals[0]: %v\n", addrVals[0]) - fmt.Printf("debug addrVals[1]: %v\n", addrVals[1]) - fmt.Println("zoo0") redelegations := keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) require.Equal(t, 1, len(redelegations)) require.True(t, redelegations[0].Equal(resBond)) - fmt.Println("zoo1") redelegations = keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) require.Equal(t, 1, len(redelegations)) require.True(t, redelegations[0].Equal(resBond)) - fmt.Println("zoo2") } // tests Get/Set/Remove/Has UnbondingDelegation @@ -248,7 +241,6 @@ func TestRedelegation(t *testing.T) { // modify a records, save, and retrieve rd.SharesSrc = sdk.NewRat(21) rd.SharesDst = sdk.NewRat(21) - keeper.SetRedelegation(ctx, rd) resBond, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index 50d08e425..6924a1057 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -2,7 +2,6 @@ package keeper import ( "encoding/binary" - "fmt" "github.com/tendermint/tendermint/crypto" @@ -54,9 +53,8 @@ func GetValidatorsBondedIndexKey(ownerAddr sdk.Address) []byte { } // rearrange the ValBondedIndexKey to get the ValidatorKey -func GetValKeyFromValBondedIndexKey(IndexKey []byte) []byte { - addr := IndexKey[1:] // remove prefix bytes - return GetValidatorKey(addr) +func GetAddressFromValBondedIndexKey(IndexKey []byte) []byte { + return IndexKey[1:] // remove prefix bytes } // get the validator by power index. power index is the key used in the power-store, @@ -93,17 +91,12 @@ func getValidatorPowerRank(validator types.Validator, pool types.Pool) []byte { } // get the key for the accumulated update validators. -// VALUE: none (key rearrangement used) +// VALUE: abci.Validator +// note records using these keys should never persist between blocks func GetTendermintUpdatesKey(ownerAddr sdk.Address) []byte { return append(TendermintUpdatesKey, ownerAddr.Bytes()...) } -// rearrange the ValBondedIndexKey to get the ValidatorKey -func GetValKeyFromTUIndexKey(IndexKey []byte) []byte { - addr := IndexKey[1:] // remove prefix bytes - return GetValidatorKey(addr) -} - //________________________________________________________________________________ // get the key for delegator bond with validator. @@ -122,7 +115,13 @@ func GetDelegationsKey(delegatorAddr sdk.Address) []byte { // get the key for an unbonding delegation by delegator and validator addr. // VALUE: stake/types.UnbondingDelegation func GetUBDKey(delegatorAddr, validatorAddr sdk.Address) []byte { - return append(GetUBDsKey(delegatorAddr), validatorAddr.Bytes()...) + + key := make([]byte, len(delegatorAddr.Bytes())) + copy(key, delegatorAddr.Bytes()) + + return append( + GetUBDsKey(key), + validatorAddr.Bytes()...) } // get the index-key for an unbonding delegation, stored by validator-index @@ -162,12 +161,12 @@ func GetUBDsByValIndexKey(validatorAddr sdk.Address) []byte { func GetREDKey(delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.Address) []byte { - fmt.Println("KEY", delegatorAddr.Bytes()) key := make([]byte, len(delegatorAddr.Bytes())) copy(key, delegatorAddr.Bytes()) return append(append( - GetREDsKey(key), validatorSrcAddr.Bytes()...), + GetREDsKey(key), + validatorSrcAddr.Bytes()...), validatorDstAddr.Bytes()...) } diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index 1e4782c86..bedbc1559 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -34,7 +34,7 @@ func (k Keeper) IterateValidatorsBonded(ctx sdk.Context, fn func(index int64, va iterator := sdk.KVStorePrefixIterator(store, ValidatorsBondedIndexKey) i := int64(0) for ; iterator.Valid(); iterator.Next() { - address := iterator.Value() + address := GetAddressFromValBondedIndexKey(iterator.Key()) validator, found := k.GetValidator(ctx, address) if !found { panic(fmt.Sprintf("validator record not found for address: %v\n", address)) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 0d556f7dc..c2711788b 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -56,7 +56,7 @@ func (k Keeper) SetValidatorByPowerIndex(ctx sdk.Context, validator types.Valida // validator index func (k Keeper) SetValidatorBondedIndex(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) - store.Set(GetValidatorsBondedIndexKey(validator.Owner), validator.Owner) + store.Set(GetValidatorsBondedIndexKey(validator.Owner), []byte{}) } // used in testing @@ -124,7 +124,7 @@ func (k Keeper) GetValidatorsBonded(ctx sdk.Context) (validators []types.Validat if i > int(maxValidators-1) { panic("maxValidators is less than the number of records in ValidatorsBonded Store, store should have been updated") } - address := iterator.Value() + address := GetAddressFromValBondedIndexKey(iterator.Key()) validator, found := k.GetValidator(ctx, address) if !found { panic(fmt.Sprintf("validator record not found for address: %v\n", address)) @@ -362,7 +362,7 @@ func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) { toKickOut := make(map[string]byte) iterator := sdk.KVStorePrefixIterator(store, ValidatorsBondedIndexKey) for ; iterator.Valid(); iterator.Next() { - ownerAddr := iterator.Value() + ownerAddr := GetAddressFromValBondedIndexKey(iterator.Key()) toKickOut[string(ownerAddr)] = 0 // set anything } iterator.Close() @@ -471,7 +471,7 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. // save the now bonded validator record to the three referenced stores bzVal := k.cdc.MustMarshalBinary(validator) store.Set(GetValidatorKey(validator.Owner), bzVal) - store.Set(GetValidatorsBondedIndexKey(validator.Owner), validator.Owner) + store.Set(GetValidatorsBondedIndexKey(validator.Owner), []byte{}) // add to accumulated changes for tendermint bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidator()) diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index c945468fd..daaeecef1 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -13,14 +13,16 @@ import ( type Delegation struct { DelegatorAddr sdk.Address `json:"delegator_addr"` ValidatorAddr sdk.Address `json:"validator_addr"` - DelegationValue + Shares sdk.Rat `json:"shares"` + Height int64 `json:"height"` // Last height bond updated + //DelegationValue } // delegation store value -type DelegationValue struct { - Shares sdk.Rat `json:"shares"` - Height int64 `json:"height"` // Last height bond updated -} +//type DelegationValue struct { +//Shares sdk.Rat `json:"shares"` +//Height int64 `json:"height"` // Last height bond updated +//} // two are equal func (d Delegation) Equal(d2 Delegation) bool { @@ -62,18 +64,22 @@ func (d Delegation) HumanReadableString() (string, error) { // element stored to represent the passive unbonding queue type UnbondingDelegation struct { - DelegatorAddr sdk.Address `json:"delegator_addr"` // delegator - ValidatorAddr sdk.Address `json:"validator_addr"` // validator unbonding from owner addr - UBDValue + DelegatorAddr sdk.Address `json:"delegator_addr"` // delegator + ValidatorAddr sdk.Address `json:"validator_addr"` // validator unbonding from owner addr + CreationHeight int64 `json:"creation_height"` // height which the unbonding took place + MinTime int64 `json:"min_time"` // unix time for unbonding completion + InitialBalance sdk.Coin `json:"initial_balance"` // atoms initially scheduled to receive at completion + Balance sdk.Coin `json:"balance"` // atoms to receive at completion + //UBDValue } // UBD store value -type UBDValue struct { - CreationHeight int64 `json:"creation_height"` // height which the unbonding took place - MinTime int64 `json:"min_time"` // unix time for unbonding completion - InitialBalance sdk.Coin `json:"initial_balance"` // atoms initially scheduled to receive at completion - Balance sdk.Coin `json:"balance"` // atoms to receive at completion -} +//type UBDValue struct { +//CreationHeight int64 `json:"creation_height"` // height which the unbonding took place +//MinTime int64 `json:"min_time"` // unix time for unbonding completion +//InitialBalance sdk.Coin `json:"initial_balance"` // atoms initially scheduled to receive at completion +//Balance sdk.Coin `json:"balance"` // atoms to receive at completion +//} // nolint func (d UnbondingDelegation) Equal(d2 UnbondingDelegation) bool { @@ -110,18 +116,24 @@ type Redelegation struct { DelegatorAddr sdk.Address `json:"delegator_addr"` // delegator ValidatorSrcAddr sdk.Address `json:"validator_src_addr"` // validator redelegation source owner addr ValidatorDstAddr sdk.Address `json:"validator_dst_addr"` // validator redelegation destination owner addr - REDValue + CreationHeight int64 `json:"creation_height"` // height which the redelegation took place + MinTime int64 `json:"min_time"` // unix time for redelegation completion + InitialBalance sdk.Coin `json:"initial_balance"` // initial balance when redelegation started + Balance sdk.Coin `json:"balance"` // current balance + SharesSrc sdk.Rat `json:"shares_src"` // amount of source shares redelegating + SharesDst sdk.Rat `json:"shares_dst"` // amount of destination shares redelegating + //REDValue } // Redelegation store value -type REDValue struct { - CreationHeight int64 `json:"creation_height"` // height which the redelegation took place - MinTime int64 `json:"min_time"` // unix time for redelegation completion - InitialBalance sdk.Coin `json:"initial_balance"` // initial balance when redelegation started - Balance sdk.Coin `json:"balance"` // current balance - SharesSrc sdk.Rat `json:"shares_src"` // amount of source shares redelegating - SharesDst sdk.Rat `json:"shares_dst"` // amount of destination shares redelegating -} +//type REDValue struct { +//CreationHeight int64 `json:"creation_height"` // height which the redelegation took place +//MinTime int64 `json:"min_time"` // unix time for redelegation completion +//InitialBalance sdk.Coin `json:"initial_balance"` // initial balance when redelegation started +//Balance sdk.Coin `json:"balance"` // current balance +//SharesSrc sdk.Rat `json:"shares_src"` // amount of source shares redelegating +//SharesDst sdk.Rat `json:"shares_dst"` // amount of destination shares redelegating +//} // nolint func (d Redelegation) Equal(d2 Redelegation) bool { From aec264d92302d2f22e9122c60ccd29290d0e4a40 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 2 Jul 2018 21:06:05 -0400 Subject: [PATCH 10/53] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b261e7d84..4dea6d7f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ BREAKING CHANGES * Add REST endpoint to unrevoke a validator previously revoked for downtime * Add REST endpoint to retrieve liveness signing information for a validator * [types] renamed rational.Evaluate to rational.Round{Int64, Int} +* [stake] most index keys nolonger hold a value - inputs are rearranged to form the desired key FEATURES * [gaiacli] You can now attach a simple text-only memo to any transaction, with the `--memo` flag From 271fbb2db3a5946f20ba34891bdedc77a9b15e15 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 2 Jul 2018 21:16:32 -0400 Subject: [PATCH 11/53] remove some junk --- x/stake/types/delegation.go | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index daaeecef1..eb38a50a7 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -15,15 +15,8 @@ type Delegation struct { ValidatorAddr sdk.Address `json:"validator_addr"` Shares sdk.Rat `json:"shares"` Height int64 `json:"height"` // Last height bond updated - //DelegationValue } -// delegation store value -//type DelegationValue struct { -//Shares sdk.Rat `json:"shares"` -//Height int64 `json:"height"` // Last height bond updated -//} - // two are equal func (d Delegation) Equal(d2 Delegation) bool { return bytes.Equal(d.DelegatorAddr, d2.DelegatorAddr) && @@ -70,17 +63,8 @@ type UnbondingDelegation struct { MinTime int64 `json:"min_time"` // unix time for unbonding completion InitialBalance sdk.Coin `json:"initial_balance"` // atoms initially scheduled to receive at completion Balance sdk.Coin `json:"balance"` // atoms to receive at completion - //UBDValue } -// UBD store value -//type UBDValue struct { -//CreationHeight int64 `json:"creation_height"` // height which the unbonding took place -//MinTime int64 `json:"min_time"` // unix time for unbonding completion -//InitialBalance sdk.Coin `json:"initial_balance"` // atoms initially scheduled to receive at completion -//Balance sdk.Coin `json:"balance"` // atoms to receive at completion -//} - // nolint func (d UnbondingDelegation) Equal(d2 UnbondingDelegation) bool { bz1 := MsgCdc.MustMarshalBinary(&d) @@ -122,19 +106,8 @@ type Redelegation struct { Balance sdk.Coin `json:"balance"` // current balance SharesSrc sdk.Rat `json:"shares_src"` // amount of source shares redelegating SharesDst sdk.Rat `json:"shares_dst"` // amount of destination shares redelegating - //REDValue } -// Redelegation store value -//type REDValue struct { -//CreationHeight int64 `json:"creation_height"` // height which the redelegation took place -//MinTime int64 `json:"min_time"` // unix time for redelegation completion -//InitialBalance sdk.Coin `json:"initial_balance"` // initial balance when redelegation started -//Balance sdk.Coin `json:"balance"` // current balance -//SharesSrc sdk.Rat `json:"shares_src"` // amount of source shares redelegating -//SharesDst sdk.Rat `json:"shares_dst"` // amount of destination shares redelegating -//} - // nolint func (d Redelegation) Equal(d2 Redelegation) bool { bz1 := MsgCdc.MustMarshalBinary(&d) From 4f0c7d8746e3e0d4315888dac72869034ed336a0 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 3 Jul 2018 13:37:17 -0400 Subject: [PATCH 12/53] address bucky comments - rearrange appends --- x/stake/keeper/delegation_test.go | 4 +++- x/stake/keeper/key.go | 39 ++++++++++++------------------- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/x/stake/keeper/delegation_test.go b/x/stake/keeper/delegation_test.go index a7cb566f1..c0a3ee8c5 100644 --- a/x/stake/keeper/delegation_test.go +++ b/x/stake/keeper/delegation_test.go @@ -179,7 +179,7 @@ func TestUnbondDelegation(t *testing.T) { require.Equal(t, int64(4), pool.BondedTokens) } -// tests Get/Set/Remove/Has UnbondingDelegation +// Make sure that that the retrieving the delegations doesn't affect the state func TestGetRedelegationsFromValidator(t *testing.T) { ctx, _, keeper := CreateTestInput(t, false, 0) @@ -198,10 +198,12 @@ func TestGetRedelegationsFromValidator(t *testing.T) { resBond, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) require.True(t, found) + // get the redelegations one time redelegations := keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) require.Equal(t, 1, len(redelegations)) require.True(t, redelegations[0].Equal(resBond)) + // get the redelegations a second time, should be exactly the same redelegations = keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) require.Equal(t, 1, len(redelegations)) require.True(t, redelegations[0].Equal(resBond)) diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index 6924a1057..4d1ad0bae 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -52,7 +52,7 @@ func GetValidatorsBondedIndexKey(ownerAddr sdk.Address) []byte { return append(ValidatorsBondedIndexKey, ownerAddr.Bytes()...) } -// rearrange the ValBondedIndexKey to get the ValidatorKey +// Get the validator owner address from ValBondedIndexKey func GetAddressFromValBondedIndexKey(IndexKey []byte) []byte { return IndexKey[1:] // remove prefix bytes } @@ -84,10 +84,12 @@ func getValidatorPowerRank(validator types.Validator, pool types.Pool) []byte { counterBytes := make([]byte, 2) binary.BigEndian.PutUint16(counterBytes, ^uint16(validator.BondIntraTxCounter)) // invert counter (first txns have priority) - return append(ValidatorsByPowerIndexKey, - append(revokedBytes, - append(powerBytes, - append(heightBytes, counterBytes...)...)...)...) + return append(append(append(append( + ValidatorsByPowerIndexKey, + revokedBytes...), + powerBytes...), + heightBytes...), + counterBytes...) } // get the key for the accumulated update validators. @@ -115,12 +117,8 @@ func GetDelegationsKey(delegatorAddr sdk.Address) []byte { // get the key for an unbonding delegation by delegator and validator addr. // VALUE: stake/types.UnbondingDelegation func GetUBDKey(delegatorAddr, validatorAddr sdk.Address) []byte { - - key := make([]byte, len(delegatorAddr.Bytes())) - copy(key, delegatorAddr.Bytes()) - return append( - GetUBDsKey(key), + GetUBDsKey(delegatorAddr.Bytes()), validatorAddr.Bytes()...) } @@ -161,11 +159,8 @@ func GetUBDsByValIndexKey(validatorAddr sdk.Address) []byte { func GetREDKey(delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.Address) []byte { - key := make([]byte, len(delegatorAddr.Bytes())) - copy(key, delegatorAddr.Bytes()) - return append(append( - GetREDsKey(key), + GetREDsKey(delegatorAddr.Bytes()), validatorSrcAddr.Bytes()...), validatorDstAddr.Bytes()...) } @@ -175,12 +170,10 @@ func GetREDKey(delegatorAddr, validatorSrcAddr, func GetREDByValSrcIndexKey(delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.Address) []byte { - return append( + return append(append( GetREDsFromValSrcIndexKey(validatorSrcAddr), - append( - delegatorAddr.Bytes(), - validatorDstAddr.Bytes()...)..., - ) + delegatorAddr.Bytes()...), + validatorDstAddr.Bytes()...) } // get the index-key for a redelegation, stored by destination-validator-index @@ -188,12 +181,10 @@ func GetREDByValSrcIndexKey(delegatorAddr, validatorSrcAddr, func GetREDByValDstIndexKey(delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.Address) []byte { - return append( + return append(append( GetREDsToValDstIndexKey(validatorDstAddr), - append( - delegatorAddr.Bytes(), - validatorSrcAddr.Bytes()...)..., - ) + delegatorAddr.Bytes()...), + validatorSrcAddr.Bytes()...) } // rearrange the ValSrcIndexKey to get the REDKey From ab964da10568b7ff1872dc754160c87312e940bf Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 3 Jul 2018 15:03:35 -0400 Subject: [PATCH 13/53] marshal/unmarshal delegation --- x/stake/types/delegation.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index eb38a50a7..705dcb6cd 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -5,6 +5,7 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/wire" ) // Delegation represents the bond with tokens held by an account. It is @@ -17,6 +18,41 @@ type Delegation struct { Height int64 `json:"height"` // Last height bond updated } +type delegationValue struct { + Shares sdk.Rat + Height int64 +} + +// return the delegation without fields contained within the key for the store +func MarshalDelegation(cdc *wire.Codec, delegation Delegation) []byte { + val := delegationValue{ + delegation.Shares, + delegation.Height, + } + return cdc.MustMarshalBinary(val) +} + +// return the delegation without fields contained within the key for the store +func UnmarshalDelegation(cdc *wire.Codec, key, value []byte) Delegation { + var storeValue delegationValue + cdc.MustUnmarshalBinary(value, &storeValue) + + addrs := IndexKey[1:] // remove prefix bytes + split := len(addrs) / 2 + if (len(addrs) % 2) != 0 { + panic("key length not even") + } + delAddr := sdk.Address{addrs[:split]} + valAddr := sdk.Address{addrs[split:]} + + return Delegation{ + DelegatorAddr: delAddr, + ValidatorAddr: valAddr, + Shares: storeValue.Shares, + Height: storeValue.Height, + } +} + // two are equal func (d Delegation) Equal(d2 Delegation) bool { return bytes.Equal(d.DelegatorAddr, d2.DelegatorAddr) && From 270e2162622446994fb3ef17a5d141e7d4aa31df Mon Sep 17 00:00:00 2001 From: Jack Zampolin Date: Tue, 3 Jul 2018 15:10:56 -0700 Subject: [PATCH 14/53] Merge PR #1512: Add Ledger Instructions * Add ledger instructions * Address PR comments --- docs/clients/ledger.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 docs/clients/ledger.md diff --git a/docs/clients/ledger.md b/docs/clients/ledger.md new file mode 100644 index 000000000..9f6386715 --- /dev/null +++ b/docs/clients/ledger.md @@ -0,0 +1,29 @@ +# Ledger // Cosmos + +### Ledger Support for account keys + +`gaiacli` now supports derivation of account keys from a Ledger seed. To use this functionality you will need the following: + +- A running `gaiad` instance connected to the network you wish to use. +- A `gaiacli` instance configured to connect to your chosen `gaiad` instance. +- A LedgerNano with the `ledger-cosmos` app installed + * Install the Cosmos app onto your Ledger by following the instructions in the [`ledger-cosmos`](https://github.com/cosmos/ledger-cosmos/blob/master/docs/BUILD.md) repository. + * A production-ready version of this app will soon be included in the [Ledger Apps Store](https://www.ledgerwallet.com/apps) + +> **NOTE:** Cosmos keys are derived acording to the [BIP 44 Hierarchical Deterministic wallet spec](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki). For more information on Cosmos derivation paths [see the hd package](https://github.com/cosmos/cosmos-sdk/blob/develop/crypto/keys/hd/hdpath.go#L30). + +Once you have the Cosmos app installed on your Ledger, and the Ledger is accessible from the machine you are using `gaiacli` from you can create a new account key using the Ledger: + +```bash +$ gaiacli keys add {{ .Key.Name }} --ledger +NAME: TYPE: ADDRESS: PUBKEY: +{{ .Key.Name }} ledger cosmosaccaddr1aw64xxr80lwqqdk8u2xhlrkxqaxamkr3e2g943 cosmosaccpub1addwnpepqvhs678gh9aqrjc2tg2vezw86csnvgzqq530ujkunt5tkuc7lhjkz5mj629 +``` + +This key will only be accessible while the Ledger is plugged in and unlocked. To send some coins with this key, run the following: + +```bash +$ gaiacli send --name {{ .Key.Name }} --to {{ .Destination.AccAddr }} --chain-id=gaia-7000 +``` + +You will be asked to review and confirm the transaction on the Ledger. Once you do this you should see the result in the console! Now you can use your Ledger to manage your Atoms and Stake! From cae6b40221979ded236c0fb0bad2859434b0f086 Mon Sep 17 00:00:00 2001 From: Rigel Date: Tue, 3 Jul 2018 19:15:48 -0400 Subject: [PATCH 15/53] Merge pull request #1467: staking index keys don't hold values * docs: Explain the expected return type within the store (#1452) * bug somewhere here * ... * ... * fix appending over key * keys cleanup * changelog * remove some junk * address bucky comments - rearrange appends * hard code address length --- CHANGELOG.md | 2 + x/stake/client/cli/query.go | 12 +- x/stake/client/cli/tx.go | 2 +- x/stake/client/rest/query.go | 6 +- x/stake/keeper/delegation.go | 48 ++++---- x/stake/keeper/delegation_test.go | 40 ++++++- x/stake/keeper/key.go | 182 ++++++++++++++++++------------ x/stake/keeper/sdk_types.go | 4 +- x/stake/keeper/validator.go | 8 +- 9 files changed, 192 insertions(+), 112 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecba00362..56bad46c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,8 @@ BREAKING CHANGES to an infraction, slash them proportional to their stake at the time * Add REST endpoint to unrevoke a validator previously revoked for downtime * Add REST endpoint to retrieve liveness signing information for a validator +* [types] renamed rational.Evaluate to rational.Round{Int64, Int} +* [stake] most index keys nolonger hold a value - inputs are rearranged to form the desired key * [lcd] Switch key creation output to return bech32 FEATURES diff --git a/x/stake/client/cli/query.go b/x/stake/client/cli/query.go index bccfd7c2b..5a22f2c41 100644 --- a/x/stake/client/cli/query.go +++ b/x/stake/client/cli/query.go @@ -122,7 +122,7 @@ func GetCmdQueryDelegation(storeName string, cdc *wire.Codec) *cobra.Command { return err } - key := stake.GetDelegationKey(delAddr, valAddr, cdc) + key := stake.GetDelegationKey(delAddr, valAddr) ctx := context.NewCoreContextFromViper() res, err := ctx.QueryStore(key, storeName) if err != nil { @@ -169,7 +169,7 @@ func GetCmdQueryDelegations(storeName string, cdc *wire.Codec) *cobra.Command { if err != nil { return err } - key := stake.GetDelegationsKey(delegatorAddr, cdc) + key := stake.GetDelegationsKey(delegatorAddr) ctx := context.NewCoreContextFromViper() resKVs, err := ctx.QuerySubspace(cdc, key, storeName) if err != nil { @@ -214,7 +214,7 @@ func GetCmdQueryUnbondingDelegation(storeName string, cdc *wire.Codec) *cobra.Co return err } - key := stake.GetUBDKey(delAddr, valAddr, cdc) + key := stake.GetUBDKey(delAddr, valAddr) ctx := context.NewCoreContextFromViper() res, err := ctx.QueryStore(key, storeName) if err != nil { @@ -261,7 +261,7 @@ func GetCmdQueryUnbondingDelegations(storeName string, cdc *wire.Codec) *cobra.C if err != nil { return err } - key := stake.GetUBDsKey(delegatorAddr, cdc) + key := stake.GetUBDsKey(delegatorAddr) ctx := context.NewCoreContextFromViper() resKVs, err := ctx.QuerySubspace(cdc, key, storeName) if err != nil { @@ -309,7 +309,7 @@ func GetCmdQueryRedelegation(storeName string, cdc *wire.Codec) *cobra.Command { return err } - key := stake.GetREDKey(delAddr, valSrcAddr, valDstAddr, cdc) + key := stake.GetREDKey(delAddr, valSrcAddr, valDstAddr) ctx := context.NewCoreContextFromViper() res, err := ctx.QueryStore(key, storeName) if err != nil { @@ -356,7 +356,7 @@ func GetCmdQueryRedelegations(storeName string, cdc *wire.Codec) *cobra.Command if err != nil { return err } - key := stake.GetREDsKey(delegatorAddr, cdc) + key := stake.GetREDsKey(delegatorAddr) ctx := context.NewCoreContextFromViper() resKVs, err := ctx.QuerySubspace(cdc, key, storeName) if err != nil { diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index dff765fac..7200caef3 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -240,7 +240,7 @@ func getShares(storeName string, cdc *wire.Codec, sharesAmountStr, sharesPercent } // make a query to get the existing delegation shares - key := stake.GetDelegationKey(delegatorAddr, validatorAddr, cdc) + key := stake.GetDelegationKey(delegatorAddr, validatorAddr) ctx := context.NewCoreContextFromViper() resQuery, err := ctx.QueryStore(key, storeName) if err != nil { diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index afa9e3bf0..12ef882e5 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -60,7 +60,7 @@ func delegationHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerF return } - key := stake.GetDelegationKey(delegatorAddr, validatorAddr, cdc) + key := stake.GetDelegationKey(delegatorAddr, validatorAddr) res, err := ctx.QueryStore(key, storeName) if err != nil { @@ -117,7 +117,7 @@ func ubdHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerFunc { return } - key := stake.GetUBDKey(delegatorAddr, validatorAddr, cdc) + key := stake.GetUBDKey(delegatorAddr, validatorAddr) res, err := ctx.QueryStore(key, storeName) if err != nil { @@ -182,7 +182,7 @@ func redHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerFunc { return } - key := stake.GetREDKey(delegatorAddr, validatorSrcAddr, validatorDstAddr, cdc) + key := stake.GetREDKey(delegatorAddr, validatorSrcAddr, validatorDstAddr) res, err := ctx.QueryStore(key, storeName) if err != nil { diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 514939e17..bb8170a6a 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -12,7 +12,7 @@ func (k Keeper) GetDelegation(ctx sdk.Context, delegatorAddr, validatorAddr sdk.Address) (delegation types.Delegation, found bool) { store := ctx.KVStore(k.storeKey) - delegatorBytes := store.Get(GetDelegationKey(delegatorAddr, validatorAddr, k.cdc)) + delegatorBytes := store.Get(GetDelegationKey(delegatorAddr, validatorAddr)) if delegatorBytes == nil { return delegation, false } @@ -46,7 +46,7 @@ func (k Keeper) GetDelegations(ctx sdk.Context, delegator sdk.Address, maxRetrieve int16) (delegations []types.Delegation) { store := ctx.KVStore(k.storeKey) - delegatorPrefixKey := GetDelegationsKey(delegator, k.cdc) + delegatorPrefixKey := GetDelegationsKey(delegator) iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) //smallest to largest delegations = make([]types.Delegation, maxRetrieve) @@ -69,13 +69,13 @@ func (k Keeper) GetDelegations(ctx sdk.Context, delegator sdk.Address, func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { store := ctx.KVStore(k.storeKey) b := k.cdc.MustMarshalBinary(delegation) - store.Set(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr, k.cdc), b) + store.Set(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr), b) } // remove the delegation func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) { store := ctx.KVStore(k.storeKey) - store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr, k.cdc)) + store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr)) } //_____________________________________________________________________________________ @@ -85,7 +85,7 @@ func (k Keeper) GetUnbondingDelegation(ctx sdk.Context, DelegatorAddr, ValidatorAddr sdk.Address) (ubd types.UnbondingDelegation, found bool) { store := ctx.KVStore(k.storeKey) - ubdKey := GetUBDKey(DelegatorAddr, ValidatorAddr, k.cdc) + ubdKey := GetUBDKey(DelegatorAddr, ValidatorAddr) bz := store.Get(ubdKey) if bz == nil { return ubd, false @@ -98,13 +98,12 @@ func (k Keeper) GetUnbondingDelegation(ctx sdk.Context, // load all unbonding delegations from a particular validator func (k Keeper) GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr sdk.Address) (unbondingDelegations []types.UnbondingDelegation) { store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, GetUBDsByValIndexKey(valAddr, k.cdc)) - i := 0 - for ; ; i++ { + iterator := sdk.KVStorePrefixIterator(store, GetUBDsByValIndexKey(valAddr)) + for { if !iterator.Valid() { break } - unbondingKey := iterator.Value() + unbondingKey := GetUBDKeyFromValIndexKey(iterator.Key()) unbondingBytes := store.Get(unbondingKey) var unbondingDelegation types.UnbondingDelegation k.cdc.MustUnmarshalBinary(unbondingBytes, &unbondingDelegation) @@ -119,17 +118,17 @@ func (k Keeper) GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr sd func (k Keeper) SetUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDelegation) { store := ctx.KVStore(k.storeKey) bz := k.cdc.MustMarshalBinary(ubd) - ubdKey := GetUBDKey(ubd.DelegatorAddr, ubd.ValidatorAddr, k.cdc) + ubdKey := GetUBDKey(ubd.DelegatorAddr, ubd.ValidatorAddr) store.Set(ubdKey, bz) - store.Set(GetUBDByValIndexKey(ubd.DelegatorAddr, ubd.ValidatorAddr, k.cdc), ubdKey) + store.Set(GetUBDByValIndexKey(ubd.DelegatorAddr, ubd.ValidatorAddr), []byte{}) } // remove the unbonding delegation object and associated index func (k Keeper) RemoveUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDelegation) { store := ctx.KVStore(k.storeKey) - ubdKey := GetUBDKey(ubd.DelegatorAddr, ubd.ValidatorAddr, k.cdc) + ubdKey := GetUBDKey(ubd.DelegatorAddr, ubd.ValidatorAddr) store.Delete(ubdKey) - store.Delete(GetUBDByValIndexKey(ubd.DelegatorAddr, ubd.ValidatorAddr, k.cdc)) + store.Delete(GetUBDByValIndexKey(ubd.DelegatorAddr, ubd.ValidatorAddr)) } //_____________________________________________________________________________________ @@ -139,7 +138,7 @@ func (k Keeper) GetRedelegation(ctx sdk.Context, DelegatorAddr, ValidatorSrcAddr, ValidatorDstAddr sdk.Address) (red types.Redelegation, found bool) { store := ctx.KVStore(k.storeKey) - redKey := GetREDKey(DelegatorAddr, ValidatorSrcAddr, ValidatorDstAddr, k.cdc) + redKey := GetREDKey(DelegatorAddr, ValidatorSrcAddr, ValidatorDstAddr) bz := store.Get(redKey) if bz == nil { return red, false @@ -152,13 +151,12 @@ func (k Keeper) GetRedelegation(ctx sdk.Context, // load all redelegations from a particular validator func (k Keeper) GetRedelegationsFromValidator(ctx sdk.Context, valAddr sdk.Address) (redelegations []types.Redelegation) { store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, GetREDsFromValSrcIndexKey(valAddr, k.cdc)) - i := 0 - for ; ; i++ { + iterator := sdk.KVStorePrefixIterator(store, GetREDsFromValSrcIndexKey(valAddr)) + for { if !iterator.Valid() { break } - redelegationKey := iterator.Value() + redelegationKey := GetREDKeyFromValSrcIndexKey(iterator.Key()) redelegationBytes := store.Get(redelegationKey) var redelegation types.Redelegation k.cdc.MustUnmarshalBinary(redelegationBytes, &redelegation) @@ -174,7 +172,7 @@ func (k Keeper) HasReceivingRedelegation(ctx sdk.Context, DelegatorAddr, ValidatorDstAddr sdk.Address) bool { store := ctx.KVStore(k.storeKey) - prefix := GetREDsByDelToValDstIndexKey(DelegatorAddr, ValidatorDstAddr, k.cdc) + prefix := GetREDsByDelToValDstIndexKey(DelegatorAddr, ValidatorDstAddr) iterator := sdk.KVStorePrefixIterator(store, prefix) //smallest to largest found := false @@ -190,19 +188,19 @@ func (k Keeper) HasReceivingRedelegation(ctx sdk.Context, func (k Keeper) SetRedelegation(ctx sdk.Context, red types.Redelegation) { store := ctx.KVStore(k.storeKey) bz := k.cdc.MustMarshalBinary(red) - redKey := GetREDKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr, k.cdc) + redKey := GetREDKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr) store.Set(redKey, bz) - store.Set(GetREDByValSrcIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr, k.cdc), redKey) - store.Set(GetREDByValDstIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr, k.cdc), redKey) + store.Set(GetREDByValSrcIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr), []byte{}) + store.Set(GetREDByValDstIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr), []byte{}) } // remove a redelegation object and associated index func (k Keeper) RemoveRedelegation(ctx sdk.Context, red types.Redelegation) { store := ctx.KVStore(k.storeKey) - redKey := GetREDKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr, k.cdc) + redKey := GetREDKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr) store.Delete(redKey) - store.Delete(GetREDByValSrcIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr, k.cdc)) - store.Delete(GetREDByValDstIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr, k.cdc)) + store.Delete(GetREDByValSrcIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr)) + store.Delete(GetREDByValDstIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr)) } //_____________________________________________________________________________________ diff --git a/x/stake/keeper/delegation_test.go b/x/stake/keeper/delegation_test.go index eb318df4d..c0a3ee8c5 100644 --- a/x/stake/keeper/delegation_test.go +++ b/x/stake/keeper/delegation_test.go @@ -179,6 +179,36 @@ func TestUnbondDelegation(t *testing.T) { require.Equal(t, int64(4), pool.BondedTokens) } +// Make sure that that the retrieving the delegations doesn't affect the state +func TestGetRedelegationsFromValidator(t *testing.T) { + ctx, _, keeper := CreateTestInput(t, false, 0) + + rd := types.Redelegation{ + DelegatorAddr: addrDels[0], + ValidatorSrcAddr: addrVals[0], + ValidatorDstAddr: addrVals[1], + CreationHeight: 0, + MinTime: 0, + SharesSrc: sdk.NewRat(5), + SharesDst: sdk.NewRat(5), + } + + // set and retrieve a record + keeper.SetRedelegation(ctx, rd) + resBond, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) + require.True(t, found) + + // get the redelegations one time + redelegations := keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resBond)) + + // get the redelegations a second time, should be exactly the same + redelegations = keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resBond)) +} + // tests Get/Set/Remove/Has UnbondingDelegation func TestRedelegation(t *testing.T) { ctx, _, keeper := CreateTestInput(t, false, 0) @@ -201,7 +231,10 @@ func TestRedelegation(t *testing.T) { keeper.SetRedelegation(ctx, rd) resBond, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) require.True(t, found) - require.True(t, rd.Equal(resBond)) + + redelegations := keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resBond)) // check if has the redelegation has = keeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1]) @@ -211,10 +244,15 @@ func TestRedelegation(t *testing.T) { rd.SharesSrc = sdk.NewRat(21) rd.SharesDst = sdk.NewRat(21) keeper.SetRedelegation(ctx, rd) + resBond, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) require.True(t, found) require.True(t, rd.Equal(resBond)) + redelegations = keeper.GetRedelegationsFromValidator(ctx, addrVals[0]) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resBond)) + // delete a record keeper.RemoveRedelegation(ctx, rd) _, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index 667f5f681..cfe8ded82 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -6,7 +6,6 @@ import ( "github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/x/stake/types" ) @@ -29,41 +28,49 @@ var ( UnbondingDelegationKey = []byte{0x0B} // key for an unbonding-delegation UnbondingDelegationByValIndexKey = []byte{0x0C} // prefix for each key for an unbonding-delegation, by validator owner RedelegationKey = []byte{0x0D} // key for a redelegation - RedelegationByValSrcIndexKey = []byte{0x0E} // prefix for each key for an redelegation, by validator owner - RedelegationByValDstIndexKey = []byte{0x0F} // prefix for each key for an redelegation, by validator owner + RedelegationByValSrcIndexKey = []byte{0x0E} // prefix for each key for an redelegation, by source validator owner + RedelegationByValDstIndexKey = []byte{0x0F} // prefix for each key for an redelegation, by destination validator owner ) const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch -// get the key for the validator with address +// get the key for the validator with address. +// VALUE: stake/types.Validator func GetValidatorKey(ownerAddr sdk.Address) []byte { return append(ValidatorsKey, ownerAddr.Bytes()...) } -// get the key for the validator with pubkey +// get the key for the validator with pubkey. +// VALUE: validator owner address ([]byte) func GetValidatorByPubKeyIndexKey(pubkey crypto.PubKey) []byte { return append(ValidatorsByPubKeyIndexKey, pubkey.Bytes()...) } -// get the key for the current validator group, ordered like tendermint +// get the key for the current validator group +// VALUE: none (key rearrangement with GetValKeyFromValBondedIndexKey) func GetValidatorsBondedIndexKey(ownerAddr sdk.Address) []byte { return append(ValidatorsBondedIndexKey, ownerAddr.Bytes()...) } -// get the power which is the key for the validator used in the power-store -func GetValidatorsByPowerIndexKey(validator types.Validator, pool types.Pool) []byte { - - // NOTE the address doesn't need to be stored because counter bytes must always be different - return GetValidatorPowerRank(validator, pool) +// Get the validator owner address from ValBondedIndexKey +func GetAddressFromValBondedIndexKey(IndexKey []byte) []byte { + return IndexKey[1:] // remove prefix bytes } -// get the power of a validator -func GetValidatorPowerRank(validator types.Validator, pool types.Pool) []byte { +// get the validator by power index. power index is the key used in the power-store, +// and represents the relative power ranking of the validator. +// VALUE: validator owner address ([]byte) +func GetValidatorsByPowerIndexKey(validator types.Validator, pool types.Pool) []byte { + // NOTE the address doesn't need to be stored because counter bytes must always be different + return getValidatorPowerRank(validator, pool) +} + +// get the power ranking of a validator +func getValidatorPowerRank(validator types.Validator, pool types.Pool) []byte { power := validator.EquivalentBondedShares(pool) powerBytes := []byte(power.ToLeftPadded(maxDigitsForAccount)) // power big-endian (more powerful validators first) - // TODO ensure that the key will be a readable string.. probably should add seperators and have revokedBytes := make([]byte, 1) if validator.Revoked { revokedBytes[0] = byte(0x01) @@ -71,127 +78,162 @@ func GetValidatorPowerRank(validator types.Validator, pool types.Pool) []byte { revokedBytes[0] = byte(0x00) } - // TODO ensure that the key will be a readable string.. probably should add seperators and have // heightBytes and counterBytes represent strings like powerBytes does heightBytes := make([]byte, binary.MaxVarintLen64) binary.BigEndian.PutUint64(heightBytes, ^uint64(validator.BondHeight)) // invert height (older validators first) counterBytes := make([]byte, 2) binary.BigEndian.PutUint16(counterBytes, ^uint16(validator.BondIntraTxCounter)) // invert counter (first txns have priority) - return append(ValidatorsByPowerIndexKey, - append(revokedBytes, - append(powerBytes, - append(heightBytes, counterBytes...)...)...)...) + return append(append(append(append( + ValidatorsByPowerIndexKey, + revokedBytes...), + powerBytes...), + heightBytes...), + counterBytes...) } -// get the key for the accumulated update validators +// get the key for the accumulated update validators. +// VALUE: abci.Validator +// note records using these keys should never persist between blocks func GetTendermintUpdatesKey(ownerAddr sdk.Address) []byte { return append(TendermintUpdatesKey, ownerAddr.Bytes()...) } //________________________________________________________________________________ -// get the key for delegator bond with validator -func GetDelegationKey(delegatorAddr, validatorAddr sdk.Address, cdc *wire.Codec) []byte { - return append(GetDelegationsKey(delegatorAddr, cdc), validatorAddr.Bytes()...) +// get the key for delegator bond with validator. +// VALUE: stake/types.Delegation +func GetDelegationKey(delegatorAddr, validatorAddr sdk.Address) []byte { + return append(GetDelegationsKey(delegatorAddr), validatorAddr.Bytes()...) } // get the prefix for a delegator for all validators -func GetDelegationsKey(delegatorAddr sdk.Address, cdc *wire.Codec) []byte { - res := cdc.MustMarshalBinary(&delegatorAddr) - return append(DelegationKey, res...) +func GetDelegationsKey(delegatorAddr sdk.Address) []byte { + return append(DelegationKey, delegatorAddr.Bytes()...) } //________________________________________________________________________________ -// get the key for an unbonding delegation -func GetUBDKey(delegatorAddr, validatorAddr sdk.Address, cdc *wire.Codec) []byte { - return append(GetUBDsKey(delegatorAddr, cdc), validatorAddr.Bytes()...) +// get the key for an unbonding delegation by delegator and validator addr. +// VALUE: stake/types.UnbondingDelegation +func GetUBDKey(delegatorAddr, validatorAddr sdk.Address) []byte { + return append( + GetUBDsKey(delegatorAddr.Bytes()), + validatorAddr.Bytes()...) } // get the index-key for an unbonding delegation, stored by validator-index -func GetUBDByValIndexKey(delegatorAddr, validatorAddr sdk.Address, cdc *wire.Codec) []byte { - return append(GetUBDsByValIndexKey(validatorAddr, cdc), delegatorAddr.Bytes()...) +// VALUE: none (key rearrangement used) +func GetUBDByValIndexKey(delegatorAddr, validatorAddr sdk.Address) []byte { + return append(GetUBDsByValIndexKey(validatorAddr), delegatorAddr.Bytes()...) +} + +// rearrange the ValIndexKey to get the UBDKey +func GetUBDKeyFromValIndexKey(IndexKey []byte) []byte { + addrs := IndexKey[1:] // remove prefix bytes + if len(addrs) != 40 { + panic("unexpected key length") + } + valAddr := addrs[:20] + delAddr := addrs[20:] + return GetUBDKey(delAddr, valAddr) } //______________ // get the prefix for all unbonding delegations from a delegator -func GetUBDsKey(delegatorAddr sdk.Address, cdc *wire.Codec) []byte { - res := cdc.MustMarshalBinary(&delegatorAddr) - return append(UnbondingDelegationKey, res...) +func GetUBDsKey(delegatorAddr sdk.Address) []byte { + return append(UnbondingDelegationKey, delegatorAddr.Bytes()...) } -// get the prefix keyspace for the indexs of unbonding delegations for a validator -func GetUBDsByValIndexKey(validatorAddr sdk.Address, cdc *wire.Codec) []byte { - res := cdc.MustMarshalBinary(&validatorAddr) - return append(UnbondingDelegationByValIndexKey, res...) +// get the prefix keyspace for the indexes of unbonding delegations for a validator +func GetUBDsByValIndexKey(validatorAddr sdk.Address) []byte { + return append(UnbondingDelegationByValIndexKey, validatorAddr.Bytes()...) } //________________________________________________________________________________ // get the key for a redelegation +// VALUE: stake/types.RedelegationKey func GetREDKey(delegatorAddr, validatorSrcAddr, - validatorDstAddr sdk.Address, cdc *wire.Codec) []byte { + validatorDstAddr sdk.Address) []byte { - return append( - GetREDsKey(delegatorAddr, cdc), - append( - validatorSrcAddr.Bytes(), - validatorDstAddr.Bytes()...)..., - ) + return append(append( + GetREDsKey(delegatorAddr.Bytes()), + validatorSrcAddr.Bytes()...), + validatorDstAddr.Bytes()...) } // get the index-key for a redelegation, stored by source-validator-index +// VALUE: none (key rearrangement used) func GetREDByValSrcIndexKey(delegatorAddr, validatorSrcAddr, - validatorDstAddr sdk.Address, cdc *wire.Codec) []byte { + validatorDstAddr sdk.Address) []byte { - return append( - GetREDsFromValSrcIndexKey(validatorSrcAddr, cdc), - append( - delegatorAddr.Bytes(), - validatorDstAddr.Bytes()...)..., - ) + return append(append( + GetREDsFromValSrcIndexKey(validatorSrcAddr), + delegatorAddr.Bytes()...), + validatorDstAddr.Bytes()...) } // get the index-key for a redelegation, stored by destination-validator-index +// VALUE: none (key rearrangement used) func GetREDByValDstIndexKey(delegatorAddr, validatorSrcAddr, - validatorDstAddr sdk.Address, cdc *wire.Codec) []byte { + validatorDstAddr sdk.Address) []byte { - return append( - GetREDsToValDstIndexKey(validatorDstAddr, cdc), - append( - delegatorAddr.Bytes(), - validatorSrcAddr.Bytes()...)..., - ) + return append(append( + GetREDsToValDstIndexKey(validatorDstAddr), + delegatorAddr.Bytes()...), + validatorSrcAddr.Bytes()...) +} + +// rearrange the ValSrcIndexKey to get the REDKey +func GetREDKeyFromValSrcIndexKey(IndexKey []byte) []byte { + addrs := IndexKey[1:] // remove prefix bytes + if len(addrs) != 60 { + panic("unexpected key length") + } + valSrcAddr := addrs[:20] + delAddr := addrs[20:40] + valDstAddr := addrs[40:] + + return GetREDKey(delAddr, valSrcAddr, valDstAddr) +} + +// rearrange the ValDstIndexKey to get the REDKey +func GetREDKeyFromValDstIndexKey(IndexKey []byte) []byte { + addrs := IndexKey[1:] // remove prefix bytes + if len(addrs) != 60 { + panic("unexpected key length") + } + valDstAddr := addrs[:20] + delAddr := addrs[20:40] + valSrcAddr := addrs[40:] + return GetREDKey(delAddr, valSrcAddr, valDstAddr) } //______________ // get the prefix keyspace for redelegations from a delegator -func GetREDsKey(delegatorAddr sdk.Address, cdc *wire.Codec) []byte { - res := cdc.MustMarshalBinary(&delegatorAddr) - return append(RedelegationKey, res...) +func GetREDsKey(delegatorAddr sdk.Address) []byte { + return append(RedelegationKey, delegatorAddr.Bytes()...) } // get the prefix keyspace for all redelegations redelegating away from a source validator -func GetREDsFromValSrcIndexKey(validatorSrcAddr sdk.Address, cdc *wire.Codec) []byte { - res := cdc.MustMarshalBinary(&validatorSrcAddr) - return append(RedelegationByValSrcIndexKey, res...) +func GetREDsFromValSrcIndexKey(validatorSrcAddr sdk.Address) []byte { + return append(RedelegationByValSrcIndexKey, validatorSrcAddr.Bytes()...) } // get the prefix keyspace for all redelegations redelegating towards a destination validator -func GetREDsToValDstIndexKey(validatorDstAddr sdk.Address, cdc *wire.Codec) []byte { - res := cdc.MustMarshalBinary(&validatorDstAddr) - return append(RedelegationByValDstIndexKey, res...) +func GetREDsToValDstIndexKey(validatorDstAddr sdk.Address) []byte { + return append(RedelegationByValDstIndexKey, validatorDstAddr.Bytes()...) } // get the prefix keyspace for all redelegations redelegating towards a destination validator // from a particular delegator func GetREDsByDelToValDstIndexKey(delegatorAddr sdk.Address, - validatorDstAddr sdk.Address, cdc *wire.Codec) []byte { + validatorDstAddr sdk.Address) []byte { return append( - GetREDsToValDstIndexKey(validatorDstAddr, cdc), + GetREDsToValDstIndexKey(validatorDstAddr), delegatorAddr.Bytes()...) } diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index 55ad658a2..bedbc1559 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -34,7 +34,7 @@ func (k Keeper) IterateValidatorsBonded(ctx sdk.Context, fn func(index int64, va iterator := sdk.KVStorePrefixIterator(store, ValidatorsBondedIndexKey) i := int64(0) for ; iterator.Valid(); iterator.Next() { - address := iterator.Value() + address := GetAddressFromValBondedIndexKey(iterator.Key()) validator, found := k.GetValidator(ctx, address) if !found { panic(fmt.Sprintf("validator record not found for address: %v\n", address)) @@ -87,7 +87,7 @@ func (k Keeper) Delegation(ctx sdk.Context, addrDel sdk.Address, addrVal sdk.Add // iterate through the active validator set and perform the provided function func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.Address, fn func(index int64, delegation sdk.Delegation) (stop bool)) { store := ctx.KVStore(k.storeKey) - key := GetDelegationsKey(delAddr, k.cdc) + key := GetDelegationsKey(delAddr) iterator := sdk.KVStorePrefixIterator(store, key) i := int64(0) for ; iterator.Valid(); iterator.Next() { diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 0d556f7dc..c2711788b 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -56,7 +56,7 @@ func (k Keeper) SetValidatorByPowerIndex(ctx sdk.Context, validator types.Valida // validator index func (k Keeper) SetValidatorBondedIndex(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) - store.Set(GetValidatorsBondedIndexKey(validator.Owner), validator.Owner) + store.Set(GetValidatorsBondedIndexKey(validator.Owner), []byte{}) } // used in testing @@ -124,7 +124,7 @@ func (k Keeper) GetValidatorsBonded(ctx sdk.Context) (validators []types.Validat if i > int(maxValidators-1) { panic("maxValidators is less than the number of records in ValidatorsBonded Store, store should have been updated") } - address := iterator.Value() + address := GetAddressFromValBondedIndexKey(iterator.Key()) validator, found := k.GetValidator(ctx, address) if !found { panic(fmt.Sprintf("validator record not found for address: %v\n", address)) @@ -362,7 +362,7 @@ func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) { toKickOut := make(map[string]byte) iterator := sdk.KVStorePrefixIterator(store, ValidatorsBondedIndexKey) for ; iterator.Valid(); iterator.Next() { - ownerAddr := iterator.Value() + ownerAddr := GetAddressFromValBondedIndexKey(iterator.Key()) toKickOut[string(ownerAddr)] = 0 // set anything } iterator.Close() @@ -471,7 +471,7 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. // save the now bonded validator record to the three referenced stores bzVal := k.cdc.MustMarshalBinary(validator) store.Set(GetValidatorKey(validator.Owner), bzVal) - store.Set(GetValidatorsBondedIndexKey(validator.Owner), validator.Owner) + store.Set(GetValidatorsBondedIndexKey(validator.Owner), []byte{}) // add to accumulated changes for tendermint bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidator()) From f1194019cd295c20cc4a00fc3aa023c962b9e32c Mon Sep 17 00:00:00 2001 From: Yukai Tu Date: Wed, 4 Jul 2018 11:29:05 +0800 Subject: [PATCH 16/53] Merge PR #1534: Check new rat decimal string length --- docs/clients/ledger.md | 29 +++++++++++++++++++++++++++++ types/rational.go | 4 ++++ types/rational_test.go | 1 + 3 files changed, 34 insertions(+) create mode 100644 docs/clients/ledger.md diff --git a/docs/clients/ledger.md b/docs/clients/ledger.md new file mode 100644 index 000000000..9f6386715 --- /dev/null +++ b/docs/clients/ledger.md @@ -0,0 +1,29 @@ +# Ledger // Cosmos + +### Ledger Support for account keys + +`gaiacli` now supports derivation of account keys from a Ledger seed. To use this functionality you will need the following: + +- A running `gaiad` instance connected to the network you wish to use. +- A `gaiacli` instance configured to connect to your chosen `gaiad` instance. +- A LedgerNano with the `ledger-cosmos` app installed + * Install the Cosmos app onto your Ledger by following the instructions in the [`ledger-cosmos`](https://github.com/cosmos/ledger-cosmos/blob/master/docs/BUILD.md) repository. + * A production-ready version of this app will soon be included in the [Ledger Apps Store](https://www.ledgerwallet.com/apps) + +> **NOTE:** Cosmos keys are derived acording to the [BIP 44 Hierarchical Deterministic wallet spec](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki). For more information on Cosmos derivation paths [see the hd package](https://github.com/cosmos/cosmos-sdk/blob/develop/crypto/keys/hd/hdpath.go#L30). + +Once you have the Cosmos app installed on your Ledger, and the Ledger is accessible from the machine you are using `gaiacli` from you can create a new account key using the Ledger: + +```bash +$ gaiacli keys add {{ .Key.Name }} --ledger +NAME: TYPE: ADDRESS: PUBKEY: +{{ .Key.Name }} ledger cosmosaccaddr1aw64xxr80lwqqdk8u2xhlrkxqaxamkr3e2g943 cosmosaccpub1addwnpepqvhs678gh9aqrjc2tg2vezw86csnvgzqq530ujkunt5tkuc7lhjkz5mj629 +``` + +This key will only be accessible while the Ledger is plugged in and unlocked. To send some coins with this key, run the following: + +```bash +$ gaiacli send --name {{ .Key.Name }} --to {{ .Destination.AccAddr }} --chain-id=gaia-7000 +``` + +You will be asked to review and confirm the transaction on the Ledger. Once you do this you should see the result in the console! Now you can use your Ledger to manage your Atoms and Stake! diff --git a/types/rational.go b/types/rational.go index ab400868d..24072fc09 100644 --- a/types/rational.go +++ b/types/rational.go @@ -41,6 +41,10 @@ func NewRat(Numerator int64, Denominator ...int64) Rat { // precision is the number of values after the decimal point which should be read func NewRatFromDecimal(decimalStr string, prec int) (f Rat, err Error) { // first extract any negative symbol + if len(decimalStr) == 0 { + return f, ErrUnknownRequest("decimal string is empty") + } + neg := false if string(decimalStr[0]) == "-" { neg = true diff --git a/types/rational_test.go b/types/rational_test.go index 3215313e0..ecbc09e88 100644 --- a/types/rational_test.go +++ b/types/rational_test.go @@ -27,6 +27,7 @@ func TestNewFromDecimal(t *testing.T) { expErr bool exp Rat }{ + {"", true, Rat{}}, {"0", false, NewRat(0)}, {"1", false, NewRat(1)}, {"1.1", false, NewRat(11, 10)}, From 199c1e81ebda231ae344e086f27654772be93284 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 3 Jul 2018 23:44:54 -0400 Subject: [PATCH 17/53] delegations new key format ported --- x/stake/client/cli/query.go | 7 +++---- x/stake/client/rest/query.go | 10 +++------- x/stake/keeper/delegation.go | 17 +++++++---------- x/stake/keeper/sdk_types.go | 4 +--- x/stake/types/delegation.go | 9 ++++----- 5 files changed, 18 insertions(+), 29 deletions(-) diff --git a/x/stake/client/cli/query.go b/x/stake/client/cli/query.go index 5a22f2c41..e66a3bb4d 100644 --- a/x/stake/client/cli/query.go +++ b/x/stake/client/cli/query.go @@ -11,6 +11,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/x/stake" + "github.com/cosmos/cosmos-sdk/x/stake/types" ) // get the command to query a validator @@ -130,7 +131,7 @@ func GetCmdQueryDelegation(storeName string, cdc *wire.Codec) *cobra.Command { } // parse out the delegation - delegation := new(stake.Delegation) + delegation := types.UnmarshalDelegation(cdc, key, res) switch viper.Get(cli.OutputFlag) { case "text": @@ -140,7 +141,6 @@ func GetCmdQueryDelegation(storeName string, cdc *wire.Codec) *cobra.Command { } fmt.Println(resp) case "json": - cdc.MustUnmarshalBinary(res, delegation) output, err := wire.MarshalJSONIndent(cdc, delegation) if err != nil { return err @@ -179,8 +179,7 @@ func GetCmdQueryDelegations(storeName string, cdc *wire.Codec) *cobra.Command { // parse out the validators var delegations []stake.Delegation for _, KV := range resKVs { - var delegation stake.Delegation - cdc.MustUnmarshalBinary(KV.Value, &delegation) + delegation := types.UnmarshalDelegation(cdc, KV.Key, KV.Value) delegations = append(delegations, delegation) } diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index 12ef882e5..b19cea72b 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -9,7 +9,9 @@ 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/stake" + "github.com/cosmos/cosmos-sdk/x/stake/types" ) const storeName = "stake" @@ -75,13 +77,7 @@ func delegationHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerF return } - var delegation stake.Delegation - err = cdc.UnmarshalBinary(res, &delegation) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("couldn't decode delegation. Error: %s", err.Error()))) - return - } + delegation := types.UnmarshalDelegation(cdc, key, res) output, err := cdc.MarshalJSON(delegation) if err != nil { diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index bb8170a6a..9c56b8512 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -12,12 +12,13 @@ func (k Keeper) GetDelegation(ctx sdk.Context, delegatorAddr, validatorAddr sdk.Address) (delegation types.Delegation, found bool) { store := ctx.KVStore(k.storeKey) - delegatorBytes := store.Get(GetDelegationKey(delegatorAddr, validatorAddr)) - if delegatorBytes == nil { + key := GetDelegationKey(delegatorAddr, validatorAddr) + value := store.Get(key) + if value == nil { return delegation, false } - k.cdc.MustUnmarshalBinary(delegatorBytes, &delegation) + delegation = types.UnmarshalDelegation(k.cdc, key, value) return delegation, true } @@ -31,9 +32,7 @@ func (k Keeper) GetAllDelegations(ctx sdk.Context) (delegations []types.Delegati if !iterator.Valid() { break } - bondBytes := iterator.Value() - var delegation types.Delegation - k.cdc.MustUnmarshalBinary(bondBytes, &delegation) + delegation := types.UnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) delegations = append(delegations, delegation) iterator.Next() } @@ -55,9 +54,7 @@ func (k Keeper) GetDelegations(ctx sdk.Context, delegator sdk.Address, if !iterator.Valid() || i > int(maxRetrieve-1) { break } - bondBytes := iterator.Value() - var delegation types.Delegation - k.cdc.MustUnmarshalBinary(bondBytes, &delegation) + delegation := types.UnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) delegations[i] = delegation iterator.Next() } @@ -68,7 +65,7 @@ func (k Keeper) GetDelegations(ctx sdk.Context, delegator sdk.Address, // set the delegation func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { store := ctx.KVStore(k.storeKey) - b := k.cdc.MustMarshalBinary(delegation) + b := types.MarshalDelegation(k.cdc, delegation) store.Set(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr), b) } diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index bedbc1559..9e45982b4 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -91,9 +91,7 @@ func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.Address, fn func iterator := sdk.KVStorePrefixIterator(store, key) i := int64(0) for ; iterator.Valid(); iterator.Next() { - bz := iterator.Value() - var delegation types.Delegation - k.cdc.MustUnmarshalBinary(bz, &delegation) + delegation := types.UnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) stop := fn(i, delegation) // XXX is this safe will the fields be able to get written to? if stop { break diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index 705dcb6cd..b6d35fb56 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -37,13 +37,12 @@ func UnmarshalDelegation(cdc *wire.Codec, key, value []byte) Delegation { var storeValue delegationValue cdc.MustUnmarshalBinary(value, &storeValue) - addrs := IndexKey[1:] // remove prefix bytes - split := len(addrs) / 2 - if (len(addrs) % 2) != 0 { + addrs := key[1:] // remove prefix bytes + if len(addrs) != 40 { panic("key length not even") } - delAddr := sdk.Address{addrs[:split]} - valAddr := sdk.Address{addrs[split:]} + delAddr := sdk.Address(addrs[:20]) + valAddr := sdk.Address(addrs[20:]) return Delegation{ DelegatorAddr: delAddr, From 0b9e0f2afc2bf39257af101119727fd4afaafc99 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Wed, 4 Jul 2018 00:21:36 -0400 Subject: [PATCH 18/53] Merge PR #1492: Improve Module Test Coverage * Merge pull request #1492: Improve Module Test Coverage * Revert renaming of SignCheckDeliver [#1492] * Remove named fields from stake unit tests & fix comments [#1492] * update for tmlibs->tendermint/libs * Remove tmlibs dependency --- Gopkg.lock | 3 +- docs/core/app5.md | 2 +- examples/democoin/app/app_test.go | 4 +- examples/democoin/x/cool/app_test.go | 10 +- examples/democoin/x/pow/app_test.go | 2 +- x/auth/mock/app.go | 110 ------------ x/auth/mock/auth_app_test.go | 92 ---------- x/auth/mock/simulate_block.go | 110 ------------ x/bank/app_test.go | 2 +- x/bank/bench_test.go | 2 +- x/gov/msgs_test.go | 2 +- x/gov/test_common.go | 4 +- x/ibc/app_test.go | 2 +- x/mock/app.go | 168 ++++++++++++++++++ x/mock/app_test.go | 102 +++++++++++ x/mock/test_utils.go | 71 ++++++++ x/slashing/app_test.go | 10 +- x/stake/app_test.go | 118 ++++++------ x/stake/genesis.go | 34 ++-- x/stake/stake.go | 46 +++-- x/stake/types/delegation.go | 35 ++-- x/stake/types/delegation_test.go | 116 ++++++++++++ x/stake/types/errors.go | 27 ++- x/stake/types/msg_test.go | 32 +--- x/stake/types/params.go | 10 +- x/stake/types/params_test.go | 21 +++ x/stake/types/pool_test.go | 25 ++- x/stake/types/shares.go | 78 ++++---- x/stake/types/shares_test.go | 35 ++++ .../types/{test_common.go => test_utils.go} | 68 +++---- x/stake/types/validator.go | 98 ++++++---- x/stake/types/validator_test.go | 91 +++++++++- 32 files changed, 942 insertions(+), 588 deletions(-) delete mode 100644 x/auth/mock/app.go delete mode 100644 x/auth/mock/auth_app_test.go delete mode 100644 x/auth/mock/simulate_block.go create mode 100644 x/mock/app.go create mode 100644 x/mock/app_test.go create mode 100644 x/mock/test_utils.go create mode 100644 x/stake/types/delegation_test.go create mode 100644 x/stake/types/params_test.go create mode 100644 x/stake/types/shares_test.go rename x/stake/types/{test_common.go => test_utils.go} (84%) diff --git a/Gopkg.lock b/Gopkg.lock index a9b4a1f5c..7a9b56696 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -137,6 +137,7 @@ ".", "hcl/ast", "hcl/parser", + "hcl/printer", "hcl/scanner", "hcl/strconv", "hcl/token", @@ -433,7 +434,7 @@ "netutil", "trace" ] - revision = "87b3feba568e144938625fc5d80ec92566c1a8fe" + revision = "ed29d75add3d7c4bf7ca65aac0c6df3d1420216f" [[projects]] branch = "master" diff --git a/docs/core/app5.md b/docs/core/app5.md index c6011f042..39cc7a263 100644 --- a/docs/core/app5.md +++ b/docs/core/app5.md @@ -59,7 +59,7 @@ func newApp(logger log.Logger, db dbm.DB) abci.Application { Note we utilize the popular [cobra library](https://github.com/spf13/cobra) for the CLI, in concert with the [viper library](https://github.com/spf13/library) -for managing configuration. See our [cli library](https://github.com/tendermint/tmlibs/blob/master/cli/setup.go) +for managing configuration. See our [cli library](https://github.com/tendermint/blob/master/tmlibs/cli/setup.go) for more details. TODO: compile and run the binary diff --git a/examples/democoin/app/app_test.go b/examples/democoin/app/app_test.go index a642eff72..60005713e 100644 --- a/examples/democoin/app/app_test.go +++ b/examples/democoin/app/app_test.go @@ -4,14 +4,12 @@ import ( "os" "testing" - "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/examples/democoin/types" "github.com/cosmos/cosmos-sdk/examples/democoin/x/cool" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/x/auth" - + "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" dbm "github.com/tendermint/tendermint/libs/db" diff --git a/examples/democoin/x/cool/app_test.go b/examples/democoin/x/cool/app_test.go index e93f6d99c..df5786a04 100644 --- a/examples/democoin/x/cool/app_test.go +++ b/examples/democoin/x/cool/app_test.go @@ -3,15 +3,13 @@ package cool import ( "testing" - "github.com/stretchr/testify/require" - - abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/auth/mock" bank "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/mock" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" ) var ( diff --git a/examples/democoin/x/pow/app_test.go b/examples/democoin/x/pow/app_test.go index d223a1f10..076dc20bc 100644 --- a/examples/democoin/x/pow/app_test.go +++ b/examples/democoin/x/pow/app_test.go @@ -7,8 +7,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/auth/mock" "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/mock" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" diff --git a/x/auth/mock/app.go b/x/auth/mock/app.go deleted file mode 100644 index 758b1efab..000000000 --- a/x/auth/mock/app.go +++ /dev/null @@ -1,110 +0,0 @@ -package mock - -import ( - "os" - - abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto" - dbm "github.com/tendermint/tendermint/libs/db" - "github.com/tendermint/tendermint/libs/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" -) - -// Extended ABCI application -type App struct { - *bam.BaseApp - Cdc *wire.Codec // public since the codec is passed into the module anyways. - KeyMain *sdk.KVStoreKey - KeyAccount *sdk.KVStoreKey - - // TODO: Abstract this out from not needing to be auth specifically - AccountMapper auth.AccountMapper - FeeCollectionKeeper auth.FeeCollectionKeeper - - GenesisAccounts []auth.Account -} - -// partially construct a new app on the memstore for module and genesis testing -func NewApp() *App { - logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") - db := dbm.NewMemDB() - - // create the cdc with some standard codecs - cdc := wire.NewCodec() - sdk.RegisterWire(cdc) - wire.RegisterCrypto(cdc) - auth.RegisterWire(cdc) - - // create your application object - app := &App{ - BaseApp: bam.NewBaseApp("mock", cdc, logger, db), - Cdc: cdc, - KeyMain: sdk.NewKVStoreKey("main"), - KeyAccount: sdk.NewKVStoreKey("acc"), - } - - // define the accountMapper - app.AccountMapper = auth.NewAccountMapper( - app.Cdc, - app.KeyAccount, // target store - &auth.BaseAccount{}, // prototype - ) - - // initialize the app, the chainers and blockers can be overwritten before calling complete setup - app.SetInitChainer(app.InitChainer) - - app.SetAnteHandler(auth.NewAnteHandler(app.AccountMapper, app.FeeCollectionKeeper)) - - return app -} - -// complete the application setup after the routes have been registered -func (app *App) CompleteSetup(newKeys []*sdk.KVStoreKey) error { - newKeys = append(newKeys, app.KeyMain) - newKeys = append(newKeys, app.KeyAccount) - app.MountStoresIAVL(newKeys...) - err := app.LoadLatestVersion(app.KeyMain) - return err -} - -// custom logic for initialization -func (app *App) InitChainer(ctx sdk.Context, _ abci.RequestInitChain) abci.ResponseInitChain { - - // load the accounts - for _, genacc := range app.GenesisAccounts { - acc := app.AccountMapper.NewAccountWithAddress(ctx, genacc.GetAddress()) - err := acc.SetCoins(genacc.GetCoins()) - if err != nil { - // TODO: Handle with #870 - panic(err) - } - app.AccountMapper.SetAccount(ctx, acc) - } - - return abci.ResponseInitChain{} -} - -// Generate genesis accounts loaded with coins, and returns their addresses, pubkeys, and privkeys -func CreateGenAccounts(numAccs int64, genCoins sdk.Coins) (genAccs []auth.Account, addrs []sdk.Address, pubKeys []crypto.PubKey, privKeys []crypto.PrivKey) { - for i := int64(0); i < numAccs; i++ { - privKey := crypto.GenPrivKeyEd25519() - pubKey := privKey.PubKey() - addr := pubKey.Address() - - genAcc := &auth.BaseAccount{ - Address: addr, - Coins: genCoins, - } - - genAccs = append(genAccs, genAcc) - privKeys = append(privKeys, privKey) - pubKeys = append(pubKeys, pubKey) - addrs = append(addrs, addr) - } - - return -} diff --git a/x/auth/mock/auth_app_test.go b/x/auth/mock/auth_app_test.go deleted file mode 100644 index 3f340bbf9..000000000 --- a/x/auth/mock/auth_app_test.go +++ /dev/null @@ -1,92 +0,0 @@ -package mock - -import ( - "testing" - - "github.com/stretchr/testify/require" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth" - - abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto" -) - -// A mock transaction that has a validation which can fail. -type testMsg struct { - signers []sdk.Address - positiveNum int64 -} - -// TODO: Clean this up, make it public -const msgType = "testMsg" - -func (tx testMsg) Type() string { return msgType } -func (tx testMsg) GetMsg() sdk.Msg { return tx } -func (tx testMsg) GetMemo() string { return "" } -func (tx testMsg) GetSignBytes() []byte { return nil } -func (tx testMsg) GetSigners() []sdk.Address { return tx.signers } -func (tx testMsg) GetSignatures() []auth.StdSignature { return nil } -func (tx testMsg) ValidateBasic() sdk.Error { - if tx.positiveNum >= 0 { - return nil - } - return sdk.ErrTxDecode("positiveNum should be a non-negative integer.") -} - -// test auth module messages - -var ( - priv1 = crypto.GenPrivKeyEd25519() - addr1 = priv1.PubKey().Address() - priv2 = crypto.GenPrivKeyEd25519() - addr2 = priv2.PubKey().Address() - - coins = sdk.Coins{sdk.NewCoin("foocoin", 10)} - testMsg1 = testMsg{signers: []sdk.Address{addr1}, positiveNum: 1} -) - -// initialize the mock application for this module -func getMockApp(t *testing.T) *App { - mapp := NewApp() - - mapp.Router().AddRoute(msgType, func(ctx sdk.Context, msg sdk.Msg) (res sdk.Result) { return }) - require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{})) - return mapp -} - -func TestMsgPrivKeys(t *testing.T) { - mapp := getMockApp(t) - mapp.Cdc.RegisterConcrete(testMsg{}, "mock/testMsg", nil) - - // Construct some genesis bytes to reflect basecoin/types/AppAccount - // Give 77 foocoin to the first key - coins := sdk.Coins{sdk.NewCoin("foocoin", 77)} - acc1 := &auth.BaseAccount{ - Address: addr1, - Coins: coins, - } - accs := []auth.Account{acc1} - - // Construct genesis state - SetGenesis(mapp, accs) - - // A checkTx context (true) - ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{}) - res1 := mapp.AccountMapper.GetAccount(ctxCheck, addr1) - require.Equal(t, acc1, res1.(*auth.BaseAccount)) - - // Run a CheckDeliver - SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{testMsg1}, []int64{0}, []int64{0}, true, priv1) - - // signing a SendMsg with the wrong privKey should be an auth error - mapp.BeginBlock(abci.RequestBeginBlock{}) - tx := GenTx([]sdk.Msg{testMsg1}, []int64{0}, []int64{1}, priv2) - res := mapp.Deliver(tx) - require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log) - - // resigning the tx with the correct priv key should still work - res = SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{testMsg1}, []int64{0}, []int64{1}, true, priv1) - - require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeOK), res.Code, res.Log) -} diff --git a/x/auth/mock/simulate_block.go b/x/auth/mock/simulate_block.go deleted file mode 100644 index f85fdf180..000000000 --- a/x/auth/mock/simulate_block.go +++ /dev/null @@ -1,110 +0,0 @@ -package mock - -import ( - "testing" - - "github.com/cosmos/cosmos-sdk/baseapp" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/crypto" - - abci "github.com/tendermint/tendermint/abci/types" -) - -var chainID = "" // TODO - -// set the mock app genesis -func SetGenesis(app *App, accs []auth.Account) { - - // pass the accounts in via the application (lazy) instead of through RequestInitChain - app.GenesisAccounts = accs - - app.InitChain(abci.RequestInitChain{}) - app.Commit() -} - -// check an account balance -func CheckBalance(t *testing.T, app *App, addr sdk.Address, exp sdk.Coins) { - ctxCheck := app.BaseApp.NewContext(true, abci.Header{}) - res := app.AccountMapper.GetAccount(ctxCheck, addr) - require.Equal(t, exp, res.GetCoins()) -} - -// generate a signed transaction -func GenTx(msgs []sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKeyEd25519) auth.StdTx { - - // make the transaction free - fee := auth.StdFee{ - sdk.Coins{sdk.NewCoin("foocoin", 0)}, - 100000, - } - - sigs := make([]auth.StdSignature, len(priv)) - memo := "testmemotestmemo" - for i, p := range priv { - sig, err := p.Sign(auth.StdSignBytes(chainID, accnums[i], seq[i], fee, msgs, memo)) - if err != nil { - panic(err) - } - sigs[i] = auth.StdSignature{ - PubKey: p.PubKey(), - Signature: sig, - AccountNumber: accnums[i], - Sequence: seq[i], - } - } - return auth.NewStdTx(msgs, fee, sigs, memo) -} - -// generate a set of signed transactions a msg, that differ only by having the -// sequence numbers incremented between every transaction. -func GenSequenceOfTxs(msgs []sdk.Msg, accnums []int64, initSeqNums []int64, numToGenerate int, priv ...crypto.PrivKeyEd25519) []auth.StdTx { - txs := make([]auth.StdTx, numToGenerate, numToGenerate) - for i := 0; i < numToGenerate; i++ { - txs[i] = GenTx(msgs, accnums, initSeqNums, priv...) - incrementAllSequenceNumbers(initSeqNums) - } - return txs -} - -func incrementAllSequenceNumbers(initSeqNums []int64) { - for i := 0; i < len(initSeqNums); i++ { - initSeqNums[i]++ - } -} - -// check a transaction result -func SignCheck(app *baseapp.BaseApp, msgs []sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKeyEd25519) sdk.Result { - tx := GenTx(msgs, accnums, seq, priv...) - res := app.Check(tx) - return res -} - -// simulate a block -func SignCheckDeliver(t *testing.T, app *baseapp.BaseApp, msgs []sdk.Msg, accnums []int64, seq []int64, expPass bool, priv ...crypto.PrivKeyEd25519) sdk.Result { - - // Sign the tx - tx := GenTx(msgs, accnums, seq, priv...) - - // Run a Check - res := app.Check(tx) - if expPass { - require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) - } else { - require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log) - } - - // Simulate a Block - app.BeginBlock(abci.RequestBeginBlock{}) - res = app.Deliver(tx) - if expPass { - require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) - } else { - require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log) - } - app.EndBlock(abci.RequestEndBlock{}) - - app.Commit() - return res -} diff --git a/x/bank/app_test.go b/x/bank/app_test.go index 72ea312a9..425e9aa2d 100644 --- a/x/bank/app_test.go +++ b/x/bank/app_test.go @@ -7,7 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/auth/mock" + "github.com/cosmos/cosmos-sdk/x/mock" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" diff --git a/x/bank/bench_test.go b/x/bank/bench_test.go index dce4d8fa9..be8319f9f 100644 --- a/x/bank/bench_test.go +++ b/x/bank/bench_test.go @@ -5,7 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/auth/mock" + "github.com/cosmos/cosmos-sdk/x/mock" abci "github.com/tendermint/tendermint/abci/types" ) diff --git a/x/gov/msgs_test.go b/x/gov/msgs_test.go index e9be4ded3..d0a629299 100644 --- a/x/gov/msgs_test.go +++ b/x/gov/msgs_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth/mock" + "github.com/cosmos/cosmos-sdk/x/mock" ) var ( diff --git a/x/gov/test_common.go b/x/gov/test_common.go index 743c5b639..70e47e86d 100644 --- a/x/gov/test_common.go +++ b/x/gov/test_common.go @@ -12,13 +12,13 @@ import ( "github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth/mock" "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/mock" "github.com/cosmos/cosmos-sdk/x/stake" ) // initialize the mock application for this module -func getMockApp(t *testing.T, numGenAccs int64) (*mock.App, Keeper, stake.Keeper, []sdk.Address, []crypto.PubKey, []crypto.PrivKey) { +func getMockApp(t *testing.T, numGenAccs int) (*mock.App, Keeper, stake.Keeper, []sdk.Address, []crypto.PubKey, []crypto.PrivKey) { mapp := mock.NewApp() stake.RegisterWire(mapp.Cdc) diff --git a/x/ibc/app_test.go b/x/ibc/app_test.go index 1540bf2ed..3671cd3e1 100644 --- a/x/ibc/app_test.go +++ b/x/ibc/app_test.go @@ -7,8 +7,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/auth/mock" "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/mock" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" diff --git a/x/mock/app.go b/x/mock/app.go new file mode 100644 index 000000000..e16a32268 --- /dev/null +++ b/x/mock/app.go @@ -0,0 +1,168 @@ +package mock + +import ( + "os" + + 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" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" + dbm "github.com/tendermint/tendermint/libs/db" + "github.com/tendermint/tendermint/libs/log" +) + +const chainID = "" + +// App extends an ABCI application. +type App struct { + *bam.BaseApp + Cdc *wire.Codec // Cdc is public since the codec is passed into the module anyways + KeyMain *sdk.KVStoreKey + KeyAccount *sdk.KVStoreKey + + // TODO: Abstract this out from not needing to be auth specifically + AccountMapper auth.AccountMapper + FeeCollectionKeeper auth.FeeCollectionKeeper + + GenesisAccounts []auth.Account +} + +// NewApp partially constructs a new app on the memstore for module and genesis +// testing. +func NewApp() *App { + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") + db := dbm.NewMemDB() + + // Create the cdc with some standard codecs + cdc := wire.NewCodec() + sdk.RegisterWire(cdc) + wire.RegisterCrypto(cdc) + auth.RegisterWire(cdc) + + // Create your application object + app := &App{ + BaseApp: bam.NewBaseApp("mock", cdc, logger, db), + Cdc: cdc, + KeyMain: sdk.NewKVStoreKey("main"), + KeyAccount: sdk.NewKVStoreKey("acc"), + } + + // Define the accountMapper + app.AccountMapper = auth.NewAccountMapper( + app.Cdc, + app.KeyAccount, + &auth.BaseAccount{}, + ) + + // Initialize the app. The chainers and blockers can be overwritten before + // calling complete setup. + app.SetInitChainer(app.InitChainer) + app.SetAnteHandler(auth.NewAnteHandler(app.AccountMapper, app.FeeCollectionKeeper)) + + return app +} + +// CompleteSetup completes the application setup after the routes have been +// registered. +func (app *App) CompleteSetup(newKeys []*sdk.KVStoreKey) error { + newKeys = append(newKeys, app.KeyMain) + newKeys = append(newKeys, app.KeyAccount) + + app.MountStoresIAVL(newKeys...) + err := app.LoadLatestVersion(app.KeyMain) + + return err +} + +// InitChainer performs custom logic for initialization. +func (app *App) InitChainer(ctx sdk.Context, _ abci.RequestInitChain) abci.ResponseInitChain { + // Load the genesis accounts + for _, genacc := range app.GenesisAccounts { + acc := app.AccountMapper.NewAccountWithAddress(ctx, genacc.GetAddress()) + acc.SetCoins(genacc.GetCoins()) + app.AccountMapper.SetAccount(ctx, acc) + } + + return abci.ResponseInitChain{} +} + +// CreateGenAccounts generates genesis accounts loaded with coins, and returns +// their addresses, pubkeys, and privkeys. +func CreateGenAccounts(numAccs int, genCoins sdk.Coins) (genAccs []auth.Account, addrs []sdk.Address, pubKeys []crypto.PubKey, privKeys []crypto.PrivKey) { + for i := 0; i < numAccs; i++ { + privKey := crypto.GenPrivKeyEd25519() + pubKey := privKey.PubKey() + addr := pubKey.Address() + + genAcc := &auth.BaseAccount{ + Address: addr, + Coins: genCoins, + } + + genAccs = append(genAccs, genAcc) + privKeys = append(privKeys, privKey) + pubKeys = append(pubKeys, pubKey) + addrs = append(addrs, addr) + } + + return +} + +// SetGenesis sets the mock app genesis accounts. +func SetGenesis(app *App, accs []auth.Account) { + // Pass the accounts in via the application (lazy) instead of through + // RequestInitChain. + app.GenesisAccounts = accs + + app.InitChain(abci.RequestInitChain{}) + app.Commit() +} + +// GenTx generates a signed mock transaction. +func GenTx(msgs []sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKey) auth.StdTx { + // Make the transaction free + fee := auth.StdFee{ + sdk.Coins{sdk.NewCoin("foocoin", 0)}, + 100000, + } + + sigs := make([]auth.StdSignature, len(priv)) + memo := "testmemotestmemo" + + for i, p := range priv { + sig, err := p.Sign(auth.StdSignBytes(chainID, accnums[i], seq[i], fee, msgs, memo)) + if err != nil { + panic(err) + } + + sigs[i] = auth.StdSignature{ + PubKey: p.PubKey(), + Signature: sig, + AccountNumber: accnums[i], + Sequence: seq[i], + } + } + + return auth.NewStdTx(msgs, fee, sigs, memo) +} + +// GenSequenceOfTxs generates a set of signed transactions of messages, such +// that they differ only by having the sequence numbers incremented between +// every transaction. +func GenSequenceOfTxs(msgs []sdk.Msg, accnums []int64, initSeqNums []int64, numToGenerate int, priv ...crypto.PrivKey) []auth.StdTx { + txs := make([]auth.StdTx, numToGenerate, numToGenerate) + for i := 0; i < numToGenerate; i++ { + txs[i] = GenTx(msgs, accnums, initSeqNums, priv...) + incrementAllSequenceNumbers(initSeqNums) + } + + return txs +} + +func incrementAllSequenceNumbers(initSeqNums []int64) { + for i := 0; i < len(initSeqNums); i++ { + initSeqNums[i]++ + } +} diff --git a/x/mock/app_test.go b/x/mock/app_test.go new file mode 100644 index 000000000..7ee82474c --- /dev/null +++ b/x/mock/app_test.go @@ -0,0 +1,102 @@ +package mock + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" +) + +const msgType = "testMsg" + +var ( + numAccts = 2 + genCoins = sdk.Coins{sdk.NewCoin("foocoin", 77)} + accs, addrs, pubKeys, privKeys = CreateGenAccounts(numAccts, genCoins) +) + +// testMsg is a mock transaction that has a validation which can fail. +type testMsg struct { + signers []sdk.Address + positiveNum int64 +} + +func (tx testMsg) Type() string { return msgType } +func (tx testMsg) GetMsg() sdk.Msg { return tx } +func (tx testMsg) GetMemo() string { return "" } +func (tx testMsg) GetSignBytes() []byte { return nil } +func (tx testMsg) GetSigners() []sdk.Address { return tx.signers } +func (tx testMsg) GetSignatures() []auth.StdSignature { return nil } +func (tx testMsg) ValidateBasic() sdk.Error { + if tx.positiveNum >= 0 { + return nil + } + return sdk.ErrTxDecode("positiveNum should be a non-negative integer.") +} + +// getMockApp returns an initialized mock application. +func getMockApp(t *testing.T) *App { + mApp := NewApp() + + mApp.Router().AddRoute(msgType, func(ctx sdk.Context, msg sdk.Msg) (res sdk.Result) { return }) + require.NoError(t, mApp.CompleteSetup([]*sdk.KVStoreKey{})) + + return mApp +} + +func TestCheckAndDeliverGenTx(t *testing.T) { + mApp := getMockApp(t) + mApp.Cdc.RegisterConcrete(testMsg{}, "mock/testMsg", nil) + + SetGenesis(mApp, accs) + ctxCheck := mApp.BaseApp.NewContext(true, abci.Header{}) + + msg := testMsg{signers: []sdk.Address{addrs[0]}, positiveNum: 1} + + acct := mApp.AccountMapper.GetAccount(ctxCheck, addrs[0]) + require.Equal(t, accs[0], acct.(*auth.BaseAccount)) + + SignCheckDeliver( + t, mApp.BaseApp, []sdk.Msg{msg}, + []int64{accs[0].GetAccountNumber()}, []int64{accs[0].GetSequence()}, + true, privKeys[0], + ) + + // Signing a tx with the wrong privKey should result in an auth error + res := SignCheckDeliver( + t, mApp.BaseApp, []sdk.Msg{msg}, + []int64{accs[1].GetAccountNumber()}, []int64{accs[1].GetSequence() + 1}, + false, privKeys[1], + ) + require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log) + + // Resigning the tx with the correct privKey should result in an OK result + SignCheckDeliver( + t, mApp.BaseApp, []sdk.Msg{msg}, + []int64{accs[0].GetAccountNumber()}, []int64{accs[0].GetSequence() + 1}, + true, privKeys[0], + ) +} + +func TestCheckGenTx(t *testing.T) { + mApp := getMockApp(t) + mApp.Cdc.RegisterConcrete(testMsg{}, "mock/testMsg", nil) + + SetGenesis(mApp, accs) + + msg1 := testMsg{signers: []sdk.Address{addrs[0]}, positiveNum: 1} + CheckGenTx( + t, mApp.BaseApp, []sdk.Msg{msg1}, + []int64{accs[0].GetAccountNumber()}, []int64{accs[0].GetSequence()}, + true, privKeys[0], + ) + + msg2 := testMsg{signers: []sdk.Address{addrs[0]}, positiveNum: -1} + CheckGenTx( + t, mApp.BaseApp, []sdk.Msg{msg2}, + []int64{accs[0].GetAccountNumber()}, []int64{accs[0].GetSequence()}, + false, privKeys[0], + ) +} diff --git a/x/mock/test_utils.go b/x/mock/test_utils.go new file mode 100644 index 000000000..f9620c140 --- /dev/null +++ b/x/mock/test_utils.go @@ -0,0 +1,71 @@ +package mock + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" +) + +// CheckBalance checks the balance of an account. +func CheckBalance(t *testing.T, app *App, addr sdk.Address, exp sdk.Coins) { + ctxCheck := app.BaseApp.NewContext(true, abci.Header{}) + res := app.AccountMapper.GetAccount(ctxCheck, addr) + + require.Equal(t, exp, res.GetCoins()) +} + +// CheckGenTx checks a generated signed transaction. The result of the check is +// compared against the parameter 'expPass'. A test assertion is made using the +// parameter 'expPass' against the result. A corresponding result is returned. +func CheckGenTx( + t *testing.T, app *baseapp.BaseApp, msgs []sdk.Msg, accNums []int64, + seq []int64, expPass bool, priv ...crypto.PrivKey, +) sdk.Result { + tx := GenTx(msgs, accNums, seq, priv...) + res := app.Check(tx) + + if expPass { + require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) + } else { + require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log) + } + + return res +} + +// SignCheckDeliver checks a generated signed transaction and simulates a +// block commitment with the given transaction. A test assertion is made using +// the parameter 'expPass' against the result. A corresponding result is +// returned. +func SignCheckDeliver( + t *testing.T, app *baseapp.BaseApp, msgs []sdk.Msg, accNums []int64, + seq []int64, expPass bool, priv ...crypto.PrivKey, +) sdk.Result { + tx := GenTx(msgs, accNums, seq, priv...) + res := app.Check(tx) + + if expPass { + require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) + } else { + require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log) + } + + // Simulate a sending a transaction and committing a block + app.BeginBlock(abci.RequestBeginBlock{}) + res = app.Deliver(tx) + + if expPass { + require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) + } else { + require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log) + } + + app.EndBlock(abci.RequestEndBlock{}) + app.Commit() + + return res +} diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index a64d3eb0f..d6fb0d9fe 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -5,11 +5,10 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/auth/mock" "github.com/cosmos/cosmos-sdk/x/bank" - "github.com/stretchr/testify/require" - + "github.com/cosmos/cosmos-sdk/x/mock" "github.com/cosmos/cosmos-sdk/x/stake" + "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" ) @@ -103,10 +102,9 @@ func TestSlashingMsgs(t *testing.T) { require.True(sdk.RatEq(t, sdk.NewRat(10), validator.PoolShares.Bonded())) unrevokeMsg := MsgUnrevoke{ValidatorAddr: validator.PubKey.Address()} - // no signing info yet checkValidatorSigningInfo(t, mapp, keeper, addr1, false) - // unrevoke should fail with validator not revoked - res := mock.SignCheck(mapp.BaseApp, []sdk.Msg{unrevokeMsg}, []int64{0}, []int64{1}, priv1) + // unrevoke should fail with unknown validator + res := mock.CheckGenTx(t, mapp.BaseApp, []sdk.Msg{unrevokeMsg}, []int64{0}, []int64{1}, false, priv1) require.Equal(t, sdk.ToABCICode(DefaultCodespace, CodeValidatorNotRevoked), res.Code) } diff --git a/x/stake/app_test.go b/x/stake/app_test.go index d4fc5bdf0..02dd09134 100644 --- a/x/stake/app_test.go +++ b/x/stake/app_test.go @@ -5,11 +5,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/auth/mock" "github.com/cosmos/cosmos-sdk/x/bank" - "github.com/stretchr/testify/assert" + "github.com/cosmos/cosmos-sdk/x/mock" "github.com/stretchr/testify/require" - abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" ) @@ -22,81 +20,86 @@ var ( addr3 = crypto.GenPrivKeyEd25519().PubKey().Address() priv4 = crypto.GenPrivKeyEd25519() addr4 = priv4.PubKey().Address() - coins = sdk.Coins{{"foocoin", sdk.NewInt(10)}} - fee = auth.StdFee{ - sdk.Coins{{"foocoin", sdk.NewInt(0)}}, - 100000, - } + coins = sdk.NewCoin("foocoin", 10) + fee = auth.StdFee{sdk.Coins{sdk.NewCoin("foocoin", 0)}, 100000} ) -// initialize the mock application for this module +// getMockApp returns an initialized mock application for this module. func getMockApp(t *testing.T) (*mock.App, Keeper) { - mapp := mock.NewApp() + mApp := mock.NewApp() + + RegisterWire(mApp.Cdc) - RegisterWire(mapp.Cdc) keyStake := sdk.NewKVStoreKey("stake") - coinKeeper := bank.NewKeeper(mapp.AccountMapper) - keeper := NewKeeper(mapp.Cdc, keyStake, coinKeeper, mapp.RegisterCodespace(DefaultCodespace)) - mapp.Router().AddRoute("stake", NewHandler(keeper)) + coinKeeper := bank.NewKeeper(mApp.AccountMapper) + keeper := NewKeeper(mApp.Cdc, keyStake, coinKeeper, mApp.RegisterCodespace(DefaultCodespace)) - mapp.SetEndBlocker(getEndBlocker(keeper)) - mapp.SetInitChainer(getInitChainer(mapp, keeper)) + mApp.Router().AddRoute("stake", NewHandler(keeper)) + mApp.SetEndBlocker(getEndBlocker(keeper)) + mApp.SetInitChainer(getInitChainer(mApp, keeper)) - require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyStake})) - return mapp, keeper + require.NoError(t, mApp.CompleteSetup([]*sdk.KVStoreKey{keyStake})) + return mApp, keeper } -// stake endblocker +// getEndBlocker returns a stake endblocker. func getEndBlocker(keeper Keeper) sdk.EndBlocker { return func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { validatorUpdates := EndBlocker(ctx, keeper) + return abci.ResponseEndBlock{ ValidatorUpdates: validatorUpdates, } } } -// overwrite the mock init chainer +// getInitChainer initializes the chainer of the mock app and sets the genesis +// state. It returns an empty ResponseInitChain. func getInitChainer(mapp *mock.App, keeper Keeper) sdk.InitChainer { return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { mapp.InitChainer(ctx, req) + stakeGenesis := DefaultGenesisState() stakeGenesis.Pool.LooseTokens = 100000 + InitGenesis(ctx, keeper, stakeGenesis) return abci.ResponseInitChain{} } } -//__________________________________________________________________________________________ - -func checkValidator(t *testing.T, mapp *mock.App, keeper Keeper, - addr sdk.Address, expFound bool) Validator { - +func checkValidator( + t *testing.T, mapp *mock.App, keeper Keeper, + addr sdk.Address, expFound bool, +) Validator { ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{}) validator, found := keeper.GetValidator(ctxCheck, addr1) + require.Equal(t, expFound, found) return validator } -func checkDelegation(t *testing.T, mapp *mock.App, keeper Keeper, delegatorAddr, - validatorAddr sdk.Address, expFound bool, expShares sdk.Rat) { - +func checkDelegation( + t *testing.T, mapp *mock.App, keeper Keeper, delegatorAddr, + validatorAddr sdk.Address, expFound bool, expShares sdk.Rat, +) { ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{}) delegation, found := keeper.GetDelegation(ctxCheck, delegatorAddr, validatorAddr) if expFound { require.True(t, found) - assert.True(sdk.RatEq(t, expShares, delegation.Shares)) + require.True(sdk.RatEq(t, expShares, delegation.Shares)) + return } + require.False(t, found) } func TestStakeMsgs(t *testing.T) { - mapp, keeper := getMockApp(t) + mApp, keeper := getMockApp(t) - genCoin := sdk.Coin{"steak", sdk.NewInt(42)} - bondCoin := sdk.Coin{"steak", sdk.NewInt(10)} + genCoin := sdk.NewCoin("steak", 42) + bondCoin := sdk.NewCoin("steak", 10) acc1 := &auth.BaseAccount{ Address: addr1, @@ -108,56 +111,51 @@ func TestStakeMsgs(t *testing.T) { } accs := []auth.Account{acc1, acc2} - mock.SetGenesis(mapp, accs) - mock.CheckBalance(t, mapp, addr1, sdk.Coins{genCoin}) - mock.CheckBalance(t, mapp, addr2, sdk.Coins{genCoin}) - - //////////////////// - // Create Validator + mock.SetGenesis(mApp, accs) + mock.CheckBalance(t, mApp, addr1, sdk.Coins{genCoin}) + mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin}) + // create validator description := NewDescription("foo_moniker", "", "", "") createValidatorMsg := NewMsgCreateValidator( addr1, priv1.PubKey(), bondCoin, description, ) - mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{createValidatorMsg}, []int64{0}, []int64{0}, true, priv1) - mock.CheckBalance(t, mapp, addr1, sdk.Coins{genCoin.Minus(bondCoin)}) - mapp.BeginBlock(abci.RequestBeginBlock{}) - validator := checkValidator(t, mapp, keeper, addr1, true) + mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{createValidatorMsg}, []int64{0}, []int64{0}, true, priv1) + mock.CheckBalance(t, mApp, addr1, sdk.Coins{genCoin.Minus(bondCoin)}) + mApp.BeginBlock(abci.RequestBeginBlock{}) + + validator := checkValidator(t, mApp, keeper, addr1, true) require.Equal(t, addr1, validator.Owner) require.Equal(t, sdk.Bonded, validator.Status()) require.True(sdk.RatEq(t, sdk.NewRat(10), validator.PoolShares.Bonded())) // check the bond that should have been created as well - checkDelegation(t, mapp, keeper, addr1, addr1, true, sdk.NewRat(10)) - - //////////////////// - // Edit Validator + checkDelegation(t, mApp, keeper, addr1, addr1, true, sdk.NewRat(10)) + // edit the validator description = NewDescription("bar_moniker", "", "", "") editValidatorMsg := NewMsgEditValidator(addr1, description) - mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{editValidatorMsg}, []int64{0}, []int64{1}, true, priv1) - validator = checkValidator(t, mapp, keeper, addr1, true) + + mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{editValidatorMsg}, []int64{0}, []int64{1}, true, priv1) + validator = checkValidator(t, mApp, keeper, addr1, true) require.Equal(t, description, validator.Description) - //////////////////// - // Delegate - - mock.CheckBalance(t, mapp, addr2, sdk.Coins{genCoin}) + // delegate + mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin}) delegateMsg := NewMsgDelegate(addr2, addr1, bondCoin) - mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{delegateMsg}, []int64{1}, []int64{0}, true, priv2) - mock.CheckBalance(t, mapp, addr2, sdk.Coins{genCoin.Minus(bondCoin)}) - checkDelegation(t, mapp, keeper, addr2, addr1, true, sdk.NewRat(10)) - //////////////////// - // Begin Unbonding + mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{delegateMsg}, []int64{1}, []int64{0}, true, priv2) + mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)}) + checkDelegation(t, mApp, keeper, addr2, addr1, true, sdk.NewRat(10)) + // begin unbonding beginUnbondingMsg := NewMsgBeginUnbonding(addr2, addr1, sdk.NewRat(10)) - mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{beginUnbondingMsg}, []int64{1}, []int64{1}, true, priv2) + mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{beginUnbondingMsg}, []int64{1}, []int64{1}, true, priv2) // delegation should exist anymore - checkDelegation(t, mapp, keeper, addr2, addr1, false, sdk.Rat{}) + checkDelegation(t, mApp, keeper, addr2, addr1, false, sdk.Rat{}) // balance should be the same because bonding not yet complete - mock.CheckBalance(t, mapp, addr2, sdk.Coins{genCoin.Minus(bondCoin)}) + mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)}) } diff --git a/x/stake/genesis.go b/x/stake/genesis.go index 55dd06f76..1116a4748 100644 --- a/x/stake/genesis.go +++ b/x/stake/genesis.go @@ -1,50 +1,58 @@ package stake import ( - tmtypes "github.com/tendermint/tendermint/types" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" + tmtypes "github.com/tendermint/tendermint/types" ) -// InitGenesis - store genesis parameters +// InitGenesis sets the pool and parameters for the provided keeper and +// initializes the IntraTxCounter. For each validator in data, it sets that +// validator in the keeper along with manually setting the indexes. In +// addition, it also sets any delegations found in data. Finally, it updates +// the bonded validators. func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) { keeper.SetPool(ctx, data.Pool) keeper.SetNewParams(ctx, data.Params) keeper.InitIntraTxCounter(ctx) - for _, validator := range data.Validators { - // set validator + for _, validator := range data.Validators { keeper.SetValidator(ctx, validator) - // manually set indexes for the first time + // Manually set indexes for the first time keeper.SetValidatorByPubKeyIndex(ctx, validator) keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool) + if validator.Status() == sdk.Bonded { keeper.SetValidatorBondedIndex(ctx, validator) } } + for _, bond := range data.Bonds { keeper.SetDelegation(ctx, bond) } + keeper.UpdateBondedValidatorsFull(ctx) } -// WriteGenesis - output genesis parameters +// WriteGenesis returns a GenesisState for a given context and keeper. The +// GenesisState will contain the pool, params, validators, and bonds found in +// the keeper. func WriteGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState { pool := keeper.GetPool(ctx) params := keeper.GetParams(ctx) validators := keeper.GetAllValidators(ctx) bonds := keeper.GetAllDelegations(ctx) + return types.GenesisState{ - pool, - params, - validators, - bonds, + Pool: pool, + Params: params, + Validators: validators, + Bonds: bonds, } } -// WriteValidators - output current validator set +// WriteValidators returns a slice of bonded genesis validators. func WriteValidators(ctx sdk.Context, keeper Keeper) (vals []tmtypes.GenesisValidator) { keeper.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) (stop bool) { vals = append(vals, tmtypes.GenesisValidator{ @@ -52,7 +60,9 @@ func WriteValidators(ctx sdk.Context, keeper Keeper) (vals []tmtypes.GenesisVali Power: validator.GetPower().RoundInt64(), Name: validator.GetMoniker(), }) + return false }) + return } diff --git a/x/stake/stake.go b/x/stake/stake.go index 5e4356b81..869b838ff 100644 --- a/x/stake/stake.go +++ b/x/stake/stake.go @@ -7,30 +7,29 @@ import ( "github.com/cosmos/cosmos-sdk/x/stake/types" ) -// keeper -type Keeper = keeper.Keeper - -var NewKeeper = keeper.NewKeeper - -// types -type Validator = types.Validator -type Description = types.Description -type Delegation = types.Delegation -type UnbondingDelegation = types.UnbondingDelegation -type Redelegation = types.Redelegation -type Params = types.Params -type Pool = types.Pool -type PoolShares = types.PoolShares -type MsgCreateValidator = types.MsgCreateValidator -type MsgEditValidator = types.MsgEditValidator -type MsgDelegate = types.MsgDelegate -type MsgBeginUnbonding = types.MsgBeginUnbonding -type MsgCompleteUnbonding = types.MsgCompleteUnbonding -type MsgBeginRedelegate = types.MsgBeginRedelegate -type MsgCompleteRedelegate = types.MsgCompleteRedelegate -type GenesisState = types.GenesisState +type ( + Keeper = keeper.Keeper + Validator = types.Validator + Description = types.Description + Delegation = types.Delegation + UnbondingDelegation = types.UnbondingDelegation + Redelegation = types.Redelegation + Params = types.Params + Pool = types.Pool + PoolShares = types.PoolShares + MsgCreateValidator = types.MsgCreateValidator + MsgEditValidator = types.MsgEditValidator + MsgDelegate = types.MsgDelegate + MsgBeginUnbonding = types.MsgBeginUnbonding + MsgCompleteUnbonding = types.MsgCompleteUnbonding + MsgBeginRedelegate = types.MsgBeginRedelegate + MsgCompleteRedelegate = types.MsgCompleteRedelegate + GenesisState = types.GenesisState +) var ( + NewKeeper = keeper.NewKeeper + GetValidatorKey = keeper.GetValidatorKey GetValidatorByPubKeyIndexKey = keeper.GetValidatorByPubKeyIndexKey GetValidatorsBondedIndexKey = keeper.GetValidatorsBondedIndexKey @@ -72,7 +71,6 @@ var ( DefaultGenesisState = types.DefaultGenesisState RegisterWire = types.RegisterWire - // messages NewMsgCreateValidator = types.NewMsgCreateValidator NewMsgEditValidator = types.NewMsgEditValidator NewMsgDelegate = types.NewMsgDelegate @@ -82,7 +80,6 @@ var ( NewMsgCompleteRedelegate = types.NewMsgCompleteRedelegate ) -// errors const ( DefaultCodespace = types.DefaultCodespace CodeInvalidValidator = types.CodeInvalidValidator @@ -126,7 +123,6 @@ var ( ErrMissingSignature = types.ErrMissingSignature ) -// tags var ( ActionCreateValidator = tags.ActionCreateValidator ActionEditValidator = tags.ActionEditValidator diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index eb38a50a7..a7d0a1f8c 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -17,7 +17,7 @@ type Delegation struct { Height int64 `json:"height"` // Last height bond updated } -// two are equal +// Equal returns a boolean determining if two Delegation types are identical. func (d Delegation) Equal(d2 Delegation) bool { return bytes.Equal(d.DelegatorAddr, d2.DelegatorAddr) && bytes.Equal(d.ValidatorAddr, d2.ValidatorAddr) && @@ -33,16 +33,20 @@ func (d Delegation) GetDelegator() sdk.Address { return d.DelegatorAddr } func (d Delegation) GetValidator() sdk.Address { return d.ValidatorAddr } func (d Delegation) GetBondShares() sdk.Rat { return d.Shares } -//Human Friendly pretty printer +// HumanReadableString returns a human readable string representation of a +// Delegation. An error is returned if the Delegation's delegator or validator +// addresses cannot be Bech32 encoded. func (d Delegation) HumanReadableString() (string, error) { bechAcc, err := sdk.Bech32ifyAcc(d.DelegatorAddr) if err != nil { return "", err } + bechVal, err := sdk.Bech32ifyAcc(d.ValidatorAddr) if err != nil { return "", err } + resp := "Delegation \n" resp += fmt.Sprintf("Delegator: %s\n", bechAcc) resp += fmt.Sprintf("Validator: %s\n", bechVal) @@ -50,12 +54,9 @@ func (d Delegation) HumanReadableString() (string, error) { resp += fmt.Sprintf("Height: %d", d.Height) return resp, nil - } -//__________________________________________________________________ - -// element stored to represent the passive unbonding queue +// UnbondingDelegation reflects a delegation's passive unbonding queue. type UnbondingDelegation struct { DelegatorAddr sdk.Address `json:"delegator_addr"` // delegator ValidatorAddr sdk.Address `json:"validator_addr"` // validator unbonding from owner addr @@ -65,23 +66,28 @@ type UnbondingDelegation struct { Balance sdk.Coin `json:"balance"` // atoms to receive at completion } -// nolint +// Equal returns a boolean determining if two UnbondingDelegation types are +// identical. func (d UnbondingDelegation) Equal(d2 UnbondingDelegation) bool { bz1 := MsgCdc.MustMarshalBinary(&d) bz2 := MsgCdc.MustMarshalBinary(&d2) return bytes.Equal(bz1, bz2) } -//Human Friendly pretty printer +// HumanReadableString returns a human readable string representation of an +// UnbondingDelegation. An error is returned if the UnbondingDelegation's +// delegator or validator addresses cannot be Bech32 encoded. func (d UnbondingDelegation) HumanReadableString() (string, error) { bechAcc, err := sdk.Bech32ifyAcc(d.DelegatorAddr) if err != nil { return "", err } + bechVal, err := sdk.Bech32ifyAcc(d.ValidatorAddr) if err != nil { return "", err } + resp := "Unbonding Delegation \n" resp += fmt.Sprintf("Delegator: %s\n", bechAcc) resp += fmt.Sprintf("Validator: %s\n", bechVal) @@ -93,9 +99,7 @@ func (d UnbondingDelegation) HumanReadableString() (string, error) { } -//__________________________________________________________________ - -// element stored to represent the passive redelegation queue +// Redelegation reflects a delegation's passive re-delegation queue. type Redelegation struct { DelegatorAddr sdk.Address `json:"delegator_addr"` // delegator ValidatorSrcAddr sdk.Address `json:"validator_src_addr"` // validator redelegation source owner addr @@ -108,27 +112,32 @@ type Redelegation struct { SharesDst sdk.Rat `json:"shares_dst"` // amount of destination shares redelegating } -// nolint +// Equal returns a boolean determining if two Redelegation types are identical. func (d Redelegation) Equal(d2 Redelegation) bool { bz1 := MsgCdc.MustMarshalBinary(&d) bz2 := MsgCdc.MustMarshalBinary(&d2) return bytes.Equal(bz1, bz2) } -//Human Friendly pretty printer +// HumanReadableString returns a human readable string representation of a +// Redelegation. An error is returned if the UnbondingDelegation's delegator or +// validator addresses cannot be Bech32 encoded. func (d Redelegation) HumanReadableString() (string, error) { bechAcc, err := sdk.Bech32ifyAcc(d.DelegatorAddr) if err != nil { return "", err } + bechValSrc, err := sdk.Bech32ifyAcc(d.ValidatorSrcAddr) if err != nil { return "", err } + bechValDst, err := sdk.Bech32ifyAcc(d.ValidatorDstAddr) if err != nil { return "", err } + resp := "Redelegation \n" resp += fmt.Sprintf("Delegator: %s\n", bechAcc) resp += fmt.Sprintf("Source Validator: %s\n", bechValSrc) diff --git a/x/stake/types/delegation_test.go b/x/stake/types/delegation_test.go new file mode 100644 index 000000000..640f5d979 --- /dev/null +++ b/x/stake/types/delegation_test.go @@ -0,0 +1,116 @@ +package types + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestDelegationEqual(t *testing.T) { + d1 := Delegation{ + DelegatorAddr: addr1, + ValidatorAddr: addr2, + Shares: sdk.NewRat(100), + } + d2 := Delegation{ + DelegatorAddr: addr1, + ValidatorAddr: addr2, + Shares: sdk.NewRat(100), + } + + ok := d1.Equal(d2) + require.True(t, ok) + + d2.ValidatorAddr = addr3 + d2.Shares = sdk.NewRat(200) + + ok = d1.Equal(d2) + require.False(t, ok) +} + +func TestDelegationHumanReadableString(t *testing.T) { + d := Delegation{ + DelegatorAddr: addr1, + ValidatorAddr: addr2, + Shares: sdk.NewRat(100), + } + + // NOTE: Being that the validator's keypair is random, we cannot test the + // actual contents of the string. + valStr, err := d.HumanReadableString() + require.Nil(t, err) + require.NotEmpty(t, valStr) +} + +func TestUnbondingDelegationEqual(t *testing.T) { + ud1 := UnbondingDelegation{ + DelegatorAddr: addr1, + ValidatorAddr: addr2, + } + ud2 := UnbondingDelegation{ + DelegatorAddr: addr1, + ValidatorAddr: addr2, + } + + ok := ud1.Equal(ud2) + require.True(t, ok) + + ud2.ValidatorAddr = addr3 + ud2.MinTime = 20 * 20 * 2 + + ok = ud1.Equal(ud2) + require.False(t, ok) +} + +func TestUnbondingDelegationHumanReadableString(t *testing.T) { + ud := UnbondingDelegation{ + DelegatorAddr: addr1, + ValidatorAddr: addr2, + } + + // NOTE: Being that the validator's keypair is random, we cannot test the + // actual contents of the string. + valStr, err := ud.HumanReadableString() + require.Nil(t, err) + require.NotEmpty(t, valStr) +} + +func TestRedelegationEqual(t *testing.T) { + r1 := Redelegation{ + DelegatorAddr: addr1, + ValidatorSrcAddr: addr2, + ValidatorDstAddr: addr3, + } + r2 := Redelegation{ + DelegatorAddr: addr1, + ValidatorSrcAddr: addr2, + ValidatorDstAddr: addr3, + } + + ok := r1.Equal(r2) + require.True(t, ok) + + r2.SharesDst = sdk.NewRat(10) + r2.SharesSrc = sdk.NewRat(20) + r2.MinTime = 20 * 20 * 2 + + ok = r1.Equal(r2) + require.False(t, ok) +} + +func TestRedelegationHumanReadableString(t *testing.T) { + r := Redelegation{ + DelegatorAddr: addr1, + ValidatorSrcAddr: addr2, + ValidatorDstAddr: addr3, + SharesDst: sdk.NewRat(10), + SharesSrc: sdk.NewRat(20), + } + + // NOTE: Being that the validator's keypair is random, we cannot test the + // actual contents of the string. + valStr, err := r.HumanReadableString() + require.Nil(t, err) + require.NotEmpty(t, valStr) +} diff --git a/x/stake/types/errors.go b/x/stake/types/errors.go index 2914741f4..09ed2d369 100644 --- a/x/stake/types/errors.go +++ b/x/stake/types/errors.go @@ -25,97 +25,118 @@ const ( func ErrNilValidatorAddr(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidInput, "validator address is nil") } + func ErrNoValidatorFound(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "validator does not exist for that address") } + func ErrValidatorAlreadyExists(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "validator already exist, cannot re-create validator") } + func ErrValidatorRevoked(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "validator for this address is currently revoked") } + func ErrBadRemoveValidator(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "error removing validator") } + func ErrDescriptionLength(codespace sdk.CodespaceType, descriptor string, got, max int) sdk.Error { msg := fmt.Sprintf("bad description length for %v, got length %v, max is %v", descriptor, got, max) return sdk.NewError(codespace, CodeInvalidValidator, msg) } + func ErrCommissionNegative(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "commission must be positive") } + func ErrCommissionHuge(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than 100%") } -// delegation func ErrNilDelegatorAddr(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidInput, "delegator address is nil") } + func ErrBadDenom(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "invalid coin denomination") } + func ErrBadDelegationAmount(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "amount must be > 0") } + func ErrNoDelegation(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "no delegation for this (address, validator) pair") } + func ErrBadDelegatorAddr(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "delegator does not exist for that address") } + func ErrNoDelegatorForAddress(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "delegator does not contain this delegation") } + func ErrInsufficientShares(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "insufficient delegation shares") } + func ErrDelegationValidatorEmpty(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "cannot delegate to an empty validator") } + func ErrNotEnoughDelegationShares(codespace sdk.CodespaceType, shares string) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, fmt.Sprintf("not enough shares only have %v", shares)) } + func ErrBadSharesAmount(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "shares must be > 0") } + func ErrBadSharesPrecision(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, fmt.Sprintf("shares denominator must be < %s, try reducing the number of decimal points", maximumBondingRationalDenominator.String()), ) } + func ErrBadSharesPercent(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "shares percent must be >0 and <=1") } -// redelegation func ErrNotMature(codespace sdk.CodespaceType, operation, descriptor string, got, min int64) sdk.Error { msg := fmt.Sprintf("%v is not mature requires a min %v of %v, currently it is %v", operation, descriptor, got, min) return sdk.NewError(codespace, CodeUnauthorized, msg) } + func ErrNoUnbondingDelegation(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "no unbonding delegation found") } + func ErrNoRedelegation(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "no redelegation found") } + func ErrBadRedelegationDst(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "redelegation validator not found") } + func ErrTransitiveRedelegation(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "redelegation to this validator already in progress, first redelegation to this validator must complete before next redelegation") } -// messages func ErrBothShareMsgsGiven(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidInput, "both shares amount and shares percent provided") } + func ErrNeitherShareMsgsGiven(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidInput, "neither shares amount nor shares percent provided") } + func ErrMissingSignature(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "missing signature") } diff --git a/x/stake/types/msg_test.go b/x/stake/types/msg_test.go index f3d8bc686..1a854a492 100644 --- a/x/stake/types/msg_test.go +++ b/x/stake/types/msg_test.go @@ -10,9 +10,9 @@ import ( ) var ( - coinPos = sdk.Coin{"steak", sdk.NewInt(1000)} - coinZero = sdk.Coin{"steak", sdk.NewInt(0)} - coinNeg = sdk.Coin{"steak", sdk.NewInt(-10000)} + coinPos = sdk.NewCoin("steak", 1000) + coinZero = sdk.NewCoin("steak", 0) + coinNeg = sdk.NewCoin("steak", -10000) ) // test ValidateBasic for MsgCreateValidator @@ -197,29 +197,3 @@ func TestMsgCompleteUnbonding(t *testing.T) { } } } - -// TODO introduce with go-amino -//func TestSerializeMsg(t *testing.T) { - -//// make sure all types construct properly -//bondAmt := 1234321 -//bond := sdk.Coin{Denom: "atom", Amount: int64(bondAmt)} - -//tests := []struct { -//tx sdk.Msg -//}{ -//{NewMsgCreateValidator(addr1, pk1, bond, Description{})}, -//{NewMsgEditValidator(addr1, Description{})}, -//{NewMsgDelegate(addr1, addr2, bond)}, -//{NewMsgUnbond(addr1, addr2, strconv.Itoa(bondAmt))}, -//} - -//for i, tc := range tests { -//var tx sdk.Tx -//bs := wire.BinaryBytes(tc.tx) -//err := wire.ReadBinaryBytes(bs, &tx) -//if require.NoError(t, err, "%d", i) { -//require.Equal(t, tc.tx, tx, "%d", i) -//} -//} -//} diff --git a/x/stake/types/params.go b/x/stake/types/params.go index 8c1b897f2..5a7dd6ef5 100644 --- a/x/stake/types/params.go +++ b/x/stake/types/params.go @@ -6,6 +6,10 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +// defaultUnbondingTime reflects three weeks in seconds as the default +// unbonding time. +const defaultUnbondingTime int64 = 60 * 60 * 24 * 3 + // Params defines the high level settings for staking type Params struct { InflationRateChange sdk.Rat `json:"inflation_rate_change"` // maximum annual change in inflation rate @@ -19,21 +23,21 @@ type Params struct { BondDenom string `json:"bond_denom"` // bondable coin denomination } -// nolint +// Equal returns a boolean determining if two Param types are identical. func (p Params) Equal(p2 Params) bool { bz1 := MsgCdc.MustMarshalBinary(&p) bz2 := MsgCdc.MustMarshalBinary(&p2) return bytes.Equal(bz1, bz2) } -// default params +// DefaultParams returns a default set of parameters. func DefaultParams() Params { return Params{ InflationRateChange: sdk.NewRat(13, 100), InflationMax: sdk.NewRat(20, 100), InflationMin: sdk.NewRat(7, 100), GoalBonded: sdk.NewRat(67, 100), - UnbondingTime: 60 * 60 * 24 * 3, // 3 weeks in seconds + UnbondingTime: defaultUnbondingTime, MaxValidators: 100, BondDenom: "steak", } diff --git a/x/stake/types/params_test.go b/x/stake/types/params_test.go new file mode 100644 index 000000000..c18700ef4 --- /dev/null +++ b/x/stake/types/params_test.go @@ -0,0 +1,21 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParamsEqual(t *testing.T) { + p1 := DefaultParams() + p2 := DefaultParams() + + ok := p1.Equal(p2) + require.True(t, ok) + + p2.UnbondingTime = 60 * 60 * 24 * 2 + p2.BondDenom = "soup" + + ok = p1.Equal(p2) + require.False(t, ok) +} diff --git a/x/stake/types/pool_test.go b/x/stake/types/pool_test.go index a62c69d46..3a52646f6 100644 --- a/x/stake/types/pool_test.go +++ b/x/stake/types/pool_test.go @@ -3,11 +3,24 @@ package types import ( "testing" - "github.com/stretchr/testify/require" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" ) +func TestPoolEqual(t *testing.T) { + p1 := InitialPool() + p2 := InitialPool() + + ok := p1.Equal(p2) + require.True(t, ok) + + p2.BondedTokens = 3 + p2.BondedShares = sdk.NewRat(10) + + ok = p1.Equal(p2) + require.False(t, ok) +} + func TestBondedRatio(t *testing.T) { pool := InitialPool() pool.LooseTokens = 1 @@ -62,10 +75,10 @@ func TestUnbondedShareExRate(t *testing.T) { } func TestAddTokensBonded(t *testing.T) { - poolA := InitialPool() poolA.LooseTokens = 10 require.Equal(t, poolA.BondedShareExRate(), sdk.OneRat()) + poolB, sharesB := poolA.addTokensBonded(10) require.Equal(t, poolB.BondedShareExRate(), sdk.OneRat()) @@ -78,10 +91,10 @@ func TestAddTokensBonded(t *testing.T) { } func TestRemoveSharesBonded(t *testing.T) { - poolA := InitialPool() poolA.LooseTokens = 10 require.Equal(t, poolA.BondedShareExRate(), sdk.OneRat()) + poolB, tokensB := poolA.removeSharesBonded(sdk.NewRat(10)) require.Equal(t, poolB.BondedShareExRate(), sdk.OneRat()) @@ -94,10 +107,10 @@ func TestRemoveSharesBonded(t *testing.T) { } func TestAddTokensUnbonded(t *testing.T) { - poolA := InitialPool() poolA.LooseTokens = 10 require.Equal(t, poolA.UnbondedShareExRate(), sdk.OneRat()) + poolB, sharesB := poolA.addTokensUnbonded(10) require.Equal(t, poolB.UnbondedShareExRate(), sdk.OneRat()) @@ -110,11 +123,11 @@ func TestAddTokensUnbonded(t *testing.T) { } func TestRemoveSharesUnbonded(t *testing.T) { - poolA := InitialPool() poolA.UnbondedTokens = 10 poolA.UnbondedShares = sdk.NewRat(10) require.Equal(t, poolA.UnbondedShareExRate(), sdk.OneRat()) + poolB, tokensB := poolA.removeSharesUnbonded(sdk.NewRat(10)) require.Equal(t, poolB.UnbondedShareExRate(), sdk.OneRat()) diff --git a/x/stake/types/shares.go b/x/stake/types/shares.go index 09301d0db..5a2cb2be6 100644 --- a/x/stake/types/shares.go +++ b/x/stake/types/shares.go @@ -4,18 +4,19 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// pool shares held by a validator +// PoolShares reflects the shares of a validator in a pool. type PoolShares struct { Status sdk.BondStatus `json:"status"` - Amount sdk.Rat `json:"amount"` // total shares of type ShareKind + Amount sdk.Rat `json:"amount"` } -// only the vitals - does not check bond height of IntraTxCounter +// Equal returns a boolean determining of two PoolShares are identical. func (s PoolShares) Equal(s2 PoolShares) bool { return s.Status == s2.Status && s.Amount.Equal(s2.Amount) } +// NewUnbondedShares returns a new PoolShares with a specified unbonded amount. func NewUnbondedShares(amount sdk.Rat) PoolShares { return PoolShares{ Status: sdk.Unbonded, @@ -23,6 +24,8 @@ func NewUnbondedShares(amount sdk.Rat) PoolShares { } } +// NewUnbondingShares returns a new PoolShares with a specified unbonding +// amount. func NewUnbondingShares(amount sdk.Rat) PoolShares { return PoolShares{ Status: sdk.Unbonding, @@ -30,6 +33,7 @@ func NewUnbondingShares(amount sdk.Rat) PoolShares { } } +// NewBondedShares returns a new PoolSahres with a specified bonding amount. func NewBondedShares(amount sdk.Rat) PoolShares { return PoolShares{ Status: sdk.Bonded, @@ -37,9 +41,7 @@ func NewBondedShares(amount sdk.Rat) PoolShares { } } -//_________________________________________________________________________________________________________ - -// amount of unbonded shares +// Unbonded returns the amount of unbonded shares. func (s PoolShares) Unbonded() sdk.Rat { if s.Status == sdk.Unbonded { return s.Amount @@ -47,7 +49,7 @@ func (s PoolShares) Unbonded() sdk.Rat { return sdk.ZeroRat() } -// amount of unbonding shares +// Unbonding returns the amount of unbonding shares. func (s PoolShares) Unbonding() sdk.Rat { if s.Status == sdk.Unbonding { return s.Amount @@ -55,7 +57,7 @@ func (s PoolShares) Unbonding() sdk.Rat { return sdk.ZeroRat() } -// amount of bonded shares +// Bonded returns amount of bonded shares. func (s PoolShares) Bonded() sdk.Rat { if s.Status == sdk.Bonded { return s.Amount @@ -63,64 +65,80 @@ func (s PoolShares) Bonded() sdk.Rat { return sdk.ZeroRat() } -//_________________________________________________________________________________________________________ - -// equivalent amount of shares if the shares were unbonded +// ToUnbonded returns the equivalent amount of pool shares if the shares were +// unbonded. func (s PoolShares) ToUnbonded(p Pool) PoolShares { var amount sdk.Rat + switch s.Status { case sdk.Bonded: - exRate := p.BondedShareExRate().Quo(p.UnbondedShareExRate()) // (tok/bondedshr)/(tok/unbondedshr) = unbondedshr/bondedshr - amount = s.Amount.Mul(exRate) // bondedshr*unbondedshr/bondedshr = unbondedshr + // (tok/bondedshr)/(tok/unbondedshr) = unbondedshr/bondedshr + exRate := p.BondedShareExRate().Quo(p.UnbondedShareExRate()) + // bondedshr*unbondedshr/bondedshr = unbondedshr + amount = s.Amount.Mul(exRate) case sdk.Unbonding: - exRate := p.UnbondingShareExRate().Quo(p.UnbondedShareExRate()) // (tok/unbondingshr)/(tok/unbondedshr) = unbondedshr/unbondingshr - amount = s.Amount.Mul(exRate) // unbondingshr*unbondedshr/unbondingshr = unbondedshr + // (tok/unbondingshr)/(tok/unbondedshr) = unbondedshr/unbondingshr + exRate := p.UnbondingShareExRate().Quo(p.UnbondedShareExRate()) + // unbondingshr*unbondedshr/unbondingshr = unbondedshr + amount = s.Amount.Mul(exRate) case sdk.Unbonded: amount = s.Amount } + return NewUnbondedShares(amount) } -// equivalent amount of shares if the shares were unbonding +// ToUnbonding returns the equivalent amount of pool shares if the shares were +// unbonding. func (s PoolShares) ToUnbonding(p Pool) PoolShares { var amount sdk.Rat + switch s.Status { case sdk.Bonded: - exRate := p.BondedShareExRate().Quo(p.UnbondingShareExRate()) // (tok/bondedshr)/(tok/unbondingshr) = unbondingshr/bondedshr - amount = s.Amount.Mul(exRate) // bondedshr*unbondingshr/bondedshr = unbondingshr + // (tok/bondedshr)/(tok/unbondingshr) = unbondingshr/bondedshr + exRate := p.BondedShareExRate().Quo(p.UnbondingShareExRate()) + // bondedshr*unbondingshr/bondedshr = unbondingshr + amount = s.Amount.Mul(exRate) case sdk.Unbonding: amount = s.Amount case sdk.Unbonded: - exRate := p.UnbondedShareExRate().Quo(p.UnbondingShareExRate()) // (tok/unbondedshr)/(tok/unbondingshr) = unbondingshr/unbondedshr - amount = s.Amount.Mul(exRate) // unbondedshr*unbondingshr/unbondedshr = unbondingshr + // (tok/unbondedshr)/(tok/unbondingshr) = unbondingshr/unbondedshr + exRate := p.UnbondedShareExRate().Quo(p.UnbondingShareExRate()) + // unbondedshr*unbondingshr/unbondedshr = unbondingshr + amount = s.Amount.Mul(exRate) } + return NewUnbondingShares(amount) } -// equivalent amount of shares if the shares were bonded +// ToBonded the equivalent amount of pool shares if the shares were bonded. func (s PoolShares) ToBonded(p Pool) PoolShares { var amount sdk.Rat + switch s.Status { case sdk.Bonded: amount = s.Amount case sdk.Unbonding: - exRate := p.UnbondingShareExRate().Quo(p.BondedShareExRate()) // (tok/ubshr)/(tok/bshr) = bshr/ubshr - amount = s.Amount.Mul(exRate) // ubshr*bshr/ubshr = bshr + // (tok/ubshr)/(tok/bshr) = bshr/ubshr + exRate := p.UnbondingShareExRate().Quo(p.BondedShareExRate()) + // ubshr*bshr/ubshr = bshr + amount = s.Amount.Mul(exRate) case sdk.Unbonded: - exRate := p.UnbondedShareExRate().Quo(p.BondedShareExRate()) // (tok/ubshr)/(tok/bshr) = bshr/ubshr - amount = s.Amount.Mul(exRate) // ubshr*bshr/ubshr = bshr + // (tok/ubshr)/(tok/bshr) = bshr/ubshr + exRate := p.UnbondedShareExRate().Quo(p.BondedShareExRate()) + // ubshr*bshr/ubshr = bshr + amount = s.Amount.Mul(exRate) } + return NewUnbondedShares(amount) } -//_________________________________________________________________________________________________________ - -// TODO better tests -// get the equivalent amount of tokens contained by the shares +// Tokens returns the equivalent amount of tokens contained by the pool shares +// for a given pool. func (s PoolShares) Tokens(p Pool) sdk.Rat { switch s.Status { case sdk.Bonded: - return p.BondedShareExRate().Mul(s.Amount) // (tokens/shares) * shares + return p.BondedShareExRate().Mul(s.Amount) case sdk.Unbonding: return p.UnbondingShareExRate().Mul(s.Amount) case sdk.Unbonded: diff --git a/x/stake/types/shares_test.go b/x/stake/types/shares_test.go new file mode 100644 index 000000000..8a374606c --- /dev/null +++ b/x/stake/types/shares_test.go @@ -0,0 +1,35 @@ +package types + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestPoolSharesTokens(t *testing.T) { + pool := InitialPool() + pool.LooseTokens = 10 + + val := Validator{ + Owner: addr1, + PubKey: pk1, + PoolShares: NewBondedShares(sdk.NewRat(100)), + DelegatorShares: sdk.NewRat(100), + } + + pool.BondedTokens = val.PoolShares.Bonded().RoundInt64() + pool.BondedShares = val.PoolShares.Bonded() + + poolShares := NewBondedShares(sdk.NewRat(50)) + tokens := poolShares.Tokens(pool) + require.Equal(t, int64(50), tokens.RoundInt64()) + + poolShares = NewUnbondingShares(sdk.NewRat(50)) + tokens = poolShares.Tokens(pool) + require.Equal(t, int64(50), tokens.RoundInt64()) + + poolShares = NewUnbondedShares(sdk.NewRat(50)) + tokens = poolShares.Tokens(pool) + require.Equal(t, int64(50), tokens.RoundInt64()) +} diff --git a/x/stake/types/test_common.go b/x/stake/types/test_utils.go similarity index 84% rename from x/stake/types/test_common.go rename to x/stake/types/test_utils.go index 12f11f864..7912b7fa8 100644 --- a/x/stake/types/test_common.go +++ b/x/stake/types/test_utils.go @@ -11,7 +11,6 @@ import ( ) var ( - // dummy pubkeys/addresses pk1 = crypto.GenPrivKeyEd25519().PubKey() pk2 = crypto.GenPrivKeyEd25519().PubKey() pk3 = crypto.GenPrivKeyEd25519().PubKey() @@ -23,18 +22,20 @@ var ( emptyPubkey crypto.PubKey ) -//______________________________________________________________ - -// any operation that transforms staking state -// takes in RNG instance, pool, validator -// returns updated pool, updated validator, delta tokens, descriptive message +// Operation reflects any operation that transforms staking state. It takes in +// a RNG instance, pool, validator and returns an updated pool, updated +// validator, delta tokens, and descriptive message. type Operation func(r *rand.Rand, pool Pool, c Validator) (Pool, Validator, int64, string) -// operation: bond or unbond a validator depending on current status +// OpBondOrUnbond implements an operation that bonds or unbonds a validator +// depending on current status. // nolint: unparam func OpBondOrUnbond(r *rand.Rand, pool Pool, val Validator) (Pool, Validator, int64, string) { - var msg string - var newStatus sdk.BondStatus + var ( + msg string + newStatus sdk.BondStatus + ) + if val.Status() == sdk.Bonded { msg = fmt.Sprintf("sdk.Unbonded previously bonded validator %s (poolShares: %v, delShares: %v, DelegatorShareExRate: %v)", val.Owner, val.PoolShares.Bonded(), val.DelegatorShares, val.DelegatorShareExRate(pool)) @@ -45,21 +46,27 @@ func OpBondOrUnbond(r *rand.Rand, pool Pool, val Validator) (Pool, Validator, in val.Owner, val.PoolShares.Bonded(), val.DelegatorShares, val.DelegatorShareExRate(pool)) newStatus = sdk.Bonded } + val, pool = val.UpdateStatus(pool, newStatus) return pool, val, 0, msg } -// operation: add a random number of tokens to a validator +// OpAddTokens implements an operation that adds a random number of tokens to a +// validator. func OpAddTokens(r *rand.Rand, pool Pool, val Validator) (Pool, Validator, int64, string) { - tokens := int64(r.Int31n(1000)) msg := fmt.Sprintf("validator %s (status: %d, poolShares: %v, delShares: %v, DelegatorShareExRate: %v)", val.Owner, val.Status(), val.PoolShares.Bonded(), val.DelegatorShares, val.DelegatorShareExRate(pool)) + + tokens := int64(r.Int31n(1000)) val, pool, _ = val.AddTokensFromDel(pool, tokens) msg = fmt.Sprintf("Added %d tokens to %s", tokens, msg) - return pool, val, -1 * tokens, msg // tokens are removed so for accounting must be negative + + // Tokens are removed so for accounting must be negative + return pool, val, -1 * tokens, msg } -// operation: remove a random number of shares from a validator +// OpRemoveShares implements an operation that removes a random number of +// shares from a validator. func OpRemoveShares(r *rand.Rand, pool Pool, val Validator) (Pool, Validator, int64, string) { var shares sdk.Rat for { @@ -76,7 +83,7 @@ func OpRemoveShares(r *rand.Rand, pool Pool, val Validator) (Pool, Validator, in return pool, val, tokens, msg } -// pick a random staking operation +// RandomOperation returns a random staking operation. func RandomOperation(r *rand.Rand) Operation { operations := []Operation{ OpBondOrUnbond, @@ -86,10 +93,11 @@ func RandomOperation(r *rand.Rand) Operation { r.Shuffle(len(operations), func(i, j int) { operations[i], operations[j] = operations[j], operations[i] }) + return operations[0] } -// ensure invariants that should always be true are true +// AssertInvariants ensures invariants that should always be true are true. // nolint: unparam func AssertInvariants(t *testing.T, msg string, pOrig Pool, cOrig []Validator, pMod Pool, vMods []Validator, tokens int64) { @@ -105,29 +113,28 @@ func AssertInvariants(t *testing.T, msg string, pOrig.UnbondedTokens, pOrig.BondedTokens, pMod.UnbondedTokens, pMod.BondedTokens, tokens) - // nonnegative bonded shares + // Nonnegative bonded shares require.False(t, pMod.BondedShares.LT(sdk.ZeroRat()), "Negative bonded shares - msg: %v\npOrig: %v\npMod: %v\ntokens: %v\n", msg, pOrig, pMod, tokens) - // nonnegative unbonded shares + // Nonnegative unbonded shares require.False(t, pMod.UnbondedShares.LT(sdk.ZeroRat()), "Negative unbonded shares - msg: %v\npOrig: %v\npMod: %v\ntokens: %v\n", msg, pOrig, pMod, tokens) - // nonnegative bonded ex rate + // Nonnegative bonded ex rate require.False(t, pMod.BondedShareExRate().LT(sdk.ZeroRat()), "Applying operation \"%s\" resulted in negative BondedShareExRate: %d", msg, pMod.BondedShareExRate().RoundInt64()) - // nonnegative unbonded ex rate + // Nonnegative unbonded ex rate require.False(t, pMod.UnbondedShareExRate().LT(sdk.ZeroRat()), "Applying operation \"%s\" resulted in negative UnbondedShareExRate: %d", msg, pMod.UnbondedShareExRate().RoundInt64()) for _, vMod := range vMods { - - // nonnegative ex rate + // Nonnegative ex rate require.False(t, vMod.DelegatorShareExRate(pMod).LT(sdk.ZeroRat()), "Applying operation \"%s\" resulted in negative validator.DelegatorShareExRate(): %v (validator.Owner: %s)", msg, @@ -135,7 +142,7 @@ func AssertInvariants(t *testing.T, msg string, vMod.Owner, ) - // nonnegative poolShares + // Nonnegative poolShares require.False(t, vMod.PoolShares.Bonded().LT(sdk.ZeroRat()), "Applying operation \"%s\" resulted in negative validator.PoolShares.Bonded(): %v (validator.DelegatorShares: %v, validator.DelegatorShareExRate: %v, validator.Owner: %s)", msg, @@ -145,7 +152,7 @@ func AssertInvariants(t *testing.T, msg string, vMod.Owner, ) - // nonnegative delShares + // Nonnegative delShares require.False(t, vMod.DelegatorShares.LT(sdk.ZeroRat()), "Applying operation \"%s\" resulted in negative validator.DelegatorShares: %v (validator.PoolShares.Bonded(): %v, validator.DelegatorShareExRate: %v, validator.Owner: %s)", msg, @@ -154,27 +161,25 @@ func AssertInvariants(t *testing.T, msg string, vMod.DelegatorShareExRate(pMod), vMod.Owner, ) - } - } -//________________________________________________________________________________ -// TODO refactor this random setup +// TODO: refactor this random setup -// generate a random validator +// randomValidator generates a random validator. // nolint: unparam func randomValidator(r *rand.Rand, i int) Validator { - poolSharesAmt := sdk.NewRat(int64(r.Int31n(10000))) delShares := sdk.NewRat(int64(r.Int31n(10000))) var pShares PoolShares + if r.Float64() < float64(0.5) { pShares = NewBondedShares(poolSharesAmt) } else { pShares = NewUnbondedShares(poolSharesAmt) } + return Validator{ Owner: addr1, PubKey: pk1, @@ -183,7 +188,7 @@ func randomValidator(r *rand.Rand, i int) Validator { } } -// generate a random staking state +// RandomSetup generates a random staking state. func RandomSetup(r *rand.Rand, numValidators int) (Pool, []Validator) { pool := InitialPool() pool.LooseTokens = 100000 @@ -191,6 +196,7 @@ func RandomSetup(r *rand.Rand, numValidators int) (Pool, []Validator) { validators := make([]Validator, numValidators) for i := 0; i < numValidators; i++ { validator := randomValidator(r, i) + if validator.Status() == sdk.Bonded { pool.BondedShares = pool.BondedShares.Add(validator.PoolShares.Bonded()) pool.BondedTokens += validator.PoolShares.Bonded().RoundInt64() @@ -198,7 +204,9 @@ func RandomSetup(r *rand.Rand, numValidators int) (Pool, []Validator) { pool.UnbondedShares = pool.UnbondedShares.Add(validator.PoolShares.Unbonded()) pool.UnbondedTokens += validator.PoolShares.Unbonded().RoundInt64() } + validators[i] = validator } + return pool, validators } diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index c2c19439b..c55ae725a 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -4,13 +4,14 @@ import ( "bytes" "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" tmtypes "github.com/tendermint/tendermint/types" - - sdk "github.com/cosmos/cosmos-sdk/types" ) +const doNotModifyDescVal = "[do-not-modify]" + // Validator defines the total amount of bond shares and their exchange rate to // coins. Accumulation of interest is modelled as an in increase in the // exchange rate, and slashing as a decrease. When coins are delegated to this @@ -60,15 +61,13 @@ func NewValidator(owner sdk.Address, pubKey crypto.PubKey, description Descripti } } -// only the vitals - does not check bond height of IntraTxCounter +// Equal returns a boolean reflecting if two given validators are identical. func (v Validator) Equal(c2 Validator) bool { return v.PubKey.Equals(c2.PubKey) && bytes.Equal(v.Owner, c2.Owner) && v.PoolShares.Equal(c2.PoolShares) && v.DelegatorShares.Equal(c2.DelegatorShares) && v.Description == c2.Description && - //v.BondHeight == c2.BondHeight && - //v.BondIntraTxCounter == c2.BondIntraTxCounter && // counter is always changing v.ProposerRewardPool.IsEqual(c2.ProposerRewardPool) && v.Commission.Equal(c2.Commission) && v.CommissionMax.Equal(c2.CommissionMax) && @@ -85,6 +84,7 @@ type Description struct { Details string `json:"details"` // optional details } +// NewDescription returns a new Description with the provided values. func NewDescription(moniker, identity, website, details string) Description { return Description{ Moniker: moniker, @@ -94,20 +94,22 @@ func NewDescription(moniker, identity, website, details string) Description { } } -// update the description based on input +// UpdateDescription updates the fields of a given description. An error is +// returned if the resulting description contains an invalid length. func (d Description) UpdateDescription(d2 Description) (Description, sdk.Error) { - if d.Moniker == "[do-not-modify]" { + if d.Moniker == doNotModifyDescVal { d2.Moniker = d.Moniker } - if d.Identity == "[do-not-modify]" { + if d.Identity == doNotModifyDescVal { d2.Identity = d.Identity } - if d.Website == "[do-not-modify]" { + if d.Website == doNotModifyDescVal { d2.Website = d.Website } - if d.Details == "[do-not-modify]" { + if d.Details == doNotModifyDescVal { d2.Details = d.Details } + return Description{ Moniker: d2.Moniker, Identity: d2.Identity, @@ -116,7 +118,7 @@ func (d Description) UpdateDescription(d2 Description) (Description, sdk.Error) }.EnsureLength() } -// ensure the length of the description +// EnsureLength ensures the length of a validator's description. func (d Description) EnsureLength() (Description, sdk.Error) { if len(d.Moniker) > 70 { return d, ErrDescriptionLength(DefaultCodespace, "moniker", len(d.Moniker), 70) @@ -130,10 +132,11 @@ func (d Description) EnsureLength() (Description, sdk.Error) { if len(d.Details) > 280 { return d, ErrDescriptionLength(DefaultCodespace, "details", len(d.Details), 280) } + return d, nil } -// abci validator from stake validator type +// ABCIValidator returns an abci.Validator from a staked validator type. func (v Validator) ABCIValidator() abci.Validator { return abci.Validator{ PubKey: tmtypes.TM2PB.PubKey(v.PubKey), @@ -141,8 +144,8 @@ func (v Validator) ABCIValidator() abci.Validator { } } -// abci validator from stake validator type -// with zero power used for validator updates +// ABCIValidatorZero returns an abci.Validator from a staked validator type +// with with zero power used for validator updates. func (v Validator) ABCIValidatorZero() abci.Validator { return abci.Validator{ PubKey: tmtypes.TM2PB.PubKey(v.PubKey), @@ -150,12 +153,13 @@ func (v Validator) ABCIValidatorZero() abci.Validator { } } -// abci validator from stake validator type +// Status returns the validator's bond status inferred from the pool shares. func (v Validator) Status() sdk.BondStatus { return v.PoolShares.Status } -// update the location of the shares within a validator if its bond status has changed +// UpdateStatus updates the location of the shares within a validator if it's +// bond status has changed. func (v Validator) UpdateStatus(pool Pool, NewStatus sdk.BondStatus) (Validator, Pool) { var tokens int64 @@ -173,7 +177,8 @@ func (v Validator) UpdateStatus(pool Pool, NewStatus sdk.BondStatus) (Validator, pool, tokens = pool.removeSharesUnbonding(v.PoolShares.Amount) case sdk.Bonded: - if NewStatus == sdk.Bonded { // return if nothing needs switching + if NewStatus == sdk.Bonded { + // Return if nothing needs switching return v, pool } pool, tokens = pool.removeSharesBonded(v.PoolShares.Amount) @@ -187,14 +192,16 @@ func (v Validator) UpdateStatus(pool Pool, NewStatus sdk.BondStatus) (Validator, case sdk.Bonded: pool, v.PoolShares = pool.addTokensBonded(tokens) } + return v, pool } -// Remove pool shares -// Returns corresponding tokens, which could be burned (e.g. when slashing -// a validator) or redistributed elsewhere +// RemovePoolShares removes pool shares from a validator. It returns +// corresponding tokens, which could be burned (e.g. when slashing a validator) +// or redistributed elsewhere. func (v Validator) RemovePoolShares(pool Pool, poolShares sdk.Rat) (Validator, Pool, int64) { var tokens int64 + switch v.Status() { case sdk.Unbonded: pool, tokens = pool.removeSharesUnbonded(poolShares) @@ -203,29 +210,33 @@ func (v Validator) RemovePoolShares(pool Pool, poolShares sdk.Rat) (Validator, P case sdk.Bonded: pool, tokens = pool.removeSharesBonded(poolShares) } + v.PoolShares.Amount = v.PoolShares.Amount.Sub(poolShares) return v, pool, tokens } -// TODO remove should only be tokens -// get the power or potential power for a validator -// if bonded, the power is the BondedShares -// if not bonded, the power is the amount of bonded shares which the -// the validator would have it was bonded +// EquivalentBondedShares ... +// +// TODO: Remove should only be tokens get the power or potential power for a +// validator if bonded, the power is the BondedShares if not bonded, the power +// is the amount of bonded shares which the the validator would have it was +// bonded. func (v Validator) EquivalentBondedShares(pool Pool) (eqBondedShares sdk.Rat) { return v.PoolShares.ToBonded(pool).Amount } //_________________________________________________________________________________________________________ -// add tokens to a validator -func (v Validator) AddTokensFromDel(pool Pool, - amount int64) (validator2 Validator, p2 Pool, issuedDelegatorShares sdk.Rat) { +// AddTokensFromDel adds tokens to a validator +func (v Validator) AddTokensFromDel(pool Pool, amount int64) (Validator, Pool, sdk.Rat) { + var ( + poolShares PoolShares + equivalentBondedShares sdk.Rat + ) - exRate := v.DelegatorShareExRate(pool) // bshr/delshr + // bondedShare/delegatedShare + exRate := v.DelegatorShareExRate(pool) - var poolShares PoolShares - var equivalentBondedShares sdk.Rat switch v.Status() { case sdk.Unbonded: pool, poolShares = pool.addTokensUnbonded(amount) @@ -237,21 +248,24 @@ func (v Validator) AddTokensFromDel(pool Pool, v.PoolShares.Amount = v.PoolShares.Amount.Add(poolShares.Amount) equivalentBondedShares = poolShares.ToBonded(pool).Amount - issuedDelegatorShares = equivalentBondedShares.Quo(exRate) // bshr/(bshr/delshr) = delshr + // bondedShare/(bondedShare/delegatedShare) = delegatedShare + issuedDelegatorShares := equivalentBondedShares.Quo(exRate) v.DelegatorShares = v.DelegatorShares.Add(issuedDelegatorShares) return v, pool, issuedDelegatorShares } -// remove delegator shares from a validator -// NOTE this function assumes the shares have already been updated for the validator status -func (v Validator) RemoveDelShares(pool Pool, - delShares sdk.Rat) (validator2 Validator, p2 Pool, createdCoins int64) { - +// RemoveDelShares removes delegator shares from a validator. +// +// NOTE: This function assumes the shares have already been updated for the +// validator status. +func (v Validator) RemoveDelShares(pool Pool, delShares sdk.Rat) (Validator, Pool, int64) { amount := v.DelegatorShareExRate(pool).Mul(delShares) eqBondedSharesToRemove := NewBondedShares(amount) v.DelegatorShares = v.DelegatorShares.Sub(delShares) + var createdCoins int64 + switch v.Status() { case sdk.Unbonded: unbondedShares := eqBondedSharesToRemove.ToUnbonded(pool).Amount @@ -265,15 +279,17 @@ func (v Validator) RemoveDelShares(pool Pool, pool, createdCoins = pool.removeSharesBonded(eqBondedSharesToRemove.Amount) v.PoolShares.Amount = v.PoolShares.Amount.Sub(eqBondedSharesToRemove.Amount) } + return v, pool, createdCoins } -// get the exchange rate of tokens over delegator shares +// DelegatorShareExRate gets the exchange rate of tokens over delegator shares. // UNITS: eq-val-bonded-shares/delegator-shares func (v Validator) DelegatorShareExRate(pool Pool) sdk.Rat { if v.DelegatorShares.IsZero() { return sdk.OneRat() } + eqBondedShares := v.PoolShares.ToBonded(pool).Amount return eqBondedShares.Quo(v.DelegatorShares) } @@ -293,16 +309,20 @@ func (v Validator) GetPower() sdk.Rat { return v.PoolShares.Bonded() } func (v Validator) GetDelegatorShares() sdk.Rat { return v.DelegatorShares } func (v Validator) GetBondHeight() int64 { return v.BondHeight } -//Human Friendly pretty printer +// HumanReadableString returns a human readable string representation of a +// validator. An error is returned if the owner or the owner's public key +// cannot be converted to Bech32 format. func (v Validator) HumanReadableString() (string, error) { bechOwner, err := sdk.Bech32ifyAcc(v.Owner) if err != nil { return "", err } + bechVal, err := sdk.Bech32ifyValPub(v.PubKey) if err != nil { return "", err } + resp := "Validator \n" resp += fmt.Sprintf("Owner: %s\n", bechOwner) resp += fmt.Sprintf("Validator: %s\n", bechVal) diff --git a/x/stake/types/validator_test.go b/x/stake/types/validator_test.go index 4fcfa6e17..f978a6d6e 100644 --- a/x/stake/types/validator_test.go +++ b/x/stake/types/validator_test.go @@ -5,12 +5,89 @@ import ( "math/rand" "testing" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - - sdk "github.com/cosmos/cosmos-sdk/types" + tmtypes "github.com/tendermint/tendermint/types" ) +func TestValidatorEqual(t *testing.T) { + val1 := NewValidator(addr1, pk1, Description{}) + val2 := NewValidator(addr1, pk1, Description{}) + + ok := val1.Equal(val2) + require.True(t, ok) + + val2 = NewValidator(addr2, pk2, Description{}) + + ok = val1.Equal(val2) + require.False(t, ok) +} + +func TestUpdateDescription(t *testing.T) { + d1 := Description{ + Moniker: doNotModifyDescVal, + Identity: doNotModifyDescVal, + Website: doNotModifyDescVal, + Details: doNotModifyDescVal, + } + d2 := Description{ + Website: "https://validator.cosmos", + Details: "Test validator", + } + + d, err := d1.UpdateDescription(d2) + require.Nil(t, err) + require.Equal(t, d, d1) +} + +func TestABCIValidator(t *testing.T) { + val := NewValidator(addr1, pk1, Description{}) + + abciVal := val.ABCIValidator() + require.Equal(t, tmtypes.TM2PB.PubKey(val.PubKey), abciVal.PubKey) + require.Equal(t, val.PoolShares.Bonded().RoundInt64(), abciVal.Power) +} + +func TestABCIValidatorZero(t *testing.T) { + val := NewValidator(addr1, pk1, Description{}) + + abciVal := val.ABCIValidatorZero() + require.Equal(t, tmtypes.TM2PB.PubKey(val.PubKey), abciVal.PubKey) + require.Equal(t, int64(0), abciVal.Power) +} + +func TestRemovePoolShares(t *testing.T) { + pool := InitialPool() + pool.LooseTokens = 10 + + val := Validator{ + Owner: addr1, + PubKey: pk1, + PoolShares: NewBondedShares(sdk.NewRat(100)), + DelegatorShares: sdk.NewRat(100), + } + + pool.BondedTokens = val.PoolShares.Bonded().RoundInt64() + pool.BondedShares = val.PoolShares.Bonded() + + val, pool = val.UpdateStatus(pool, sdk.Bonded) + val, pool, tk := val.RemovePoolShares(pool, sdk.NewRat(10)) + require.Equal(t, int64(90), val.PoolShares.Amount.RoundInt64()) + require.Equal(t, int64(90), pool.BondedTokens) + require.Equal(t, int64(90), pool.BondedShares.RoundInt64()) + require.Equal(t, int64(20), pool.LooseTokens) + require.Equal(t, int64(10), tk) + + val, pool = val.UpdateStatus(pool, sdk.Unbonded) + val, pool, tk = val.RemovePoolShares(pool, sdk.NewRat(10)) + require.Equal(t, int64(80), val.PoolShares.Amount.RoundInt64()) + require.Equal(t, int64(0), pool.BondedTokens) + require.Equal(t, int64(0), pool.BondedShares.RoundInt64()) + require.Equal(t, int64(30), pool.LooseTokens) + require.Equal(t, int64(10), tk) +} + func TestAddTokensValidatorBonded(t *testing.T) { pool := InitialPool() pool.LooseTokens = 10 @@ -230,3 +307,13 @@ func TestMultiValidatorIntegrationInvariants(t *testing.T) { } } } + +func TestHumanReadableString(t *testing.T) { + val := NewValidator(addr1, pk1, Description{}) + + // NOTE: Being that the validator's keypair is random, we cannot test the + // actual contents of the string. + valStr, err := val.HumanReadableString() + require.Nil(t, err) + require.NotEmpty(t, valStr) +} From c5710ceadc2dce772402c3fc72b8f55a69df3c36 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 4 Jul 2018 00:24:29 -0400 Subject: [PATCH 19/53] add codeowners file --- .github/CODEOWNERS | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..dcdf7080b --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,7 @@ +# CODEOWNERS: https://help.github.com/articles/about-codeowners/ + +# Primary repo maintainers +* @ebuchman @rigelrozanski @cwgoes + +# Precious documentation +/docs/ @zramsay @jolesbi From 04921b9ebd640b3b5f3c9d6dabcc73d438976c88 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 4 Jul 2018 00:29:02 -0400 Subject: [PATCH 20/53] ubd and red more limited values --- x/stake/client/cli/query.go | 24 ++++------ x/stake/client/rest/query.go | 16 +------ x/stake/keeper/delegation.go | 60 ++++++++++++------------ x/stake/types/delegation.go | 90 +++++++++++++++++++++++++++++++++++- 4 files changed, 130 insertions(+), 60 deletions(-) diff --git a/x/stake/client/cli/query.go b/x/stake/client/cli/query.go index e66a3bb4d..d50b0d14d 100644 --- a/x/stake/client/cli/query.go +++ b/x/stake/client/cli/query.go @@ -75,9 +75,9 @@ func GetCmdQueryValidators(storeName string, cdc *wire.Codec) *cobra.Command { // parse out the validators var validators []stake.Validator - for _, KV := range resKVs { + for _, kv := range resKVs { var validator stake.Validator - cdc.MustUnmarshalBinary(KV.Value, &validator) + cdc.MustUnmarshalBinary(kv.Value, &validator) validators = append(validators, validator) } @@ -178,8 +178,8 @@ func GetCmdQueryDelegations(storeName string, cdc *wire.Codec) *cobra.Command { // parse out the validators var delegations []stake.Delegation - for _, KV := range resKVs { - delegation := types.UnmarshalDelegation(cdc, KV.Key, KV.Value) + for _, kv := range resKVs { + delegation := types.UnmarshalDelegation(cdc, kv.Key, kv.Value) delegations = append(delegations, delegation) } @@ -221,7 +221,7 @@ func GetCmdQueryUnbondingDelegation(storeName string, cdc *wire.Codec) *cobra.Co } // parse out the unbonding delegation - ubd := new(stake.UnbondingDelegation) + ubd := types.UnmarshalUBD(cdc, key, res) switch viper.Get(cli.OutputFlag) { case "text": @@ -231,7 +231,6 @@ func GetCmdQueryUnbondingDelegation(storeName string, cdc *wire.Codec) *cobra.Co } fmt.Println(resp) case "json": - cdc.MustUnmarshalBinary(res, ubd) output, err := wire.MarshalJSONIndent(cdc, ubd) if err != nil { return err @@ -269,9 +268,8 @@ func GetCmdQueryUnbondingDelegations(storeName string, cdc *wire.Codec) *cobra.C // parse out the validators var ubds []stake.UnbondingDelegation - for _, KV := range resKVs { - var ubd stake.UnbondingDelegation - cdc.MustUnmarshalBinary(KV.Value, &ubd) + for _, kv := range resKVs { + ubd := types.UnmarshalUBD(cdc, kv.Key, kv.Value) ubds = append(ubds, ubd) } @@ -316,7 +314,7 @@ func GetCmdQueryRedelegation(storeName string, cdc *wire.Codec) *cobra.Command { } // parse out the unbonding delegation - red := new(stake.Redelegation) + red := types.UnmarshalRED(cdc, key, res) switch viper.Get(cli.OutputFlag) { case "text": @@ -326,7 +324,6 @@ func GetCmdQueryRedelegation(storeName string, cdc *wire.Codec) *cobra.Command { } fmt.Println(resp) case "json": - cdc.MustUnmarshalBinary(res, red) output, err := wire.MarshalJSONIndent(cdc, red) if err != nil { return err @@ -364,9 +361,8 @@ func GetCmdQueryRedelegations(storeName string, cdc *wire.Codec) *cobra.Command // parse out the validators var reds []stake.Redelegation - for _, KV := range resKVs { - var red stake.Redelegation - cdc.MustUnmarshalBinary(KV.Value, &red) + for _, kv := range resKVs { + red := types.UnmarshalRED(cdc, kv.Key, kv.Value) reds = append(reds, red) } diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index b19cea72b..457806de0 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -128,13 +128,7 @@ func ubdHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerFunc { return } - var ubd stake.UnbondingDelegation - err = cdc.UnmarshalBinary(res, &ubd) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("couldn't decode unbonding-delegation. Error: %s", err.Error()))) - return - } + ubd := types.UnmarshalUBD(cdc, key, res) output, err := cdc.MarshalJSON(ubd) if err != nil { @@ -193,13 +187,7 @@ func redHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerFunc { return } - var red stake.Redelegation - err = cdc.UnmarshalBinary(res, &red) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("couldn't decode redelegation. Error: %s", err.Error()))) - return - } + red := types.UnmarshalRED(cdc, key, res) output, err := cdc.MarshalJSON(red) if err != nil { diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 9c56b8512..3d949a9a0 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -82,49 +82,48 @@ func (k Keeper) GetUnbondingDelegation(ctx sdk.Context, DelegatorAddr, ValidatorAddr sdk.Address) (ubd types.UnbondingDelegation, found bool) { store := ctx.KVStore(k.storeKey) - ubdKey := GetUBDKey(DelegatorAddr, ValidatorAddr) - bz := store.Get(ubdKey) - if bz == nil { + key := GetUBDKey(DelegatorAddr, ValidatorAddr) + value := store.Get(key) + if value == nil { return ubd, false } - k.cdc.MustUnmarshalBinary(bz, &ubd) + ubd = types.UnmarshalUBD(k.cdc, key, value) return ubd, true } // load all unbonding delegations from a particular validator -func (k Keeper) GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr sdk.Address) (unbondingDelegations []types.UnbondingDelegation) { +func (k Keeper) GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr sdk.Address) (ubds []types.UnbondingDelegation) { store := ctx.KVStore(k.storeKey) iterator := sdk.KVStorePrefixIterator(store, GetUBDsByValIndexKey(valAddr)) for { if !iterator.Valid() { break } - unbondingKey := GetUBDKeyFromValIndexKey(iterator.Key()) - unbondingBytes := store.Get(unbondingKey) - var unbondingDelegation types.UnbondingDelegation - k.cdc.MustUnmarshalBinary(unbondingBytes, &unbondingDelegation) - unbondingDelegations = append(unbondingDelegations, unbondingDelegation) + key := GetUBDKeyFromValIndexKey(iterator.Key()) + value := store.Get(key) + ubd := types.UnmarshalUBD(k.cdc, key, value) + ubds = append(ubds, ubd) iterator.Next() } iterator.Close() - return unbondingDelegations + return ubds } // set the unbonding delegation and associated index func (k Keeper) SetUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDelegation) { store := ctx.KVStore(k.storeKey) - bz := k.cdc.MustMarshalBinary(ubd) - ubdKey := GetUBDKey(ubd.DelegatorAddr, ubd.ValidatorAddr) - store.Set(ubdKey, bz) - store.Set(GetUBDByValIndexKey(ubd.DelegatorAddr, ubd.ValidatorAddr), []byte{}) + bz := types.MarshalUBD(k.cdc, ubd) + key := GetUBDKey(ubd.DelegatorAddr, ubd.ValidatorAddr) + store.Set(key, bz) + store.Set(GetUBDByValIndexKey(ubd.DelegatorAddr, ubd.ValidatorAddr), []byte{}) // index, store empty bytes } // remove the unbonding delegation object and associated index func (k Keeper) RemoveUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDelegation) { store := ctx.KVStore(k.storeKey) - ubdKey := GetUBDKey(ubd.DelegatorAddr, ubd.ValidatorAddr) - store.Delete(ubdKey) + key := GetUBDKey(ubd.DelegatorAddr, ubd.ValidatorAddr) + store.Delete(key) store.Delete(GetUBDByValIndexKey(ubd.DelegatorAddr, ubd.ValidatorAddr)) } @@ -135,33 +134,32 @@ func (k Keeper) GetRedelegation(ctx sdk.Context, DelegatorAddr, ValidatorSrcAddr, ValidatorDstAddr sdk.Address) (red types.Redelegation, found bool) { store := ctx.KVStore(k.storeKey) - redKey := GetREDKey(DelegatorAddr, ValidatorSrcAddr, ValidatorDstAddr) - bz := store.Get(redKey) - if bz == nil { + key := GetREDKey(DelegatorAddr, ValidatorSrcAddr, ValidatorDstAddr) + value := store.Get(key) + if value == nil { return red, false } - k.cdc.MustUnmarshalBinary(bz, &red) + red = types.UnmarshalRED(k.cdc, key, value) return red, true } // load all redelegations from a particular validator -func (k Keeper) GetRedelegationsFromValidator(ctx sdk.Context, valAddr sdk.Address) (redelegations []types.Redelegation) { +func (k Keeper) GetRedelegationsFromValidator(ctx sdk.Context, valAddr sdk.Address) (reds []types.Redelegation) { store := ctx.KVStore(k.storeKey) iterator := sdk.KVStorePrefixIterator(store, GetREDsFromValSrcIndexKey(valAddr)) for { if !iterator.Valid() { break } - redelegationKey := GetREDKeyFromValSrcIndexKey(iterator.Key()) - redelegationBytes := store.Get(redelegationKey) - var redelegation types.Redelegation - k.cdc.MustUnmarshalBinary(redelegationBytes, &redelegation) - redelegations = append(redelegations, redelegation) + key := GetREDKeyFromValSrcIndexKey(iterator.Key()) + value := store.Get(key) + red := types.UnmarshalRED(k.cdc, key, value) + reds = append(reds, red) iterator.Next() } iterator.Close() - return redelegations + return reds } // has a redelegation @@ -184,9 +182,9 @@ func (k Keeper) HasReceivingRedelegation(ctx sdk.Context, // set a redelegation and associated index func (k Keeper) SetRedelegation(ctx sdk.Context, red types.Redelegation) { store := ctx.KVStore(k.storeKey) - bz := k.cdc.MustMarshalBinary(red) - redKey := GetREDKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr) - store.Set(redKey, bz) + bz := types.MarshalRED(k.cdc, red) + key := GetREDKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr) + store.Set(key, bz) store.Set(GetREDByValSrcIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr), []byte{}) store.Set(GetREDByValDstIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr), []byte{}) } diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index b6d35fb56..0a3c9cf4f 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -39,7 +39,7 @@ func UnmarshalDelegation(cdc *wire.Codec, key, value []byte) Delegation { addrs := key[1:] // remove prefix bytes if len(addrs) != 40 { - panic("key length not even") + panic("unexpected key length") } delAddr := sdk.Address(addrs[:20]) valAddr := sdk.Address(addrs[20:]) @@ -100,6 +100,46 @@ type UnbondingDelegation struct { Balance sdk.Coin `json:"balance"` // atoms to receive at completion } +type ubdValue struct { + CreationHeight int64 + MinTime int64 + InitialBalance sdk.Coin + Balance sdk.Coin +} + +// return the unbonding delegation without fields contained within the key for the store +func MarshalUBD(cdc *wire.Codec, ubd UnbondingDelegation) []byte { + val := ubdValue{ + ubd.CreationHeight, + ubd.MinTime, + ubd.InitialBalance, + ubd.Balance, + } + return cdc.MustMarshalBinary(val) +} + +// return the unbonding delegation without fields contained within the key for the store +func UnmarshalUBD(cdc *wire.Codec, key, value []byte) UnbondingDelegation { + var storeValue ubdValue + cdc.MustUnmarshalBinary(value, &storeValue) + + addrs := key[1:] // remove prefix bytes + if len(addrs) != 40 { + panic("unexpected key length") + } + delAddr := sdk.Address(addrs[:20]) + valAddr := sdk.Address(addrs[20:]) + + return UnbondingDelegation{ + DelegatorAddr: delAddr, + ValidatorAddr: valAddr, + CreationHeight: storeValue.CreationHeight, + MinTime: storeValue.MinTime, + InitialBalance: storeValue.InitialBalance, + Balance: storeValue.Balance, + } +} + // nolint func (d UnbondingDelegation) Equal(d2 UnbondingDelegation) bool { bz1 := MsgCdc.MustMarshalBinary(&d) @@ -143,6 +183,54 @@ type Redelegation struct { SharesDst sdk.Rat `json:"shares_dst"` // amount of destination shares redelegating } +type redValue struct { + CreationHeight int64 + MinTime int64 + InitialBalance sdk.Coin + Balance sdk.Coin + SharesSrc sdk.Rat + SharesDst sdk.Rat +} + +// return the unbonding delegation without fields contained within the key for the store +func MarshalRED(cdc *wire.Codec, red Redelegation) []byte { + val := redValue{ + red.CreationHeight, + red.MinTime, + red.InitialBalance, + red.Balance, + red.SharesSrc, + red.SharesDst, + } + return cdc.MustMarshalBinary(val) +} + +// return the unbonding delegation without fields contained within the key for the store +func UnmarshalRED(cdc *wire.Codec, key, value []byte) Redelegation { + var storeValue redValue + cdc.MustUnmarshalBinary(value, &storeValue) + + addrs := key[1:] // remove prefix bytes + if len(addrs) != 60 { + panic("unexpected key length") + } + delAddr := sdk.Address(addrs[:20]) + valSrcAddr := sdk.Address(addrs[20:40]) + valDstAddr := sdk.Address(addrs[40:60]) + + return Redelegation{ + DelegatorAddr: delAddr, + ValidatorSrcAddr: valSrcAddr, + ValidatorDstAddr: valDstAddr, + CreationHeight: storeValue.CreationHeight, + MinTime: storeValue.MinTime, + InitialBalance: storeValue.InitialBalance, + Balance: storeValue.Balance, + SharesSrc: storeValue.SharesSrc, + SharesDst: storeValue.SharesDst, + } +} + // nolint func (d Redelegation) Equal(d2 Redelegation) bool { bz1 := MsgCdc.MustMarshalBinary(&d) From a2f7b582df0789a0a0993be32afb5df4e047a232 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 4 Jul 2018 01:32:49 -0400 Subject: [PATCH 21/53] validators smaller values stored --- x/slashing/handler_test.go | 3 +- x/slashing/test_common.go | 10 +++--- x/stake/client/cli/query.go | 8 ++--- x/stake/client/rest/query.go | 15 ++++----- x/stake/keeper/sdk_types.go | 5 ++- x/stake/keeper/validator.go | 30 +++++++---------- x/stake/types/delegation.go | 6 ++-- x/stake/types/validator.go | 65 ++++++++++++++++++++++++++++++++++++ 8 files changed, 100 insertions(+), 42 deletions(-) diff --git a/x/slashing/handler_test.go b/x/slashing/handler_test.go index c2c5d9166..d5a6b15db 100644 --- a/x/slashing/handler_test.go +++ b/x/slashing/handler_test.go @@ -15,7 +15,8 @@ func TestCannotUnrevokeUnlessRevoked(t *testing.T) { slh := NewHandler(keeper) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) - got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) + msg := newTestMsgCreateValidator(addr, val, amt) + got := stake.NewHandler(sk)(ctx, msg) require.True(t, got.IsOK()) stake.EndBlocker(ctx, sk) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) diff --git a/x/slashing/test_common.go b/x/slashing/test_common.go index edf119bc7..77b553317 100644 --- a/x/slashing/test_common.go +++ b/x/slashing/test_common.go @@ -23,16 +23,16 @@ import ( // TODO remove dependencies on staking (should only refer to validator set type from sdk) var ( - addrs = []sdk.Address{ - testAddr("A58856F0FD53BF058B4909A21AEC019107BA6160"), - testAddr("A58856F0FD53BF058B4909A21AEC019107BA6161"), - testAddr("A58856F0FD53BF058B4909A21AEC019107BA6162"), - } pks = []crypto.PubKey{ newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB50"), newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB51"), newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB52"), } + addrs = []sdk.Address{ + pks[0].Address(), + pks[1].Address(), + pks[2].Address(), + } initCoins sdk.Int = sdk.NewInt(200) ) diff --git a/x/stake/client/cli/query.go b/x/stake/client/cli/query.go index d50b0d14d..ee495e96e 100644 --- a/x/stake/client/cli/query.go +++ b/x/stake/client/cli/query.go @@ -32,8 +32,8 @@ func GetCmdQueryValidator(storeName string, cdc *wire.Codec) *cobra.Command { if err != nil { return err } - validator := new(stake.Validator) - cdc.MustUnmarshalBinary(res, validator) + + validator := types.UnmarshalValidator(cdc, addr, res) switch viper.Get(cli.OutputFlag) { case "text": @@ -76,8 +76,8 @@ func GetCmdQueryValidators(storeName string, cdc *wire.Codec) *cobra.Command { // parse out the validators var validators []stake.Validator for _, kv := range resKVs { - var validator stake.Validator - cdc.MustUnmarshalBinary(kv.Value, &validator) + addr := kv.Key[1:] + validator := types.UnmarshalValidator(cdc, addr, kv.Value) validators = append(validators, validator) } diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index 457806de0..49051c73e 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -275,15 +275,14 @@ func validatorsHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerF // parse out the validators validators := make([]StakeValidatorOutput, len(kvs)) for i, kv := range kvs { - var validator stake.Validator - var bech32Validator StakeValidatorOutput - err = cdc.UnmarshalBinary(kv.Value, &validator) - if err == nil { - bech32Validator, err = bech32StakeValidatorOutput(validator) - } + + addr := kv.Key[1:] + validator := types.UnmarshalValidator(cdc, addr, kv.Value) + + bech32Validator, err := bech32StakeValidatorOutput(validator) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("couldn't decode validator. Error: %s", err.Error()))) + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) return } validators[i] = bech32Validator diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index 9e45982b4..0fe465892 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -16,9 +16,8 @@ func (k Keeper) IterateValidators(ctx sdk.Context, fn func(index int64, validato iterator := sdk.KVStorePrefixIterator(store, ValidatorsKey) i := int64(0) for ; iterator.Valid(); iterator.Next() { - bz := iterator.Value() - var validator types.Validator - k.cdc.MustUnmarshalBinary(bz, &validator) + addr := iterator.Key()[1:] + validator := types.UnmarshalValidator(k.cdc, addr, iterator.Value()) stop := fn(i, validator) // XXX is this safe will the validator unexposed fields be able to get written to? if stop { break diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index c2711788b..ad70958a3 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -14,11 +14,12 @@ import ( // get a single validator func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.Address) (validator types.Validator, found bool) { store := ctx.KVStore(k.storeKey) - b := store.Get(GetValidatorKey(addr)) - if b == nil { + value := store.Get(GetValidatorKey(addr)) + if value == nil { return validator, false } - k.cdc.MustUnmarshalBinary(b, &validator) + fmt.Printf("debug addr: %v\n", addr) + validator = types.UnmarshalValidator(k.cdc, addr, value) return validator, true } @@ -35,15 +36,13 @@ func (k Keeper) GetValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) (val // set the main record holding validator details func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) - // set main store - bz := k.cdc.MustMarshalBinary(validator) + bz := types.MarshalValidator(k.cdc, validator) store.Set(GetValidatorKey(validator.Owner), bz) } // validator index func (k Keeper) SetValidatorByPubKeyIndex(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) - // set pointer by pubkey store.Set(GetValidatorByPubKeyIndexKey(validator.PubKey), validator.Owner) } @@ -75,9 +74,8 @@ func (k Keeper) GetAllValidators(ctx sdk.Context) (validators []types.Validator) if !iterator.Valid() { break } - bz := iterator.Value() - var validator types.Validator - k.cdc.MustUnmarshalBinary(bz, &validator) + addr := iterator.Key()[1:] + validator := types.UnmarshalValidator(k.cdc, addr, iterator.Value()) validators = append(validators, validator) iterator.Next() } @@ -96,9 +94,8 @@ func (k Keeper) GetValidators(ctx sdk.Context, maxRetrieve int16) (validators [] if !iterator.Valid() || i > int(maxRetrieve-1) { break } - bz := iterator.Value() - var validator types.Validator - k.cdc.MustUnmarshalBinary(bz, &validator) + addr := iterator.Key()[1:] + validator := types.UnmarshalValidator(k.cdc, addr, iterator.Value()) validators[i] = validator iterator.Next() } @@ -205,8 +202,7 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type // always update the main list ordered by owner address before exiting defer func() { - bz := k.cdc.MustMarshalBinary(validator) - store.Set(GetValidatorKey(ownerAddr), bz) + k.SetValidator(ctx, validator) }() // retrieve the old validator record @@ -441,8 +437,7 @@ func (k Keeper) unbondValidator(ctx sdk.Context, validator types.Validator) type k.SetPool(ctx, pool) // save the now unbonded validator record - bzVal := k.cdc.MustMarshalBinary(validator) - store.Set(GetValidatorKey(validator.Owner), bzVal) + k.SetValidator(ctx, validator) // add to accumulated changes for tendermint bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidatorZero()) @@ -469,8 +464,7 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. k.SetPool(ctx, pool) // save the now bonded validator record to the three referenced stores - bzVal := k.cdc.MustMarshalBinary(validator) - store.Set(GetValidatorKey(validator.Owner), bzVal) + k.SetValidator(ctx, validator) store.Set(GetValidatorsBondedIndexKey(validator.Owner), []byte{}) // add to accumulated changes for tendermint diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index 0a3c9cf4f..34aa32377 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -118,7 +118,7 @@ func MarshalUBD(cdc *wire.Codec, ubd UnbondingDelegation) []byte { return cdc.MustMarshalBinary(val) } -// return the unbonding delegation without fields contained within the key for the store +// unmarshal a unbonding delegation from a store key and value func UnmarshalUBD(cdc *wire.Codec, key, value []byte) UnbondingDelegation { var storeValue ubdValue cdc.MustUnmarshalBinary(value, &storeValue) @@ -192,7 +192,7 @@ type redValue struct { SharesDst sdk.Rat } -// return the unbonding delegation without fields contained within the key for the store +// return the redelegation without fields contained within the key for the store func MarshalRED(cdc *wire.Codec, red Redelegation) []byte { val := redValue{ red.CreationHeight, @@ -205,7 +205,7 @@ func MarshalRED(cdc *wire.Codec, red Redelegation) []byte { return cdc.MustMarshalBinary(val) } -// return the unbonding delegation without fields contained within the key for the store +// unmarshal a redelegation from a store key and value func UnmarshalRED(cdc *wire.Codec, key, value []byte) Redelegation { var storeValue redValue cdc.MustUnmarshalBinary(value, &storeValue) diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index c2c19439b..a2a04b865 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -9,6 +9,7 @@ import ( tmtypes "github.com/tendermint/tendermint/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/wire" ) // Validator defines the total amount of bond shares and their exchange rate to @@ -60,6 +61,70 @@ func NewValidator(owner sdk.Address, pubKey crypto.PubKey, description Descripti } } +// what's kept in the store value +type validatorValue struct { + PubKey crypto.PubKey + Revoked bool + PoolShares PoolShares + DelegatorShares sdk.Rat + Description Description + BondHeight int64 + BondIntraTxCounter int16 + ProposerRewardPool sdk.Coins + Commission sdk.Rat + CommissionMax sdk.Rat + CommissionChangeRate sdk.Rat + CommissionChangeToday sdk.Rat + PrevBondedShares sdk.Rat +} + +// return the redelegation without fields contained within the key for the store +func MarshalValidator(cdc *wire.Codec, validator Validator) []byte { + val := validatorValue{ + PubKey: validator.PubKey, + Revoked: validator.Revoked, + PoolShares: validator.PoolShares, + DelegatorShares: validator.DelegatorShares, + Description: validator.Description, + BondHeight: validator.BondHeight, + BondIntraTxCounter: validator.BondIntraTxCounter, + ProposerRewardPool: validator.ProposerRewardPool, + Commission: validator.Commission, + CommissionMax: validator.CommissionMax, + CommissionChangeRate: validator.CommissionChangeRate, + CommissionChangeToday: validator.CommissionChangeToday, + PrevBondedShares: validator.PrevBondedShares, + } + return cdc.MustMarshalBinary(val) +} + +// unmarshal a redelegation from a store key and value +func UnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) Validator { + var storeValue validatorValue + cdc.MustUnmarshalBinary(value, &storeValue) + + if len(ownerAddr) != 20 { + panic("unexpected address length") + } + + return Validator{ + Owner: ownerAddr, + PubKey: storeValue.PubKey, + Revoked: storeValue.Revoked, + PoolShares: storeValue.PoolShares, + DelegatorShares: storeValue.DelegatorShares, + Description: storeValue.Description, + BondHeight: storeValue.BondHeight, + BondIntraTxCounter: storeValue.BondIntraTxCounter, + ProposerRewardPool: storeValue.ProposerRewardPool, + Commission: storeValue.Commission, + CommissionMax: storeValue.CommissionMax, + CommissionChangeRate: storeValue.CommissionChangeRate, + CommissionChangeToday: storeValue.CommissionChangeToday, + PrevBondedShares: storeValue.PrevBondedShares, + } +} + // only the vitals - does not check bond height of IntraTxCounter func (v Validator) Equal(c2 Validator) bool { return v.PubKey.Equals(c2.PubKey) && From e41f2bc8b597e3793e25b5868da79809ce743597 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Tue, 3 Jul 2018 23:25:31 -0700 Subject: [PATCH 22/53] tests: cli_tests no longer reset call `unsafe_reset_all` on local env * Makes all cli tests use .test_gaiad, .test_gaiacli instead of the same directories as the default binaries * Abstracts alot of the functionality for setting up the server into a single function / file-wide constants. This is to reduce code duplication, especially since some of this functionality depends on each test setting up the keys in the same way. Closes #1461 --- CHANGELOG.md | 1 + cmd/gaia/cli_test/cli_test.go | 104 ++++++++++++++++++---------------- 2 files changed, 56 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56bad46c3..d13fba9e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,6 +98,7 @@ BUG FIXES * \#1353 - CLI: Show pool shares fractions in human-readable format * \#1258 - printing big.rat's can no longer overflow int64 * \#887 - limit the size of rationals that can be passed in from user input +* \#1461 - CLI tests now no longer reset your local environment data ## 0.19.0 diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 07230a4f9..7f04a78f4 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -3,6 +3,9 @@ package clitest import ( "encoding/json" "fmt" + "log" + "os" + "os/user" "testing" "github.com/stretchr/testify/require" @@ -21,30 +24,27 @@ import ( "github.com/cosmos/cosmos-sdk/x/stake" ) +var ( + pass = "1234567890" + gaiadHome = "" + gaiacliHome = "" +) + +func init() { + gaiadHome, gaiacliHome = getTestingHomeDirs() +} + func TestGaiaCLISend(t *testing.T) { + flags, port, proc := resetTestEnv(t) - tests.ExecuteT(t, "gaiad unsafe_reset_all") - pass := "1234567890" - executeWrite(t, "gaiacli keys delete foo", pass) - executeWrite(t, "gaiacli keys delete bar", pass) - chainID := executeInit(t, "gaiad init -o --name=foo") - executeWrite(t, "gaiacli keys add bar", pass) - - // get a free port, also setup some common flags - servAddr, port, err := server.FreeTCPAddr() - require.NoError(t, err) - flags := fmt.Sprintf("--node=%v --chain-id=%v", servAddr, chainID) - - // start gaiad server - proc := tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr)) defer proc.Stop(false) tests.WaitForTMStart(port) tests.WaitForNextHeightTM(port) - fooAddr, _ := executeGetAddrPK(t, "gaiacli keys show foo --output=json") + fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show foo --output=json --home=%s", gaiacliHome)) fooCech, err := sdk.Bech32ifyAcc(fooAddr) require.NoError(t, err) - barAddr, _ := executeGetAddrPK(t, "gaiacli keys show bar --output=json") + barAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome)) barCech, err := sdk.Bech32ifyAcc(barAddr) require.NoError(t, err) @@ -79,29 +79,15 @@ func TestGaiaCLISend(t *testing.T) { } func TestGaiaCLICreateValidator(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) - chainID := executeInit(t, "gaiad init -o --name=foo") - executeWrite(t, "gaiacli keys add bar", pass) - - // get a free port, also setup some common flags - servAddr, port, err := server.FreeTCPAddr() - require.NoError(t, err) - flags := fmt.Sprintf("--node=%v --chain-id=%v", servAddr, chainID) - - // start gaiad server - proc := tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr)) + flags, port, proc := resetTestEnv(t) defer proc.Stop(false) tests.WaitForTMStart(port) tests.WaitForNextHeightTM(port) - fooAddr, _ := executeGetAddrPK(t, "gaiacli keys show foo --output=json") + fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show foo --output=json --home=%s", gaiacliHome)) fooCech, err := sdk.Bech32ifyAcc(fooAddr) require.NoError(t, err) - barAddr, barPubKey := executeGetAddrPK(t, "gaiacli keys show bar --output=json") + barAddr, barPubKey := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome)) barCech, err := sdk.Bech32ifyAcc(barAddr) require.NoError(t, err) barCeshPubKey, err := sdk.Bech32ifyValPub(barPubKey) @@ -153,26 +139,12 @@ func TestGaiaCLICreateValidator(t *testing.T) { } func TestGaiaCLISubmitProposal(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) - chainID := executeInit(t, "gaiad init -o --name=foo") - executeWrite(t, "gaiacli keys add bar", pass) - - // get a free port, also setup some common flags - servAddr, port, err := server.FreeTCPAddr() - require.NoError(t, err) - flags := fmt.Sprintf("--node=%v --chain-id=%v", servAddr, chainID) - - // start gaiad server - proc := tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr)) + flags, port, proc := resetTestEnv(t) defer proc.Stop(false) tests.WaitForTMStart(port) tests.WaitForNextHeightTM(port) - fooAddr, _ := executeGetAddrPK(t, "gaiacli keys show foo --output=json") + fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show foo --output=json --home=%s", gaiacliHome)) fooCech, err := sdk.Bech32ifyAcc(fooAddr) require.NoError(t, err) @@ -206,6 +178,40 @@ func TestGaiaCLISubmitProposal(t *testing.T) { require.Equal(t, gov.VoteOptionToString(gov.OptionYes), vote.Option) } +//___________________________________________________________________________________ +// helper methods + +func getTestingHomeDirs() (string, string) { + usr, err := user.Current() + if err != nil { + log.Fatal(err) + } + // Users home directory + home := usr.HomeDir + gaiadHome := fmt.Sprintf("%s%s.test_gaiad", home, string(os.PathSeparator)) + gaiacliHome := fmt.Sprintf("%s%s.test_gaiacli", home, string(os.PathSeparator)) + return gaiadHome, gaiacliHome +} + +// returns flags, port, process +func resetTestEnv(t *testing.T) (flags string, port string, proc *tests.Process) { + tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome)) + executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass) + executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass) + chainID := executeInit(t, "gaiad init -o --name=foo --home="+gaiadHome) + executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass) + + // get a free port, also setup some common flags + servAddr, port, err := server.FreeTCPAddr() + require.NoError(t, err) + flags = fmt.Sprintf("--home=%s --node=%v --chain-id=%v", gaiacliHome, servAddr, chainID) + + // start gaiad server + proc = tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --home=%s --rpc.laddr=%v", gaiadHome, servAddr)) + + return flags, port, proc +} + //___________________________________________________________________________________ // executors From 2c697c982b27281417b127565b9fc9b314f0fa37 Mon Sep 17 00:00:00 2001 From: Fabian Weber Date: Wed, 4 Jul 2018 10:42:30 +0200 Subject: [PATCH 23/53] added sunnys changes --- client/keys/add.go | 25 +++++++------------------ client/lcd/lcd_test.go | 2 +- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/client/keys/add.go b/client/keys/add.go index 216f84c2a..4d4dee0b9 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -7,7 +7,6 @@ import ( "net/http" "github.com/cosmos/cosmos-sdk/client" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/gorilla/mux" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -162,12 +161,6 @@ type NewKeyBody struct { Password string `json:"password"` } -// new key response REST body -type NewKeyResponse struct { - Address string `json:"address"` - Mnemonic string `json:"mnemonic"` -} - // add new key REST handler func AddNewKeyRequestHandler(w http.ResponseWriter, r *http.Request) { var kb keys.Keybase @@ -216,22 +209,18 @@ func AddNewKeyRequestHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte(err.Error())) return } - bech32Account, err := sdk.Bech32ifyAcc(sdk.Address(info.GetPubKey().Address().Bytes())) + + keyOutput, err := Bech32KeyOutput(info) + keyOutput.Seed = mnemonic + + output, err := json.MarshalIndent(keyOutput, "", " ") if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } - bz, err := json.Marshal(NewKeyResponse{ - Address: bech32Account, - Mnemonic: mnemonic, - }) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - return - } - w.Write(bz) + + w.Write(output) } // function to just a new seed to display in the UI before actually persisting it in the keybase diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index bb2a205a9..234ed57b0 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -56,7 +56,7 @@ func TestKeys(t *testing.T) { res, body = Request(t, port, "POST", "/keys", jsonStr) require.Equal(t, http.StatusOK, res.StatusCode, body) - var resp keys.NewKeyResponse + var resp keys.KeyOutput err = wire.Cdc.UnmarshalJSON([]byte(body), &resp) require.Nil(t, err, body) From 557e652530c0880702e1a23ac9c9590be7113b38 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 4 Jul 2018 09:23:01 -0400 Subject: [PATCH 24/53] docs: fix dead links, closes #1508 --- docs/core/app1.md | 6 +++--- docs/core/app4.md | 2 +- docs/spec/slashing/end_block.md | 2 +- examples/README.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/core/app1.md b/docs/core/app1.md index 91e75966a..ba7f02a8d 100644 --- a/docs/core/app1.md +++ b/docs/core/app1.md @@ -189,7 +189,7 @@ docs](https://godoc.org/github.com/cosmos/cosmos-sdk/types#Context) for more det ### Result Handler takes a Context and Msg and returns a Result. -Result is motivated by the corresponding [ABCI result](https://github.com/tendermint/tendermint/abci/blob/master/types/types.proto#L165). +Result is motivated by the corresponding [ABCI result](https://github.com/tendermint/tendermint/blob/master/abci/types/types.proto#L165). It contains return values, error information, logs, and meta data about the transaction: ```go @@ -409,7 +409,7 @@ func txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) { Finally, we stitch it all together using the `BaseApp`. The BaseApp is an abstraction over the [Tendermint -ABCI](https://github.com/tendermint/tendermint/abci) that +ABCI](https://github.com/tendermint/tendermint/tree/master/abci) that simplifies application development by handling common low-level concerns. It serves as the mediator between the two key components of an SDK app: the store and the message handlers. The BaseApp implements the @@ -473,7 +473,7 @@ Tendermint consensus engine. It would be initialized by a Genesis file, and it would be driven by blocks of transactions committed by the underlying Tendermint consensus. We'll talk more about ABCI and how this all works a bit later, but feel free to check the -[specification](https://github.com/tendermint/tendermint/abci/blob/master/specification.md). +[specification](https://github.com/tendermint/tendermint/blob/master/docs/abci-spec.md). We'll also see how to connect our app to a complete suite of components for running and using a live blockchain application. diff --git a/docs/core/app4.md b/docs/core/app4.md index d7226b466..0724e5e7a 100644 --- a/docs/core/app4.md +++ b/docs/core/app4.md @@ -16,7 +16,7 @@ here we will introduce the other ABCI requests sent by Tendermint, and how we can use them to build more advanced applications. For a more complete depiction of the ABCI and how its used, see [the -specification](https://github.com/tendermint/tendermint/abci/blob/master/specification.md) +specification](https://github.com/tendermint/tendermint/blob/master/docs/abci-spec.md) ## InitChain diff --git a/docs/spec/slashing/end_block.md b/docs/spec/slashing/end_block.md index e923fd844..3eec27372 100644 --- a/docs/spec/slashing/end_block.md +++ b/docs/spec/slashing/end_block.md @@ -6,7 +6,7 @@ Tendermint blocks can include [Evidence](https://github.com/tendermint/tendermint/blob/develop/docs/spec/blockchain/blockchain.md#evidence), which indicates that a validator committed malicious behaviour. The relevant information is forwarded to the application as [ABCI -Evidence](https://github.com/tendermint/tendermint/abci/blob/develop/types/types.proto#L259), so the validator an be accordingly punished. +Evidence](https://github.com/tendermint/tendermint/blob/develop/abci/types/types.proto#L259), so the validator an be accordingly punished. For some `evidence` to be valid, it must satisfy: diff --git a/examples/README.md b/examples/README.md index 3f45e025c..a8a483ee6 100644 --- a/examples/README.md +++ b/examples/README.md @@ -256,7 +256,7 @@ Accounts are serialized and stored in a Merkle tree under the key Typically, the address of the account is the 20-byte ``RIPEMD160`` hash of the public key, but other formats are acceptable as well, as defined in the `Tendermint crypto -library `__. The Merkle tree +library `__. The Merkle tree used in Basecoin is a balanced, binary search tree, which we call an `IAVL tree `__. From 59983787735ff9fd141e2eefe8c33e66f9c1e96c Mon Sep 17 00:00:00 2001 From: Fabian Weber Date: Wed, 4 Jul 2018 16:39:16 +0200 Subject: [PATCH 25/53] added error check --- client/keys/add.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/keys/add.go b/client/keys/add.go index 4d4dee0b9..b76354685 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -211,6 +211,12 @@ func AddNewKeyRequestHandler(w http.ResponseWriter, r *http.Request) { } keyOutput, err := Bech32KeyOutput(info) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + keyOutput.Seed = mnemonic output, err := json.MarshalIndent(keyOutput, "", " ") From b0e6c765543aac883dcab11018c2ca68475cf124 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Wed, 4 Jul 2018 08:20:44 -0700 Subject: [PATCH 26/53] Remove redundant comment, switch to MustBech32ify --- cmd/gaia/cli_test/cli_test.go | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 7f04a78f4..98f393ec5 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -42,11 +42,9 @@ func TestGaiaCLISend(t *testing.T) { tests.WaitForNextHeightTM(port) fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show foo --output=json --home=%s", gaiacliHome)) - fooCech, err := sdk.Bech32ifyAcc(fooAddr) - require.NoError(t, err) + fooCech := sdk.MustBech32ifyAcc(fooAddr) barAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome)) - barCech, err := sdk.Bech32ifyAcc(barAddr) - require.NoError(t, err) + barCech := sdk.MustBech32ifyAcc(barAddr) fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooCech, flags)) require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64()) @@ -85,13 +83,10 @@ func TestGaiaCLICreateValidator(t *testing.T) { tests.WaitForNextHeightTM(port) fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show foo --output=json --home=%s", gaiacliHome)) - fooCech, err := sdk.Bech32ifyAcc(fooAddr) - require.NoError(t, err) + fooCech := sdk.MustBech32ifyAcc(fooAddr) barAddr, barPubKey := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome)) - barCech, err := sdk.Bech32ifyAcc(barAddr) - require.NoError(t, err) - barCeshPubKey, err := sdk.Bech32ifyValPub(barPubKey) - require.NoError(t, err) + barCech := sdk.MustBech32ifyAcc(barAddr) + barCeshPubKey := sdk.MustBech32ifyValPub(barPubKey) executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --name=foo", flags, barCech), pass) tests.WaitForNextHeightTM(port) @@ -145,8 +140,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) { tests.WaitForNextHeightTM(port) fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show foo --output=json --home=%s", gaiacliHome)) - fooCech, err := sdk.Bech32ifyAcc(fooAddr) - require.NoError(t, err) + fooCech := sdk.MustBech32ifyAcc(fooAddr) fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooCech, flags)) require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64()) @@ -186,7 +180,6 @@ func getTestingHomeDirs() (string, string) { if err != nil { log.Fatal(err) } - // Users home directory home := usr.HomeDir gaiadHome := fmt.Sprintf("%s%s.test_gaiad", home, string(os.PathSeparator)) gaiacliHome := fmt.Sprintf("%s%s.test_gaiacli", home, string(os.PathSeparator)) From 319358c587d709ecfb6a1bf38c7fdfa3b2d4e39b Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 4 Jul 2018 14:34:55 -0400 Subject: [PATCH 27/53] changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56bad46c3..b35664140 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,8 +37,9 @@ BREAKING CHANGES * Add REST endpoint to unrevoke a validator previously revoked for downtime * Add REST endpoint to retrieve liveness signing information for a validator * [types] renamed rational.Evaluate to rational.Round{Int64, Int} -* [stake] most index keys nolonger hold a value - inputs are rearranged to form the desired key +* [x/stake] most index keys nolonger hold a value - inputs are rearranged to form the desired key * [lcd] Switch key creation output to return bech32 +* [x/stake] store-value for delegation, validator, ubd, and red do not hold duplicate information contained store-key FEATURES * [gaiacli] You can now attach a simple text-only memo to any transaction, with the `--memo` flag From 640bccf8f798e98f47c1eb40ac7c1373a68d468c Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Wed, 4 Jul 2018 13:09:59 -0700 Subject: [PATCH 28/53] Switch using user home to a tmp directory --- cmd/gaia/cli_test/cli_test.go | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 98f393ec5..eb5b988b7 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -3,9 +3,7 @@ package clitest import ( "encoding/json" "fmt" - "log" "os" - "os/user" "testing" "github.com/stretchr/testify/require" @@ -176,13 +174,9 @@ func TestGaiaCLISubmitProposal(t *testing.T) { // helper methods func getTestingHomeDirs() (string, string) { - usr, err := user.Current() - if err != nil { - log.Fatal(err) - } - home := usr.HomeDir - gaiadHome := fmt.Sprintf("%s%s.test_gaiad", home, string(os.PathSeparator)) - gaiacliHome := fmt.Sprintf("%s%s.test_gaiacli", home, string(os.PathSeparator)) + tmpDir := os.TempDir() + gaiadHome := fmt.Sprintf("%s%s.test_gaiad", tmpDir, string(os.PathSeparator)) + gaiacliHome := fmt.Sprintf("%s%s.test_gaiacli", tmpDir, string(os.PathSeparator)) return gaiadHome, gaiacliHome } From aed3a873669d9c84f7087be78e7320e0a2dd7baf Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 4 Jul 2018 17:07:06 -0400 Subject: [PATCH 29/53] address cwgoes comments --- types/account.go | 6 ++- x/stake/client/cli/query.go | 16 +++---- x/stake/client/rest/query.go | 28 +++++++++-- x/stake/keeper/delegation.go | 20 ++++---- x/stake/keeper/key.go | 22 ++++----- x/stake/keeper/sdk_types.go | 4 +- x/stake/keeper/validator.go | 9 ++-- x/stake/types/delegation.go | 90 ++++++++++++++++++++++++++---------- x/stake/types/validator.go | 25 ++++++++-- 9 files changed, 149 insertions(+), 71 deletions(-) diff --git a/types/account.go b/types/account.go index ce872d8b5..0cdc75fe2 100644 --- a/types/account.go +++ b/types/account.go @@ -13,8 +13,12 @@ import ( //Address is a go crypto-style Address type Address = cmn.HexBytes -// Bech32 prefixes +// nolint const ( + // expected address length + AddrLen = 20 + + // Bech32 prefixes Bech32PrefixAccAddr = "cosmosaccaddr" Bech32PrefixAccPub = "cosmosaccpub" Bech32PrefixValAddr = "cosmosvaladdr" diff --git a/x/stake/client/cli/query.go b/x/stake/client/cli/query.go index ee495e96e..39c7771f0 100644 --- a/x/stake/client/cli/query.go +++ b/x/stake/client/cli/query.go @@ -33,7 +33,7 @@ func GetCmdQueryValidator(storeName string, cdc *wire.Codec) *cobra.Command { return err } - validator := types.UnmarshalValidator(cdc, addr, res) + validator := types.MustUnmarshalValidator(cdc, addr, res) switch viper.Get(cli.OutputFlag) { case "text": @@ -77,7 +77,7 @@ func GetCmdQueryValidators(storeName string, cdc *wire.Codec) *cobra.Command { var validators []stake.Validator for _, kv := range resKVs { addr := kv.Key[1:] - validator := types.UnmarshalValidator(cdc, addr, kv.Value) + validator := types.MustUnmarshalValidator(cdc, addr, kv.Value) validators = append(validators, validator) } @@ -131,7 +131,7 @@ func GetCmdQueryDelegation(storeName string, cdc *wire.Codec) *cobra.Command { } // parse out the delegation - delegation := types.UnmarshalDelegation(cdc, key, res) + delegation := types.MustUnmarshalDelegation(cdc, key, res) switch viper.Get(cli.OutputFlag) { case "text": @@ -179,7 +179,7 @@ func GetCmdQueryDelegations(storeName string, cdc *wire.Codec) *cobra.Command { // parse out the validators var delegations []stake.Delegation for _, kv := range resKVs { - delegation := types.UnmarshalDelegation(cdc, kv.Key, kv.Value) + delegation := types.MustUnmarshalDelegation(cdc, kv.Key, kv.Value) delegations = append(delegations, delegation) } @@ -221,7 +221,7 @@ func GetCmdQueryUnbondingDelegation(storeName string, cdc *wire.Codec) *cobra.Co } // parse out the unbonding delegation - ubd := types.UnmarshalUBD(cdc, key, res) + ubd := types.MustUnmarshalUBD(cdc, key, res) switch viper.Get(cli.OutputFlag) { case "text": @@ -269,7 +269,7 @@ func GetCmdQueryUnbondingDelegations(storeName string, cdc *wire.Codec) *cobra.C // parse out the validators var ubds []stake.UnbondingDelegation for _, kv := range resKVs { - ubd := types.UnmarshalUBD(cdc, kv.Key, kv.Value) + ubd := types.MustUnmarshalUBD(cdc, kv.Key, kv.Value) ubds = append(ubds, ubd) } @@ -314,7 +314,7 @@ func GetCmdQueryRedelegation(storeName string, cdc *wire.Codec) *cobra.Command { } // parse out the unbonding delegation - red := types.UnmarshalRED(cdc, key, res) + red := types.MustUnmarshalRED(cdc, key, res) switch viper.Get(cli.OutputFlag) { case "text": @@ -362,7 +362,7 @@ func GetCmdQueryRedelegations(storeName string, cdc *wire.Codec) *cobra.Command // parse out the validators var reds []stake.Redelegation for _, kv := range resKVs { - red := types.UnmarshalRED(cdc, kv.Key, kv.Value) + red := types.MustUnmarshalRED(cdc, kv.Key, kv.Value) reds = append(reds, red) } diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index 49051c73e..090445f0a 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -77,7 +77,12 @@ func delegationHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerF return } - delegation := types.UnmarshalDelegation(cdc, key, res) + delegation, err := types.UnmarshalDelegation(cdc, key, res) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } output, err := cdc.MarshalJSON(delegation) if err != nil { @@ -128,7 +133,12 @@ func ubdHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerFunc { return } - ubd := types.UnmarshalUBD(cdc, key, res) + ubd, err := types.UnmarshalUBD(cdc, key, res) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(fmt.Sprintf("couldn't query unbonding-delegation. Error: %s", err.Error()))) + return + } output, err := cdc.MarshalJSON(ubd) if err != nil { @@ -187,7 +197,12 @@ func redHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerFunc { return } - red := types.UnmarshalRED(cdc, key, res) + red, err := types.UnmarshalRED(cdc, key, res) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(fmt.Sprintf("couldn't query unbonding-delegation. Error: %s", err.Error()))) + return + } output, err := cdc.MarshalJSON(red) if err != nil { @@ -277,7 +292,12 @@ func validatorsHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerF for i, kv := range kvs { addr := kv.Key[1:] - validator := types.UnmarshalValidator(cdc, addr, kv.Value) + validator, err := types.UnmarshalValidator(cdc, addr, kv.Value) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(fmt.Sprintf("couldn't query unbonding-delegation. Error: %s", err.Error()))) + return + } bech32Validator, err := bech32StakeValidatorOutput(validator) if err != nil { diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 3d949a9a0..353154ce2 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -18,7 +18,7 @@ func (k Keeper) GetDelegation(ctx sdk.Context, return delegation, false } - delegation = types.UnmarshalDelegation(k.cdc, key, value) + delegation = types.MustUnmarshalDelegation(k.cdc, key, value) return delegation, true } @@ -32,7 +32,7 @@ func (k Keeper) GetAllDelegations(ctx sdk.Context) (delegations []types.Delegati if !iterator.Valid() { break } - delegation := types.UnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) + delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) delegations = append(delegations, delegation) iterator.Next() } @@ -54,7 +54,7 @@ func (k Keeper) GetDelegations(ctx sdk.Context, delegator sdk.Address, if !iterator.Valid() || i > int(maxRetrieve-1) { break } - delegation := types.UnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) + delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) delegations[i] = delegation iterator.Next() } @@ -65,7 +65,7 @@ func (k Keeper) GetDelegations(ctx sdk.Context, delegator sdk.Address, // set the delegation func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { store := ctx.KVStore(k.storeKey) - b := types.MarshalDelegation(k.cdc, delegation) + b := types.MustMarshalDelegation(k.cdc, delegation) store.Set(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr), b) } @@ -88,7 +88,7 @@ func (k Keeper) GetUnbondingDelegation(ctx sdk.Context, return ubd, false } - ubd = types.UnmarshalUBD(k.cdc, key, value) + ubd = types.MustUnmarshalUBD(k.cdc, key, value) return ubd, true } @@ -102,7 +102,7 @@ func (k Keeper) GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr sd } key := GetUBDKeyFromValIndexKey(iterator.Key()) value := store.Get(key) - ubd := types.UnmarshalUBD(k.cdc, key, value) + ubd := types.MustUnmarshalUBD(k.cdc, key, value) ubds = append(ubds, ubd) iterator.Next() } @@ -113,7 +113,7 @@ func (k Keeper) GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr sd // set the unbonding delegation and associated index func (k Keeper) SetUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDelegation) { store := ctx.KVStore(k.storeKey) - bz := types.MarshalUBD(k.cdc, ubd) + bz := types.MustMarshalUBD(k.cdc, ubd) key := GetUBDKey(ubd.DelegatorAddr, ubd.ValidatorAddr) store.Set(key, bz) store.Set(GetUBDByValIndexKey(ubd.DelegatorAddr, ubd.ValidatorAddr), []byte{}) // index, store empty bytes @@ -140,7 +140,7 @@ func (k Keeper) GetRedelegation(ctx sdk.Context, return red, false } - red = types.UnmarshalRED(k.cdc, key, value) + red = types.MustUnmarshalRED(k.cdc, key, value) return red, true } @@ -154,7 +154,7 @@ func (k Keeper) GetRedelegationsFromValidator(ctx sdk.Context, valAddr sdk.Addre } key := GetREDKeyFromValSrcIndexKey(iterator.Key()) value := store.Get(key) - red := types.UnmarshalRED(k.cdc, key, value) + red := types.MustUnmarshalRED(k.cdc, key, value) reds = append(reds, red) iterator.Next() } @@ -182,7 +182,7 @@ func (k Keeper) HasReceivingRedelegation(ctx sdk.Context, // set a redelegation and associated index func (k Keeper) SetRedelegation(ctx sdk.Context, red types.Redelegation) { store := ctx.KVStore(k.storeKey) - bz := types.MarshalRED(k.cdc, red) + bz := types.MustMarshalRED(k.cdc, red) key := GetREDKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr) store.Set(key, bz) store.Set(GetREDByValSrcIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr), []byte{}) diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index cfe8ded82..32c54f519 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -131,11 +131,11 @@ func GetUBDByValIndexKey(delegatorAddr, validatorAddr sdk.Address) []byte { // rearrange the ValIndexKey to get the UBDKey func GetUBDKeyFromValIndexKey(IndexKey []byte) []byte { addrs := IndexKey[1:] // remove prefix bytes - if len(addrs) != 40 { + if len(addrs) != 2*sdk.AddrLen { panic("unexpected key length") } - valAddr := addrs[:20] - delAddr := addrs[20:] + valAddr := addrs[:sdk.AddrLen] + delAddr := addrs[sdk.AddrLen:] return GetUBDKey(delAddr, valAddr) } @@ -189,12 +189,12 @@ func GetREDByValDstIndexKey(delegatorAddr, validatorSrcAddr, // rearrange the ValSrcIndexKey to get the REDKey func GetREDKeyFromValSrcIndexKey(IndexKey []byte) []byte { addrs := IndexKey[1:] // remove prefix bytes - if len(addrs) != 60 { + if len(addrs) != 3*sdk.AddrLen { panic("unexpected key length") } - valSrcAddr := addrs[:20] - delAddr := addrs[20:40] - valDstAddr := addrs[40:] + valSrcAddr := addrs[:sdk.AddrLen] + delAddr := addrs[sdk.AddrLen : 2*sdk.AddrLen] + valDstAddr := addrs[2*sdk.AddrLen:] return GetREDKey(delAddr, valSrcAddr, valDstAddr) } @@ -202,12 +202,12 @@ func GetREDKeyFromValSrcIndexKey(IndexKey []byte) []byte { // rearrange the ValDstIndexKey to get the REDKey func GetREDKeyFromValDstIndexKey(IndexKey []byte) []byte { addrs := IndexKey[1:] // remove prefix bytes - if len(addrs) != 60 { + if len(addrs) != 3*sdk.AddrLen { panic("unexpected key length") } - valDstAddr := addrs[:20] - delAddr := addrs[20:40] - valSrcAddr := addrs[40:] + valDstAddr := addrs[:sdk.AddrLen] + delAddr := addrs[sdk.AddrLen : 2*sdk.AddrLen] + valSrcAddr := addrs[2*sdk.AddrLen:] return GetREDKey(delAddr, valSrcAddr, valDstAddr) } diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index 0fe465892..b8be3e34f 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -17,7 +17,7 @@ func (k Keeper) IterateValidators(ctx sdk.Context, fn func(index int64, validato i := int64(0) for ; iterator.Valid(); iterator.Next() { addr := iterator.Key()[1:] - validator := types.UnmarshalValidator(k.cdc, addr, iterator.Value()) + validator := types.MustUnmarshalValidator(k.cdc, addr, iterator.Value()) stop := fn(i, validator) // XXX is this safe will the validator unexposed fields be able to get written to? if stop { break @@ -90,7 +90,7 @@ func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.Address, fn func iterator := sdk.KVStorePrefixIterator(store, key) i := int64(0) for ; iterator.Valid(); iterator.Next() { - delegation := types.UnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) + delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) stop := fn(i, delegation) // XXX is this safe will the fields be able to get written to? if stop { break diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index ad70958a3..164c50049 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -18,8 +18,7 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.Address) (validator types if value == nil { return validator, false } - fmt.Printf("debug addr: %v\n", addr) - validator = types.UnmarshalValidator(k.cdc, addr, value) + validator = types.MustUnmarshalValidator(k.cdc, addr, value) return validator, true } @@ -36,7 +35,7 @@ func (k Keeper) GetValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) (val // set the main record holding validator details func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) - bz := types.MarshalValidator(k.cdc, validator) + bz := types.MustMarshalValidator(k.cdc, validator) store.Set(GetValidatorKey(validator.Owner), bz) } @@ -75,7 +74,7 @@ func (k Keeper) GetAllValidators(ctx sdk.Context) (validators []types.Validator) break } addr := iterator.Key()[1:] - validator := types.UnmarshalValidator(k.cdc, addr, iterator.Value()) + validator := types.MustUnmarshalValidator(k.cdc, addr, iterator.Value()) validators = append(validators, validator) iterator.Next() } @@ -95,7 +94,7 @@ func (k Keeper) GetValidators(ctx sdk.Context, maxRetrieve int16) (validators [] break } addr := iterator.Key()[1:] - validator := types.UnmarshalValidator(k.cdc, addr, iterator.Value()) + validator := types.MustUnmarshalValidator(k.cdc, addr, iterator.Value()) validators[i] = validator iterator.Next() } diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index 7b9d45c0d..f7d31a640 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -2,6 +2,7 @@ package types import ( "bytes" + "errors" "fmt" sdk "github.com/cosmos/cosmos-sdk/types" @@ -24,7 +25,7 @@ type delegationValue struct { } // return the delegation without fields contained within the key for the store -func MarshalDelegation(cdc *wire.Codec, delegation Delegation) []byte { +func MustMarshalDelegation(cdc *wire.Codec, delegation Delegation) []byte { val := delegationValue{ delegation.Shares, delegation.Height, @@ -33,23 +34,36 @@ func MarshalDelegation(cdc *wire.Codec, delegation Delegation) []byte { } // return the delegation without fields contained within the key for the store -func UnmarshalDelegation(cdc *wire.Codec, key, value []byte) Delegation { +func MustUnmarshalDelegation(cdc *wire.Codec, key, value []byte) Delegation { + delegation, err := UnmarshalDelegation(cdc, key, value) + if err != nil { + panic(err) + } + return delegation +} + +// return the delegation without fields contained within the key for the store +func UnmarshalDelegation(cdc *wire.Codec, key, value []byte) (delegation Delegation, err error) { var storeValue delegationValue - cdc.MustUnmarshalBinary(value, &storeValue) + err = cdc.UnmarshalBinary(value, &storeValue) + if err != nil { + return + } addrs := key[1:] // remove prefix bytes - if len(addrs) != 40 { - panic("unexpected key length") + if len(addrs) != 2*sdk.AddrLen { + err = errors.New("unexpected key length") + return } - delAddr := sdk.Address(addrs[:20]) - valAddr := sdk.Address(addrs[20:]) + delAddr := sdk.Address(addrs[:sdk.AddrLen]) + valAddr := sdk.Address(addrs[sdk.AddrLen:]) return Delegation{ DelegatorAddr: delAddr, ValidatorAddr: valAddr, Shares: storeValue.Shares, Height: storeValue.Height, - } + }, nil } // nolint @@ -109,7 +123,7 @@ type ubdValue struct { } // return the unbonding delegation without fields contained within the key for the store -func MarshalUBD(cdc *wire.Codec, ubd UnbondingDelegation) []byte { +func MustMarshalUBD(cdc *wire.Codec, ubd UnbondingDelegation) []byte { val := ubdValue{ ubd.CreationHeight, ubd.MinTime, @@ -120,16 +134,29 @@ func MarshalUBD(cdc *wire.Codec, ubd UnbondingDelegation) []byte { } // unmarshal a unbonding delegation from a store key and value -func UnmarshalUBD(cdc *wire.Codec, key, value []byte) UnbondingDelegation { +func MustUnmarshalUBD(cdc *wire.Codec, key, value []byte) UnbondingDelegation { + ubd, err := UnmarshalUBD(cdc, key, value) + if err != nil { + panic(err) + } + return ubd +} + +// unmarshal a unbonding delegation from a store key and value +func UnmarshalUBD(cdc *wire.Codec, key, value []byte) (ubd UnbondingDelegation, err error) { var storeValue ubdValue - cdc.MustUnmarshalBinary(value, &storeValue) + err = cdc.UnmarshalBinary(value, &storeValue) + if err != nil { + return + } addrs := key[1:] // remove prefix bytes - if len(addrs) != 40 { - panic("unexpected key length") + if len(addrs) != 2*sdk.AddrLen { + err = errors.New("unexpected key length") + return } - delAddr := sdk.Address(addrs[:20]) - valAddr := sdk.Address(addrs[20:]) + delAddr := sdk.Address(addrs[:sdk.AddrLen]) + valAddr := sdk.Address(addrs[sdk.AddrLen:]) return UnbondingDelegation{ DelegatorAddr: delAddr, @@ -138,7 +165,7 @@ func UnmarshalUBD(cdc *wire.Codec, key, value []byte) UnbondingDelegation { MinTime: storeValue.MinTime, InitialBalance: storeValue.InitialBalance, Balance: storeValue.Balance, - } + }, nil } // nolint @@ -196,7 +223,7 @@ type redValue struct { } // return the redelegation without fields contained within the key for the store -func MarshalRED(cdc *wire.Codec, red Redelegation) []byte { +func MustMarshalRED(cdc *wire.Codec, red Redelegation) []byte { val := redValue{ red.CreationHeight, red.MinTime, @@ -209,17 +236,30 @@ func MarshalRED(cdc *wire.Codec, red Redelegation) []byte { } // unmarshal a redelegation from a store key and value -func UnmarshalRED(cdc *wire.Codec, key, value []byte) Redelegation { +func MustUnmarshalRED(cdc *wire.Codec, key, value []byte) Redelegation { + red, err := UnmarshalRED(cdc, key, value) + if err != nil { + panic(err) + } + return red +} + +// unmarshal a redelegation from a store key and value +func UnmarshalRED(cdc *wire.Codec, key, value []byte) (red Redelegation, err error) { var storeValue redValue - cdc.MustUnmarshalBinary(value, &storeValue) + err = cdc.UnmarshalBinary(value, &storeValue) + if err != nil { + return + } addrs := key[1:] // remove prefix bytes - if len(addrs) != 60 { - panic("unexpected key length") + if len(addrs) != 3*sdk.AddrLen { + err = errors.New("unexpected key length") + return } - delAddr := sdk.Address(addrs[:20]) - valSrcAddr := sdk.Address(addrs[20:40]) - valDstAddr := sdk.Address(addrs[40:60]) + delAddr := sdk.Address(addrs[:sdk.AddrLen]) + valSrcAddr := sdk.Address(addrs[sdk.AddrLen : 2*sdk.AddrLen]) + valDstAddr := sdk.Address(addrs[2*sdk.AddrLen:]) return Redelegation{ DelegatorAddr: delAddr, @@ -231,7 +271,7 @@ func UnmarshalRED(cdc *wire.Codec, key, value []byte) Redelegation { Balance: storeValue.Balance, SharesSrc: storeValue.SharesSrc, SharesDst: storeValue.SharesDst, - } + }, nil } // nolint diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index 80ee70355..480416d01 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -2,6 +2,7 @@ package types import ( "bytes" + "errors" "fmt" abci "github.com/tendermint/tendermint/abci/types" @@ -81,7 +82,7 @@ type validatorValue struct { } // return the redelegation without fields contained within the key for the store -func MarshalValidator(cdc *wire.Codec, validator Validator) []byte { +func MustMarshalValidator(cdc *wire.Codec, validator Validator) []byte { val := validatorValue{ PubKey: validator.PubKey, Revoked: validator.Revoked, @@ -101,12 +102,26 @@ func MarshalValidator(cdc *wire.Codec, validator Validator) []byte { } // unmarshal a redelegation from a store key and value -func UnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) Validator { +func MustUnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) Validator { + validator, err := UnmarshalValidator(cdc, ownerAddr, value) + if err != nil { + panic(err) + } + + return validator +} + +// unmarshal a redelegation from a store key and value +func UnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) (validator Validator, err error) { var storeValue validatorValue - cdc.MustUnmarshalBinary(value, &storeValue) + err = cdc.UnmarshalBinary(value, &storeValue) + if err != nil { + return + } if len(ownerAddr) != 20 { - panic("unexpected address length") + err = errors.New("unexpected address length") + return } return Validator{ @@ -124,7 +139,7 @@ func UnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) Validator { CommissionChangeRate: storeValue.CommissionChangeRate, CommissionChangeToday: storeValue.CommissionChangeToday, PrevBondedShares: storeValue.PrevBondedShares, - } + }, nil } // only the vitals - does not check bond height of IntraTxCounter From 22ec6ad98d789e38c0acc710d2f854376438c0fd Mon Sep 17 00:00:00 2001 From: Joon Date: Thu, 5 Jul 2018 09:04:21 -0700 Subject: [PATCH 30/53] Merge pull request #1532 : Add Codec.Seal fix wire --- baseapp/baseapp_test.go | 1 + cmd/gaia/cmd/gaiadebug/hack.go | 1 + examples/basecoin/app/app.go | 2 ++ examples/democoin/app/app.go | 3 +++ examples/democoin/x/oracle/oracle_test.go | 2 ++ wire/wire.go | 3 +-- x/ibc/ibc_test.go | 2 ++ 7 files changed, 12 insertions(+), 2 deletions(-) diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index 4eea49fd3..e919375d9 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -769,6 +769,7 @@ func MakeCodec() *wire.Codec { crypto.RegisterAmino(cdc) cdc.RegisterInterface((*auth.Account)(nil), nil) cdc.RegisterConcrete(&auth.BaseAccount{}, "cosmos-sdk/BaseAccount", nil) + cdc.Seal() return cdc } diff --git a/cmd/gaia/cmd/gaiadebug/hack.go b/cmd/gaia/cmd/gaiadebug/hack.go index 1f2ef0649..ddc8466c7 100644 --- a/cmd/gaia/cmd/gaiadebug/hack.go +++ b/cmd/gaia/cmd/gaiadebug/hack.go @@ -197,6 +197,7 @@ func MakeCodec() *wire.Codec { auth.RegisterWire(cdc) sdk.RegisterWire(cdc) wire.RegisterCrypto(cdc) + cdc.Seal() return cdc } diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index f75d6a834..6df74ef28 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -103,6 +103,8 @@ func MakeCodec() *wire.Codec { cdc.RegisterInterface((*auth.Account)(nil), nil) cdc.RegisterConcrete(&types.AppAccount{}, "basecoin/Account", nil) + cdc.Seal() + return cdc } diff --git a/examples/democoin/app/app.go b/examples/democoin/app/app.go index 1c44a0bbd..6ea7d5247 100644 --- a/examples/democoin/app/app.go +++ b/examples/democoin/app/app.go @@ -113,6 +113,9 @@ func MakeCodec() *wire.Codec { // Register AppAccount cdc.RegisterInterface((*auth.Account)(nil), nil) cdc.RegisterConcrete(&types.AppAccount{}, "democoin/Account", nil) + + cdc.Seal() + return cdc } diff --git a/examples/democoin/x/oracle/oracle_test.go b/examples/democoin/x/oracle/oracle_test.go index ef925c94f..467035897 100644 --- a/examples/democoin/x/oracle/oracle_test.go +++ b/examples/democoin/x/oracle/oracle_test.go @@ -48,6 +48,8 @@ func makeCodec() *wire.Codec { cdc.RegisterInterface((*Payload)(nil), nil) cdc.RegisterConcrete(seqOracle{}, "test/oracle/seqOracle", nil) + cdc.Seal() + return cdc } diff --git a/wire/wire.go b/wire/wire.go index 1d5291f86..679bf7c28 100644 --- a/wire/wire.go +++ b/wire/wire.go @@ -44,6 +44,5 @@ var Cdc *Codec func init() { cdc := NewCodec() RegisterCrypto(cdc) - Cdc = cdc - //Cdc = cdc.Seal() // TODO uncomment once amino upgraded to 0.9.10 + Cdc = cdc.Seal() } diff --git a/x/ibc/ibc_test.go b/x/ibc/ibc_test.go index 4cb708c1b..1d87e7806 100644 --- a/x/ibc/ibc_test.go +++ b/x/ibc/ibc_test.go @@ -53,6 +53,8 @@ func makeCodec() *wire.Codec { cdc.RegisterConcrete(&auth.BaseAccount{}, "test/ibc/Account", nil) wire.RegisterCrypto(cdc) + cdc.Seal() + return cdc } From 492272c5e6a03db5c9c802b4589f3b69f91e337e Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 5 Jul 2018 09:08:43 -0700 Subject: [PATCH 31/53] cli_test: Un-abstract common code This is done to enhance readability, so one can easily reproduce the functionality in the command line. --- cmd/gaia/cli_test/cli_test.go | 63 +++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index eb5b988b7..17c727959 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -33,7 +33,19 @@ func init() { } func TestGaiaCLISend(t *testing.T) { - flags, port, proc := resetTestEnv(t) + tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome)) + executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass) + executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass) + chainID := executeInit(t, "gaiad init -o --name=foo --home="+gaiadHome) + executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass) + + // get a free port, also setup some common flags + servAddr, port, err := server.FreeTCPAddr() + require.NoError(t, err) + flags := fmt.Sprintf("--home=%s --node=%v --chain-id=%v", gaiacliHome, servAddr, chainID) + + // start gaiad server + proc := tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --home=%s --rpc.laddr=%v", gaiadHome, servAddr)) defer proc.Stop(false) tests.WaitForTMStart(port) @@ -75,7 +87,20 @@ func TestGaiaCLISend(t *testing.T) { } func TestGaiaCLICreateValidator(t *testing.T) { - flags, port, proc := resetTestEnv(t) + tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome)) + executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass) + executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass) + chainID := executeInit(t, "gaiad init -o --name=foo --home="+gaiadHome) + executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass) + + // get a free port, also setup some common flags + servAddr, port, err := server.FreeTCPAddr() + require.NoError(t, err) + flags := fmt.Sprintf("--home=%s --node=%v --chain-id=%v", gaiacliHome, servAddr, chainID) + + // start gaiad server + proc := tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --home=%s --rpc.laddr=%v", gaiadHome, servAddr)) + defer proc.Stop(false) tests.WaitForTMStart(port) tests.WaitForNextHeightTM(port) @@ -132,7 +157,20 @@ func TestGaiaCLICreateValidator(t *testing.T) { } func TestGaiaCLISubmitProposal(t *testing.T) { - flags, port, proc := resetTestEnv(t) + tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome)) + executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass) + executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass) + chainID := executeInit(t, "gaiad init -o --name=foo --home="+gaiadHome) + executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass) + + // get a free port, also setup some common flags + servAddr, port, err := server.FreeTCPAddr() + require.NoError(t, err) + flags := fmt.Sprintf("--home=%s --node=%v --chain-id=%v", gaiacliHome, servAddr, chainID) + + // start gaiad server + proc := tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --home=%s --rpc.laddr=%v", gaiadHome, servAddr)) + defer proc.Stop(false) tests.WaitForTMStart(port) tests.WaitForNextHeightTM(port) @@ -180,25 +218,6 @@ func getTestingHomeDirs() (string, string) { return gaiadHome, gaiacliHome } -// returns flags, port, process -func resetTestEnv(t *testing.T) (flags string, port string, proc *tests.Process) { - tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome)) - executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass) - executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass) - chainID := executeInit(t, "gaiad init -o --name=foo --home="+gaiadHome) - executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass) - - // get a free port, also setup some common flags - servAddr, port, err := server.FreeTCPAddr() - require.NoError(t, err) - flags = fmt.Sprintf("--home=%s --node=%v --chain-id=%v", gaiacliHome, servAddr, chainID) - - // start gaiad server - proc = tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --home=%s --rpc.laddr=%v", gaiadHome, servAddr)) - - return flags, port, proc -} - //___________________________________________________________________________________ // executors From 547390a238b23024f24ee79898b4b61f783f1682 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Thu, 5 Jul 2018 17:11:44 +0100 Subject: [PATCH 32/53] WIP: add simple sorting using golang json.Marshal --- Gopkg.lock | 512 -------------------------------------------- server/util.go | 17 ++ server/util_test.go | 4 + 3 files changed, 21 insertions(+), 512 deletions(-) delete mode 100644 Gopkg.lock diff --git a/Gopkg.lock b/Gopkg.lock deleted file mode 100644 index 7a9b56696..000000000 --- a/Gopkg.lock +++ /dev/null @@ -1,512 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - branch = "master" - name = "github.com/bartekn/go-bip39" - packages = ["."] - revision = "a05967ea095d81c8fe4833776774cfaff8e5036c" - -[[projects]] - branch = "master" - name = "github.com/beorn7/perks" - packages = ["quantile"] - revision = "3a771d992973f24aa725d07868b467d1ddfceafb" - -[[projects]] - name = "github.com/bgentry/speakeasy" - packages = ["."] - revision = "4aabc24848ce5fd31929f7d1e4ea74d3709c14cd" - version = "v0.1.0" - -[[projects]] - branch = "master" - name = "github.com/brejski/hid" - packages = ["."] - revision = "06112dcfcc50a7e0e4fd06e17f9791e788fdaafc" - -[[projects]] - branch = "master" - name = "github.com/btcsuite/btcd" - packages = ["btcec"] - revision = "86fed781132ac890ee03e906e4ecd5d6fa180c64" - -[[projects]] - branch = "master" - name = "github.com/btcsuite/btcutil" - packages = ["bech32"] - revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4" - -[[projects]] - name = "github.com/davecgh/go-spew" - packages = ["spew"] - revision = "346938d642f2ec3594ed81d874461961cd0faa76" - version = "v1.1.0" - -[[projects]] - branch = "master" - name = "github.com/ebuchman/fail-test" - packages = ["."] - revision = "95f809107225be108efcf10a3509e4ea6ceef3c4" - -[[projects]] - name = "github.com/fsnotify/fsnotify" - packages = ["."] - revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" - version = "v1.4.7" - -[[projects]] - name = "github.com/go-kit/kit" - packages = [ - "log", - "log/level", - "log/term", - "metrics", - "metrics/discard", - "metrics/internal/lv", - "metrics/prometheus" - ] - revision = "4dc7be5d2d12881735283bcab7352178e190fc71" - version = "v0.6.0" - -[[projects]] - name = "github.com/go-logfmt/logfmt" - packages = ["."] - revision = "390ab7935ee28ec6b286364bba9b4dd6410cb3d5" - version = "v0.3.0" - -[[projects]] - name = "github.com/go-stack/stack" - packages = ["."] - revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc" - version = "v1.7.0" - -[[projects]] - name = "github.com/gogo/protobuf" - packages = [ - "gogoproto", - "jsonpb", - "proto", - "protoc-gen-gogo/descriptor", - "sortkeys", - "types" - ] - revision = "1adfc126b41513cc696b209667c8656ea7aac67c" - version = "v1.0.0" - -[[projects]] - name = "github.com/golang/protobuf" - packages = [ - "proto", - "ptypes", - "ptypes/any", - "ptypes/duration", - "ptypes/timestamp" - ] - revision = "925541529c1fa6821df4e44ce2723319eb2be768" - version = "v1.0.0" - -[[projects]] - branch = "master" - name = "github.com/golang/snappy" - packages = ["."] - revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a" - -[[projects]] - name = "github.com/gorilla/context" - packages = ["."] - revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42" - version = "v1.1.1" - -[[projects]] - name = "github.com/gorilla/mux" - packages = ["."] - revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf" - version = "v1.6.2" - -[[projects]] - name = "github.com/gorilla/websocket" - packages = ["."] - revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b" - version = "v1.2.0" - -[[projects]] - branch = "master" - name = "github.com/hashicorp/hcl" - packages = [ - ".", - "hcl/ast", - "hcl/parser", - "hcl/printer", - "hcl/scanner", - "hcl/strconv", - "hcl/token", - "json/parser", - "json/scanner", - "json/token" - ] - revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168" - -[[projects]] - name = "github.com/inconshreveable/mousetrap" - packages = ["."] - revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" - version = "v1.0" - -[[projects]] - branch = "master" - name = "github.com/jmhodges/levigo" - packages = ["."] - revision = "c42d9e0ca023e2198120196f842701bb4c55d7b9" - -[[projects]] - branch = "master" - name = "github.com/kr/logfmt" - packages = ["."] - revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0" - -[[projects]] - name = "github.com/magiconair/properties" - packages = ["."] - revision = "c2353362d570a7bfa228149c62842019201cfb71" - version = "v1.8.0" - -[[projects]] - name = "github.com/mattn/go-isatty" - packages = ["."] - revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" - version = "v0.0.3" - -[[projects]] - name = "github.com/matttproud/golang_protobuf_extensions" - packages = ["pbutil"] - revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" - version = "v1.0.1" - -[[projects]] - branch = "master" - name = "github.com/mitchellh/mapstructure" - packages = ["."] - revision = "bb74f1db0675b241733089d5a1faa5dd8b0ef57b" - -[[projects]] - name = "github.com/pelletier/go-toml" - packages = ["."] - revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194" - version = "v1.2.0" - -[[projects]] - name = "github.com/pkg/errors" - packages = ["."] - revision = "645ef00459ed84a119197bfb8d8205042c6df63d" - version = "v0.8.0" - -[[projects]] - name = "github.com/pmezard/go-difflib" - packages = ["difflib"] - revision = "792786c7400a136282c1664665ae0a8db921c6c2" - version = "v1.0.0" - -[[projects]] - name = "github.com/prometheus/client_golang" - packages = [ - "prometheus", - "prometheus/promhttp" - ] - revision = "c5b7fccd204277076155f10851dad72b76a49317" - version = "v0.8.0" - -[[projects]] - branch = "master" - name = "github.com/prometheus/client_model" - packages = ["go"] - revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c" - -[[projects]] - branch = "master" - name = "github.com/prometheus/common" - packages = [ - "expfmt", - "internal/bitbucket.org/ww/goautoneg", - "model" - ] - revision = "7600349dcfe1abd18d72d3a1770870d9800a7801" - -[[projects]] - branch = "master" - name = "github.com/prometheus/procfs" - packages = [ - ".", - "internal/util", - "nfs", - "xfs" - ] - revision = "40f013a808ec4fa79def444a1a56de4d1727efcb" - -[[projects]] - branch = "master" - name = "github.com/rcrowley/go-metrics" - packages = ["."] - revision = "e2704e165165ec55d062f5919b4b29494e9fa790" - -[[projects]] - name = "github.com/spf13/afero" - packages = [ - ".", - "mem" - ] - revision = "787d034dfe70e44075ccc060d346146ef53270ad" - version = "v1.1.1" - -[[projects]] - name = "github.com/spf13/cast" - packages = ["."] - revision = "8965335b8c7107321228e3e3702cab9832751bac" - version = "v1.2.0" - -[[projects]] - name = "github.com/spf13/cobra" - packages = ["."] - revision = "7b2c5ac9fc04fc5efafb60700713d4fa609b777b" - version = "v0.0.1" - -[[projects]] - branch = "master" - name = "github.com/spf13/jwalterweatherman" - packages = ["."] - revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" - -[[projects]] - name = "github.com/spf13/pflag" - packages = ["."] - revision = "583c0c0531f06d5278b7d917446061adc344b5cd" - version = "v1.0.1" - -[[projects]] - name = "github.com/spf13/viper" - packages = ["."] - revision = "25b30aa063fc18e48662b86996252eabdcf2f0c7" - version = "v1.0.0" - -[[projects]] - name = "github.com/stretchr/testify" - packages = [ - "assert", - "require" - ] - revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" - version = "v1.2.1" - -[[projects]] - branch = "master" - name = "github.com/syndtr/goleveldb" - packages = [ - "leveldb", - "leveldb/cache", - "leveldb/comparer", - "leveldb/errors", - "leveldb/filter", - "leveldb/iterator", - "leveldb/journal", - "leveldb/memdb", - "leveldb/opt", - "leveldb/storage", - "leveldb/table", - "leveldb/util" - ] - revision = "0d5a0ceb10cf9ab89fdd744cc8c50a83134f6697" - -[[projects]] - branch = "master" - name = "github.com/tendermint/ed25519" - packages = [ - ".", - "edwards25519", - "extra25519" - ] - revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057" - -[[projects]] - name = "github.com/tendermint/go-amino" - packages = ["."] - revision = "2106ca61d91029c931fd54968c2bb02dc96b1412" - version = "0.10.1" - -[[projects]] - name = "github.com/tendermint/iavl" - packages = ["."] - revision = "9e5dc3e61f70b285bb25414452d47aca1ff34c1d" - version = "v0.8.2-rc0" - -[[projects]] - name = "github.com/tendermint/tendermint" - packages = [ - "abci/client", - "abci/example/code", - "abci/example/kvstore", - "abci/server", - "abci/types", - "blockchain", - "cmd/tendermint/commands", - "config", - "consensus", - "consensus/types", - "crypto", - "crypto/merkle", - "crypto/tmhash", - "evidence", - "libs/autofile", - "libs/bech32", - "libs/cli", - "libs/cli/flags", - "libs/clist", - "libs/common", - "libs/db", - "libs/events", - "libs/flowrate", - "libs/log", - "libs/pubsub", - "libs/pubsub/query", - "lite", - "lite/client", - "lite/errors", - "lite/files", - "lite/proxy", - "mempool", - "node", - "p2p", - "p2p/conn", - "p2p/pex", - "p2p/upnp", - "privval", - "proxy", - "rpc/client", - "rpc/core", - "rpc/core/types", - "rpc/grpc", - "rpc/lib", - "rpc/lib/client", - "rpc/lib/server", - "rpc/lib/types", - "state", - "state/txindex", - "state/txindex/kv", - "state/txindex/null", - "types", - "version" - ] - revision = "5923b6288fe8ce9581936ee97c2bf9cf9c02c2f4" - version = "v0.22.0-rc2" - -[[projects]] - name = "github.com/zondax/ledger-goclient" - packages = ["."] - revision = "065cbf938a16f20335c40cfe180f9cd4955c6a5a" - -[[projects]] - branch = "master" - name = "golang.org/x/crypto" - packages = [ - "blowfish", - "curve25519", - "internal/subtle", - "nacl/box", - "nacl/secretbox", - "openpgp/armor", - "openpgp/errors", - "pbkdf2", - "poly1305", - "ripemd160", - "salsa20/salsa" - ] - revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602" - -[[projects]] - branch = "master" - name = "golang.org/x/net" - packages = [ - "context", - "http/httpguts", - "http2", - "http2/hpack", - "idna", - "internal/timeseries", - "netutil", - "trace" - ] - revision = "ed29d75add3d7c4bf7ca65aac0c6df3d1420216f" - -[[projects]] - branch = "master" - name = "golang.org/x/sys" - packages = ["unix"] - revision = "7138fd3d9dc8335c567ca206f4333fb75eb05d56" - -[[projects]] - name = "golang.org/x/text" - packages = [ - "collate", - "collate/build", - "internal/colltab", - "internal/gen", - "internal/tag", - "internal/triegen", - "internal/ucd", - "language", - "secure/bidirule", - "transform", - "unicode/bidi", - "unicode/cldr", - "unicode/norm", - "unicode/rangetable" - ] - revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" - version = "v0.3.0" - -[[projects]] - name = "google.golang.org/genproto" - packages = ["googleapis/rpc/status"] - revision = "7fd901a49ba6a7f87732eb344f6e3c5b19d1b200" - -[[projects]] - name = "google.golang.org/grpc" - packages = [ - ".", - "balancer", - "balancer/base", - "balancer/roundrobin", - "codes", - "connectivity", - "credentials", - "encoding", - "encoding/proto", - "grpclb/grpc_lb_v1/messages", - "grpclog", - "internal", - "keepalive", - "metadata", - "naming", - "peer", - "resolver", - "resolver/dns", - "resolver/passthrough", - "stats", - "status", - "tap", - "transport" - ] - revision = "d11072e7ca9811b1100b80ca0269ac831f06d024" - version = "v1.11.3" - -[[projects]] - name = "gopkg.in/yaml.v2" - packages = ["."] - revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" - version = "v2.2.1" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - inputs-digest = "13ad2a57b6942729e2d08b5c37810d62108aa64a335a4822fcff1ad992c0662b" - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/server/util.go b/server/util.go index d1ad001c5..44b0d95ab 100644 --- a/server/util.go +++ b/server/util.go @@ -135,6 +135,23 @@ func AppendJSON(cdc *wire.Codec, baseJSON []byte, key string, value json.RawMess return json.RawMessage(bz), err } +// SortedJSON takes any JSON and returns it sorted by keys. +// This can be used to sort JSON which will be returned by GetSignBytes, +// e.g. for the ledger integration. +// If the passed JSON isn't valid this will fail. +func SortJSON(toSortJSON []byte) ([]byte, error) { + var c interface{} + err := json.Unmarshal(toSortJSON, &c) + if err != nil { + return nil, err + } + js, err := json.MarshalIndent(c, "", " ") + if err != nil { + return nil, err + } + return js, nil +} + // https://stackoverflow.com/questions/23558425/how-do-i-get-the-local-ip-address-in-go // TODO there must be a better way to get external IP func externalIP() (string, error) { diff --git a/server/util_test.go b/server/util_test.go index 8f1ab21db..a207558f3 100644 --- a/server/util_test.go +++ b/server/util_test.go @@ -38,3 +38,7 @@ func TestAppendJSON(t *testing.T) { require.Equal(t, bar, resBar, "appended: %v", appended) } + +func TestSortJSON(t *testing.T) { + // TODO add testcases of several types +} From c4c1c626c903f808984e2a7c6490ac35232f8b57 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 5 Jul 2018 09:47:04 -0700 Subject: [PATCH 33/53] Add --owk flag to gaiad init --- cmd/gaia/cli_test/cli_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 17c727959..f3452f17a 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -36,7 +36,7 @@ func TestGaiaCLISend(t *testing.T) { tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome)) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass) - chainID := executeInit(t, "gaiad init -o --name=foo --home="+gaiadHome) + chainID := executeInit(t, "gaiad init -o --owk --name=foo --home="+gaiadHome) executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass) // get a free port, also setup some common flags @@ -90,7 +90,7 @@ func TestGaiaCLICreateValidator(t *testing.T) { tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome)) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass) - chainID := executeInit(t, "gaiad init -o --name=foo --home="+gaiadHome) + chainID := executeInit(t, "gaiad init -o --owk --name=foo --home="+gaiadHome) executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass) // get a free port, also setup some common flags @@ -160,7 +160,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) { tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome)) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass) - chainID := executeInit(t, "gaiad init -o --name=foo --home="+gaiadHome) + chainID := executeInit(t, "gaiad init -o --owk --name=foo --home="+gaiadHome) executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass) // get a free port, also setup some common flags From 72aac78a39615bbe8317b836d510188ba13831be Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 5 Jul 2018 09:51:20 -0700 Subject: [PATCH 34/53] Set home-client in gaiad init --- cmd/gaia/cli_test/cli_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index f3452f17a..7f68d11c0 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -36,7 +36,7 @@ func TestGaiaCLISend(t *testing.T) { tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome)) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass) - chainID := executeInit(t, "gaiad init -o --owk --name=foo --home="+gaiadHome) + chainID := executeInit(t, fmt.Sprintf("gaiad init -o --owk --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass) // get a free port, also setup some common flags @@ -90,7 +90,7 @@ func TestGaiaCLICreateValidator(t *testing.T) { tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome)) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass) - chainID := executeInit(t, "gaiad init -o --owk --name=foo --home="+gaiadHome) + chainID := executeInit(t, fmt.Sprintf("gaiad init -o --owk --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass) // get a free port, also setup some common flags @@ -160,7 +160,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) { tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome)) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass) - chainID := executeInit(t, "gaiad init -o --owk --name=foo --home="+gaiadHome) + chainID := executeInit(t, fmt.Sprintf("gaiad init -o --owk --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass) // get a free port, also setup some common flags From 23414868a11b00c3e29ecf8d288ca142a117943b Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 5 Jul 2018 10:14:12 -0700 Subject: [PATCH 35/53] Remove --owk flag --- cmd/gaia/cli_test/cli_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 7f68d11c0..0761bd08f 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -36,7 +36,7 @@ func TestGaiaCLISend(t *testing.T) { tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome)) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass) - chainID := executeInit(t, fmt.Sprintf("gaiad init -o --owk --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) + chainID := executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass) // get a free port, also setup some common flags @@ -90,7 +90,7 @@ func TestGaiaCLICreateValidator(t *testing.T) { tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome)) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass) - chainID := executeInit(t, fmt.Sprintf("gaiad init -o --owk --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) + chainID := executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass) // get a free port, also setup some common flags @@ -160,7 +160,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) { tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome)) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass) - chainID := executeInit(t, fmt.Sprintf("gaiad init -o --owk --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) + chainID := executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass) // get a free port, also setup some common flags From 97182dce21229d12c7191926829066856b6b655e Mon Sep 17 00:00:00 2001 From: Liamsi Date: Thu, 5 Jul 2018 19:09:08 +0100 Subject: [PATCH 36/53] Add test-cases, remove indentation --- server/util.go | 9 +++++---- server/util_test.go | 29 ++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/server/util.go b/server/util.go index 44b0d95ab..c77222bfe 100644 --- a/server/util.go +++ b/server/util.go @@ -135,17 +135,18 @@ func AppendJSON(cdc *wire.Codec, baseJSON []byte, key string, value json.RawMess return json.RawMessage(bz), err } -// SortedJSON takes any JSON and returns it sorted by keys. -// This can be used to sort JSON which will be returned by GetSignBytes, +// SortedJSON takes any JSON and returns it sorted by keys. Also, all white-spaces +// are removed. +// This method can be used to canonicalize JSON to be returned by GetSignBytes, // e.g. for the ledger integration. -// If the passed JSON isn't valid this will fail. +// If the passed JSON isn't valid it will return an error. func SortJSON(toSortJSON []byte) ([]byte, error) { var c interface{} err := json.Unmarshal(toSortJSON, &c) if err != nil { return nil, err } - js, err := json.MarshalIndent(c, "", " ") + js, err := json.Marshal(c) if err != nil { return nil, err } diff --git a/server/util_test.go b/server/util_test.go index a207558f3..301215e1a 100644 --- a/server/util_test.go +++ b/server/util_test.go @@ -40,5 +40,32 @@ func TestAppendJSON(t *testing.T) { } func TestSortJSON(t *testing.T) { - // TODO add testcases of several types + cases := []struct { + unsortedJson string + want string + wantErr bool + }{ + // simple case + {unsortedJson: `{"cosmos":"foo", "atom":"bar", "tendermint":"foobar"}`, + want: `{"atom":"bar","cosmos":"foo","tendermint":"foobar"}`, wantErr: false}, + // failing case (invalid JSON): + {unsortedJson: `"cosmos":"foo",,,, "atom":"bar", "tendermint":"foobar"}`, + want: "", wantErr: true}, + // genesis.json + {unsortedJson: `{"consensus_params":{"block_size_params":{"max_bytes":22020096,"max_txs":100000,"max_gas":-1},"tx_size_params":{"max_bytes":10240,"max_gas":-1},"block_gossip_params":{"block_part_size_bytes":65536},"evidence_params":{"max_age":100000}},"validators":[{"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="},"power":100,"name":""}],"app_hash":"","genesis_time":"2018-05-11T15:52:25.424795506Z","chain_id":"test-chain-Q6VeoW","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"denom":"Token","amount":1000},{"denom":"steak","amount":50}]}],"stake":{"pool":{"total_supply":50,"bonded_shares":"0","unbonded_shares":"0","bonded_pool":0,"unbonded_pool":0,"inflation_last_time":0,"inflation":"7/100"},"params":{"inflation_rate_change":"13/100","inflation_max":"1/5","inflation_min":"7/100","goal_bonded":"67/100","max_validators":100,"bond_denom":"steak"},"candidates":null,"bonds":null}}}`, + want: `{"app_hash":"","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"amount":1000,"denom":"Token"},{"amount":50,"denom":"steak"}]}],"stake":{"bonds":null,"candidates":null,"params":{"bond_denom":"steak","goal_bonded":"67/100","inflation_max":"1/5","inflation_min":"7/100","inflation_rate_change":"13/100","max_validators":100},"pool":{"bonded_pool":0,"bonded_shares":"0","inflation":"7/100","inflation_last_time":0,"total_supply":50,"unbonded_pool":0,"unbonded_shares":"0"}}},"chain_id":"test-chain-Q6VeoW","consensus_params":{"block_gossip_params":{"block_part_size_bytes":65536},"block_size_params":{"max_bytes":22020096,"max_gas":-1,"max_txs":100000},"evidence_params":{"max_age":100000},"tx_size_params":{"max_bytes":10240,"max_gas":-1}},"genesis_time":"2018-05-11T15:52:25.424795506Z","validators":[{"name":"","power":100,"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="}}]}`, + wantErr: false}, + // from the TXSpec: + {unsortedJson: `{"chain_id":"test-chain-1","sequence":1,"fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"alt_bytes":null}`, + want: `{"alt_bytes":null,"chain_id":"test-chain-1","fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"sequence":1}`, + wantErr: false}, + } + + for _, tc := range cases { + got, err := SortJSON([]byte(tc.unsortedJson)) + if tc.wantErr != (err != nil) { + t.Fatalf("got %t, want: %t, err=%s", err != nil, tc.wantErr, err) + } + require.Equal(t, string(got), tc.want) + } } From 51fdc9db2f9cd4c2b7edcf5f45a7910f321abce7 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Thu, 5 Jul 2018 14:07:03 -0400 Subject: [PATCH 37/53] Merge pull request #1559: Inconsistent Genesis Generation Key Order --- examples/democoin/cmd/democoind/main.go | 8 ++++++-- server/init.go | 26 +++++++------------------ server/util.go | 14 +++++++++---- server/util_test.go | 4 ++-- 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/examples/democoin/cmd/democoind/main.go b/examples/democoin/cmd/democoind/main.go index 0bb84c146..e74b3b700 100644 --- a/examples/democoin/cmd/democoind/main.go +++ b/examples/democoin/cmd/democoind/main.go @@ -29,20 +29,24 @@ func CoolAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (appState jso if err != nil { return } + key := "cool" value := json.RawMessage(`{ "trend": "ice-cold" }`) - appState, err = server.AppendJSON(cdc, appState, key, value) + + appState, err = server.InsertKeyJSON(cdc, appState, key, value) if err != nil { return } + key = "pow" value = json.RawMessage(`{ "difficulty": 1, "count": 0 }`) - appState, err = server.AppendJSON(cdc, appState, key, value) + + appState, err = server.InsertKeyJSON(cdc, appState, key, value) return } diff --git a/server/init.go b/server/init.go index 0cc99e79f..3c9186fba 100644 --- a/server/init.go +++ b/server/init.go @@ -332,32 +332,20 @@ func readOrCreatePrivValidator(tmConfig *cfg.Config) crypto.PubKey { return privValidator.GetPubKey() } -// create the genesis file +// writeGenesisFile creates and writes the genesis configuration to disk. An +// error is returned if building or writing the configuration to file fails. func writeGenesisFile(cdc *wire.Codec, genesisFile, chainID string, validators []tmtypes.GenesisValidator, appState json.RawMessage) error { genDoc := tmtypes.GenesisDoc{ - ChainID: chainID, - Validators: validators, + ChainID: chainID, + Validators: validators, + AppStateJSON: appState, } + if err := genDoc.ValidateAndComplete(); err != nil { return err } - if err := genDoc.SaveAs(genesisFile); err != nil { - return err - } - return addAppStateToGenesis(cdc, genesisFile, appState) -} -// Add one line to the genesis file -func addAppStateToGenesis(cdc *wire.Codec, genesisConfigPath string, appState json.RawMessage) error { - bz, err := ioutil.ReadFile(genesisConfigPath) - if err != nil { - return err - } - out, err := AppendJSON(cdc, bz, "app_state", appState) - if err != nil { - return err - } - return ioutil.WriteFile(genesisConfigPath, out, 0600) + return genDoc.SaveAs(genesisFile) } //_____________________________________________________________________ diff --git a/server/util.go b/server/util.go index d1ad001c5..0f1816b16 100644 --- a/server/util.go +++ b/server/util.go @@ -123,15 +123,21 @@ func AddCommands( //___________________________________________________________________________________ -// append a new json field to existing json message -func AppendJSON(cdc *wire.Codec, baseJSON []byte, key string, value json.RawMessage) (appended []byte, err error) { +// InsertKeyJSON inserts a new JSON field/key with a given value to an existing +// JSON message. An error is returned if any serialization operation fails. +// +// NOTE: The ordering of the keys returned as the resulting JSON message is +// non-deterministic, so the client should not rely on key ordering. +func InsertKeyJSON(cdc *wire.Codec, baseJSON []byte, key string, value json.RawMessage) ([]byte, error) { var jsonMap map[string]json.RawMessage - err = cdc.UnmarshalJSON(baseJSON, &jsonMap) - if err != nil { + + if err := cdc.UnmarshalJSON(baseJSON, &jsonMap); err != nil { return nil, err } + jsonMap[key] = value bz, err := wire.MarshalJSONIndent(cdc, jsonMap) + return json.RawMessage(bz), err } diff --git a/server/util_test.go b/server/util_test.go index 8f1ab21db..6082caa2c 100644 --- a/server/util_test.go +++ b/server/util_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestAppendJSON(t *testing.T) { +func TestInsertKeyJSON(t *testing.T) { cdc := wire.NewCodec() foo := map[string]string{"foo": "foofoo"} @@ -24,7 +24,7 @@ func TestAppendJSON(t *testing.T) { barRaw := json.RawMessage(bz) // make the append - appBz, err := AppendJSON(cdc, fooRaw, "barOuter", barRaw) + appBz, err := InsertKeyJSON(cdc, fooRaw, "barOuter", barRaw) require.NoError(t, err) // test the append From 28245dba900b4e67a1e48381341b455d69cbaca1 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Thu, 5 Jul 2018 19:18:48 +0100 Subject: [PATCH 38/53] adhere to golint --- server/util_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/server/util_test.go b/server/util_test.go index 301215e1a..dc4ba75f2 100644 --- a/server/util_test.go +++ b/server/util_test.go @@ -41,28 +41,28 @@ func TestAppendJSON(t *testing.T) { func TestSortJSON(t *testing.T) { cases := []struct { - unsortedJson string + unsortedJSON string want string wantErr bool }{ // simple case - {unsortedJson: `{"cosmos":"foo", "atom":"bar", "tendermint":"foobar"}`, + {unsortedJSON: `{"cosmos":"foo", "atom":"bar", "tendermint":"foobar"}`, want: `{"atom":"bar","cosmos":"foo","tendermint":"foobar"}`, wantErr: false}, // failing case (invalid JSON): - {unsortedJson: `"cosmos":"foo",,,, "atom":"bar", "tendermint":"foobar"}`, + {unsortedJSON: `"cosmos":"foo",,,, "atom":"bar", "tendermint":"foobar"}`, want: "", wantErr: true}, // genesis.json - {unsortedJson: `{"consensus_params":{"block_size_params":{"max_bytes":22020096,"max_txs":100000,"max_gas":-1},"tx_size_params":{"max_bytes":10240,"max_gas":-1},"block_gossip_params":{"block_part_size_bytes":65536},"evidence_params":{"max_age":100000}},"validators":[{"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="},"power":100,"name":""}],"app_hash":"","genesis_time":"2018-05-11T15:52:25.424795506Z","chain_id":"test-chain-Q6VeoW","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"denom":"Token","amount":1000},{"denom":"steak","amount":50}]}],"stake":{"pool":{"total_supply":50,"bonded_shares":"0","unbonded_shares":"0","bonded_pool":0,"unbonded_pool":0,"inflation_last_time":0,"inflation":"7/100"},"params":{"inflation_rate_change":"13/100","inflation_max":"1/5","inflation_min":"7/100","goal_bonded":"67/100","max_validators":100,"bond_denom":"steak"},"candidates":null,"bonds":null}}}`, + {unsortedJSON: `{"consensus_params":{"block_size_params":{"max_bytes":22020096,"max_txs":100000,"max_gas":-1},"tx_size_params":{"max_bytes":10240,"max_gas":-1},"block_gossip_params":{"block_part_size_bytes":65536},"evidence_params":{"max_age":100000}},"validators":[{"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="},"power":100,"name":""}],"app_hash":"","genesis_time":"2018-05-11T15:52:25.424795506Z","chain_id":"test-chain-Q6VeoW","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"denom":"Token","amount":1000},{"denom":"steak","amount":50}]}],"stake":{"pool":{"total_supply":50,"bonded_shares":"0","unbonded_shares":"0","bonded_pool":0,"unbonded_pool":0,"inflation_last_time":0,"inflation":"7/100"},"params":{"inflation_rate_change":"13/100","inflation_max":"1/5","inflation_min":"7/100","goal_bonded":"67/100","max_validators":100,"bond_denom":"steak"},"candidates":null,"bonds":null}}}`, want: `{"app_hash":"","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"amount":1000,"denom":"Token"},{"amount":50,"denom":"steak"}]}],"stake":{"bonds":null,"candidates":null,"params":{"bond_denom":"steak","goal_bonded":"67/100","inflation_max":"1/5","inflation_min":"7/100","inflation_rate_change":"13/100","max_validators":100},"pool":{"bonded_pool":0,"bonded_shares":"0","inflation":"7/100","inflation_last_time":0,"total_supply":50,"unbonded_pool":0,"unbonded_shares":"0"}}},"chain_id":"test-chain-Q6VeoW","consensus_params":{"block_gossip_params":{"block_part_size_bytes":65536},"block_size_params":{"max_bytes":22020096,"max_gas":-1,"max_txs":100000},"evidence_params":{"max_age":100000},"tx_size_params":{"max_bytes":10240,"max_gas":-1}},"genesis_time":"2018-05-11T15:52:25.424795506Z","validators":[{"name":"","power":100,"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="}}]}`, wantErr: false}, // from the TXSpec: - {unsortedJson: `{"chain_id":"test-chain-1","sequence":1,"fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"alt_bytes":null}`, + {unsortedJSON: `{"chain_id":"test-chain-1","sequence":1,"fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"alt_bytes":null}`, want: `{"alt_bytes":null,"chain_id":"test-chain-1","fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"sequence":1}`, wantErr: false}, } for _, tc := range cases { - got, err := SortJSON([]byte(tc.unsortedJson)) + got, err := SortJSON([]byte(tc.unsortedJSON)) if tc.wantErr != (err != nil) { t.Fatalf("got %t, want: %t, err=%s", err != nil, tc.wantErr, err) } From 0f1ceb073e4cd2a1a39b377ca01def9f8a43b0e5 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Fri, 6 Jul 2018 00:23:12 +0100 Subject: [PATCH 39/53] sort all relevant GetSignBytes: - call SortJSON before return JSON bytes to guarantee alphabetic ordering --- x/auth/stdtx.go | 5 +++++ x/bank/msgs.go | 17 +++++++++++++++++ x/bank/msgs_test.go | 4 ++-- x/gov/msgs.go | 13 +++++++++++++ x/stake/types/msg.go | 29 +++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+), 2 deletions(-) diff --git a/x/auth/stdtx.go b/x/auth/stdtx.go index fd55eebb9..566940db7 100644 --- a/x/auth/stdtx.go +++ b/x/auth/stdtx.go @@ -3,6 +3,7 @@ package auth import ( "encoding/json" + "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/tendermint/tendermint/crypto" ) @@ -141,6 +142,10 @@ func StdSignBytes(chainID string, accnum int64, sequence int64, fee StdFee, msgs if err != nil { panic(err) } + bz, err = server.SortJSON(bz) + if err != nil { + panic(err) + } return bz } diff --git a/x/bank/msgs.go b/x/bank/msgs.go index 1a871979e..069ace9ce 100644 --- a/x/bank/msgs.go +++ b/x/bank/msgs.go @@ -3,6 +3,7 @@ package bank import ( "encoding/json" + "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -72,6 +73,10 @@ func (msg MsgSend) GetSignBytes() []byte { if err != nil { panic(err) } + b, err = server.SortJSON(b) + if err != nil { + panic(err) + } return b } @@ -133,6 +138,10 @@ func (msg MsgIssue) GetSignBytes() []byte { if err != nil { panic(err) } + b, err = server.SortJSON(b) + if err != nil { + panic(err) + } return b } @@ -162,6 +171,10 @@ func (in Input) GetSignBytes() []byte { if err != nil { panic(err) } + bin, err = server.SortJSON(bin) + if err != nil { + panic(err) + } return bin } @@ -209,6 +222,10 @@ func (out Output) GetSignBytes() []byte { if err != nil { panic(err) } + bin, err = server.SortJSON(bin) + if err != nil { + panic(err) + } return bin } diff --git a/x/bank/msgs_test.go b/x/bank/msgs_test.go index 3754858ec..f4e7363d3 100644 --- a/x/bank/msgs_test.go +++ b/x/bank/msgs_test.go @@ -187,7 +187,7 @@ func TestMsgSendGetSignBytes(t *testing.T) { } res := msg.GetSignBytes() - expected := `{"inputs":[{"address":"cosmosaccaddr1d9h8qat5e4ehc5","coins":[{"denom":"atom","amount":"10"}]}],"outputs":[{"address":"cosmosaccaddr1da6hgur4wse3jx32","coins":[{"denom":"atom","amount":"10"}]}]}` + expected := `{"inputs":[{"address":"cosmosaccaddr1d9h8qat5e4ehc5","coins":[{"amount":"10","denom":"atom"}]}],"outputs":[{"address":"cosmosaccaddr1da6hgur4wse3jx32","coins":[{"amount":"10","denom":"atom"}]}]}` require.Equal(t, expected, string(res)) } @@ -257,7 +257,7 @@ func TestMsgIssueGetSignBytes(t *testing.T) { } res := msg.GetSignBytes() - expected := `{"banker":"cosmosaccaddr1d9h8qat5e4ehc5","outputs":[{"address":"cosmosaccaddr1d3hkzm3dveex7mfdvfsku6cwsauqd","coins":[{"denom":"atom","amount":"10"}]}]}` + expected := `{"banker":"cosmosaccaddr1d9h8qat5e4ehc5","outputs":[{"address":"cosmosaccaddr1d3hkzm3dveex7mfdvfsku6cwsauqd","coins":[{"amount":"10","denom":"atom"}]}]}` require.Equal(t, expected, string(res)) } diff --git a/x/gov/msgs.go b/x/gov/msgs.go index f436d024b..afe7084c4 100644 --- a/x/gov/msgs.go +++ b/x/gov/msgs.go @@ -3,6 +3,7 @@ package gov import ( "fmt" + "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -82,6 +83,10 @@ func (msg MsgSubmitProposal) GetSignBytes() []byte { if err != nil { panic(err) } + b, err = server.SortJSON(b) + if err != nil { + panic(err) + } return b } @@ -149,6 +154,10 @@ func (msg MsgDeposit) GetSignBytes() []byte { if err != nil { panic(err) } + b, err = server.SortJSON(b) + if err != nil { + panic(err) + } return b } @@ -213,6 +222,10 @@ func (msg MsgVote) GetSignBytes() []byte { if err != nil { panic(err) } + b, err = server.SortJSON(b) + if err != nil { + panic(err) + } return b } diff --git a/x/stake/types/msg.go b/x/stake/types/msg.go index 878c1ba17..609935fb0 100644 --- a/x/stake/types/msg.go +++ b/x/stake/types/msg.go @@ -3,6 +3,7 @@ package types import ( "math" + "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/tendermint/tendermint/crypto" ) @@ -63,6 +64,10 @@ func (msg MsgCreateValidator) GetSignBytes() []byte { if err != nil { panic(err) } + b, err = server.SortJSON(b) + if err != nil { + panic(err) + } return b } @@ -114,6 +119,10 @@ func (msg MsgEditValidator) GetSignBytes() []byte { if err != nil { panic(err) } + b, err = server.SortJSON(b) + if err != nil { + panic(err) + } return b } @@ -166,6 +175,10 @@ func (msg MsgDelegate) GetSignBytes() []byte { if err != nil { panic(err) } + b, err = server.SortJSON(b) + if err != nil { + panic(err) + } return b } @@ -226,6 +239,10 @@ func (msg MsgBeginRedelegate) GetSignBytes() []byte { if err != nil { panic(err) } + b, err = server.SortJSON(b) + if err != nil { + panic(err) + } return b } @@ -286,6 +303,10 @@ func (msg MsgCompleteRedelegate) GetSignBytes() []byte { if err != nil { panic(err) } + b, err = server.SortJSON(b) + if err != nil { + panic(err) + } return b } @@ -338,6 +359,10 @@ func (msg MsgBeginUnbonding) GetSignBytes() []byte { if err != nil { panic(err) } + b, err = server.SortJSON(b) + if err != nil { + panic(err) + } return b } @@ -387,6 +412,10 @@ func (msg MsgCompleteUnbonding) GetSignBytes() []byte { if err != nil { panic(err) } + b, err = server.SortJSON(b) + if err != nil { + panic(err) + } return b } From 66fdb9585b7903ba1c9003d495b54da5858809bf Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 6 Jul 2018 02:09:33 +0200 Subject: [PATCH 40/53] Gopkg.lock & 'make format' --- Gopkg.lock | 512 ++++++++++++++++++++++++++++++++++++++++++++ server/util_test.go | 2 +- 2 files changed, 513 insertions(+), 1 deletion(-) create mode 100644 Gopkg.lock diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 000000000..879453988 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,512 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/bartekn/go-bip39" + packages = ["."] + revision = "a05967ea095d81c8fe4833776774cfaff8e5036c" + +[[projects]] + branch = "master" + name = "github.com/beorn7/perks" + packages = ["quantile"] + revision = "3a771d992973f24aa725d07868b467d1ddfceafb" + +[[projects]] + name = "github.com/bgentry/speakeasy" + packages = ["."] + revision = "4aabc24848ce5fd31929f7d1e4ea74d3709c14cd" + version = "v0.1.0" + +[[projects]] + branch = "master" + name = "github.com/brejski/hid" + packages = ["."] + revision = "06112dcfcc50a7e0e4fd06e17f9791e788fdaafc" + +[[projects]] + branch = "master" + name = "github.com/btcsuite/btcd" + packages = ["btcec"] + revision = "86fed781132ac890ee03e906e4ecd5d6fa180c64" + +[[projects]] + branch = "master" + name = "github.com/btcsuite/btcutil" + packages = ["bech32"] + revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + branch = "master" + name = "github.com/ebuchman/fail-test" + packages = ["."] + revision = "95f809107225be108efcf10a3509e4ea6ceef3c4" + +[[projects]] + name = "github.com/fsnotify/fsnotify" + packages = ["."] + revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" + version = "v1.4.7" + +[[projects]] + name = "github.com/go-kit/kit" + packages = [ + "log", + "log/level", + "log/term", + "metrics", + "metrics/discard", + "metrics/internal/lv", + "metrics/prometheus" + ] + revision = "4dc7be5d2d12881735283bcab7352178e190fc71" + version = "v0.6.0" + +[[projects]] + name = "github.com/go-logfmt/logfmt" + packages = ["."] + revision = "390ab7935ee28ec6b286364bba9b4dd6410cb3d5" + version = "v0.3.0" + +[[projects]] + name = "github.com/go-stack/stack" + packages = ["."] + revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc" + version = "v1.7.0" + +[[projects]] + name = "github.com/gogo/protobuf" + packages = [ + "gogoproto", + "jsonpb", + "proto", + "protoc-gen-gogo/descriptor", + "sortkeys", + "types" + ] + revision = "1adfc126b41513cc696b209667c8656ea7aac67c" + version = "v1.0.0" + +[[projects]] + name = "github.com/golang/protobuf" + packages = [ + "proto", + "ptypes", + "ptypes/any", + "ptypes/duration", + "ptypes/timestamp" + ] + revision = "925541529c1fa6821df4e44ce2723319eb2be768" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/golang/snappy" + packages = ["."] + revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a" + +[[projects]] + name = "github.com/gorilla/context" + packages = ["."] + revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42" + version = "v1.1.1" + +[[projects]] + name = "github.com/gorilla/mux" + packages = ["."] + revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf" + version = "v1.6.2" + +[[projects]] + name = "github.com/gorilla/websocket" + packages = ["."] + revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b" + version = "v1.2.0" + +[[projects]] + branch = "master" + name = "github.com/hashicorp/hcl" + packages = [ + ".", + "hcl/ast", + "hcl/parser", + "hcl/printer", + "hcl/scanner", + "hcl/strconv", + "hcl/token", + "json/parser", + "json/scanner", + "json/token" + ] + revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168" + +[[projects]] + name = "github.com/inconshreveable/mousetrap" + packages = ["."] + revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" + version = "v1.0" + +[[projects]] + branch = "master" + name = "github.com/jmhodges/levigo" + packages = ["."] + revision = "c42d9e0ca023e2198120196f842701bb4c55d7b9" + +[[projects]] + branch = "master" + name = "github.com/kr/logfmt" + packages = ["."] + revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0" + +[[projects]] + name = "github.com/magiconair/properties" + packages = ["."] + revision = "c2353362d570a7bfa228149c62842019201cfb71" + version = "v1.8.0" + +[[projects]] + name = "github.com/mattn/go-isatty" + packages = ["."] + revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" + version = "v0.0.3" + +[[projects]] + name = "github.com/matttproud/golang_protobuf_extensions" + packages = ["pbutil"] + revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" + version = "v1.0.1" + +[[projects]] + branch = "master" + name = "github.com/mitchellh/mapstructure" + packages = ["."] + revision = "bb74f1db0675b241733089d5a1faa5dd8b0ef57b" + +[[projects]] + name = "github.com/pelletier/go-toml" + packages = ["."] + revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194" + version = "v1.2.0" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "645ef00459ed84a119197bfb8d8205042c6df63d" + version = "v0.8.0" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + name = "github.com/prometheus/client_golang" + packages = [ + "prometheus", + "prometheus/promhttp" + ] + revision = "c5b7fccd204277076155f10851dad72b76a49317" + version = "v0.8.0" + +[[projects]] + branch = "master" + name = "github.com/prometheus/client_model" + packages = ["go"] + revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c" + +[[projects]] + branch = "master" + name = "github.com/prometheus/common" + packages = [ + "expfmt", + "internal/bitbucket.org/ww/goautoneg", + "model" + ] + revision = "7600349dcfe1abd18d72d3a1770870d9800a7801" + +[[projects]] + branch = "master" + name = "github.com/prometheus/procfs" + packages = [ + ".", + "internal/util", + "nfs", + "xfs" + ] + revision = "ae68e2d4c00fed4943b5f6698d504a5fe083da8a" + +[[projects]] + branch = "master" + name = "github.com/rcrowley/go-metrics" + packages = ["."] + revision = "e2704e165165ec55d062f5919b4b29494e9fa790" + +[[projects]] + name = "github.com/spf13/afero" + packages = [ + ".", + "mem" + ] + revision = "787d034dfe70e44075ccc060d346146ef53270ad" + version = "v1.1.1" + +[[projects]] + name = "github.com/spf13/cast" + packages = ["."] + revision = "8965335b8c7107321228e3e3702cab9832751bac" + version = "v1.2.0" + +[[projects]] + name = "github.com/spf13/cobra" + packages = ["."] + revision = "7b2c5ac9fc04fc5efafb60700713d4fa609b777b" + version = "v0.0.1" + +[[projects]] + branch = "master" + name = "github.com/spf13/jwalterweatherman" + packages = ["."] + revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" + +[[projects]] + name = "github.com/spf13/pflag" + packages = ["."] + revision = "583c0c0531f06d5278b7d917446061adc344b5cd" + version = "v1.0.1" + +[[projects]] + name = "github.com/spf13/viper" + packages = ["."] + revision = "25b30aa063fc18e48662b86996252eabdcf2f0c7" + version = "v1.0.0" + +[[projects]] + name = "github.com/stretchr/testify" + packages = [ + "assert", + "require" + ] + revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" + version = "v1.2.1" + +[[projects]] + branch = "master" + name = "github.com/syndtr/goleveldb" + packages = [ + "leveldb", + "leveldb/cache", + "leveldb/comparer", + "leveldb/errors", + "leveldb/filter", + "leveldb/iterator", + "leveldb/journal", + "leveldb/memdb", + "leveldb/opt", + "leveldb/storage", + "leveldb/table", + "leveldb/util" + ] + revision = "0d5a0ceb10cf9ab89fdd744cc8c50a83134f6697" + +[[projects]] + branch = "master" + name = "github.com/tendermint/ed25519" + packages = [ + ".", + "edwards25519", + "extra25519" + ] + revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057" + +[[projects]] + name = "github.com/tendermint/go-amino" + packages = ["."] + revision = "2106ca61d91029c931fd54968c2bb02dc96b1412" + version = "0.10.1" + +[[projects]] + name = "github.com/tendermint/iavl" + packages = ["."] + revision = "9e5dc3e61f70b285bb25414452d47aca1ff34c1d" + version = "v0.8.2-rc0" + +[[projects]] + name = "github.com/tendermint/tendermint" + packages = [ + "abci/client", + "abci/example/code", + "abci/example/kvstore", + "abci/server", + "abci/types", + "blockchain", + "cmd/tendermint/commands", + "config", + "consensus", + "consensus/types", + "crypto", + "crypto/merkle", + "crypto/tmhash", + "evidence", + "libs/autofile", + "libs/bech32", + "libs/cli", + "libs/cli/flags", + "libs/clist", + "libs/common", + "libs/db", + "libs/events", + "libs/flowrate", + "libs/log", + "libs/pubsub", + "libs/pubsub/query", + "lite", + "lite/client", + "lite/errors", + "lite/files", + "lite/proxy", + "mempool", + "node", + "p2p", + "p2p/conn", + "p2p/pex", + "p2p/upnp", + "privval", + "proxy", + "rpc/client", + "rpc/core", + "rpc/core/types", + "rpc/grpc", + "rpc/lib", + "rpc/lib/client", + "rpc/lib/server", + "rpc/lib/types", + "state", + "state/txindex", + "state/txindex/kv", + "state/txindex/null", + "types", + "version" + ] + revision = "5923b6288fe8ce9581936ee97c2bf9cf9c02c2f4" + version = "v0.22.0-rc2" + +[[projects]] + name = "github.com/zondax/ledger-goclient" + packages = ["."] + revision = "065cbf938a16f20335c40cfe180f9cd4955c6a5a" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = [ + "blowfish", + "curve25519", + "internal/subtle", + "nacl/box", + "nacl/secretbox", + "openpgp/armor", + "openpgp/errors", + "pbkdf2", + "poly1305", + "ripemd160", + "salsa20/salsa" + ] + revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = [ + "context", + "http/httpguts", + "http2", + "http2/hpack", + "idna", + "internal/timeseries", + "netutil", + "trace" + ] + revision = "ed29d75add3d7c4bf7ca65aac0c6df3d1420216f" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["unix"] + revision = "151529c776cdc58ddbe7963ba9af779f3577b419" + +[[projects]] + name = "golang.org/x/text" + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable" + ] + revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" + version = "v0.3.0" + +[[projects]] + name = "google.golang.org/genproto" + packages = ["googleapis/rpc/status"] + revision = "7fd901a49ba6a7f87732eb344f6e3c5b19d1b200" + +[[projects]] + name = "google.golang.org/grpc" + packages = [ + ".", + "balancer", + "balancer/base", + "balancer/roundrobin", + "codes", + "connectivity", + "credentials", + "encoding", + "encoding/proto", + "grpclb/grpc_lb_v1/messages", + "grpclog", + "internal", + "keepalive", + "metadata", + "naming", + "peer", + "resolver", + "resolver/dns", + "resolver/passthrough", + "stats", + "status", + "tap", + "transport" + ] + revision = "d11072e7ca9811b1100b80ca0269ac831f06d024" + version = "v1.11.3" + +[[projects]] + name = "gopkg.in/yaml.v2" + packages = ["."] + revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" + version = "v2.2.1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "13ad2a57b6942729e2d08b5c37810d62108aa64a335a4822fcff1ad992c0662b" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/server/util_test.go b/server/util_test.go index 69910d26a..09e66ab4a 100644 --- a/server/util_test.go +++ b/server/util_test.go @@ -53,7 +53,7 @@ func TestSortJSON(t *testing.T) { want: "", wantErr: true}, // genesis.json {unsortedJSON: `{"consensus_params":{"block_size_params":{"max_bytes":22020096,"max_txs":100000,"max_gas":-1},"tx_size_params":{"max_bytes":10240,"max_gas":-1},"block_gossip_params":{"block_part_size_bytes":65536},"evidence_params":{"max_age":100000}},"validators":[{"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="},"power":100,"name":""}],"app_hash":"","genesis_time":"2018-05-11T15:52:25.424795506Z","chain_id":"test-chain-Q6VeoW","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"denom":"Token","amount":1000},{"denom":"steak","amount":50}]}],"stake":{"pool":{"total_supply":50,"bonded_shares":"0","unbonded_shares":"0","bonded_pool":0,"unbonded_pool":0,"inflation_last_time":0,"inflation":"7/100"},"params":{"inflation_rate_change":"13/100","inflation_max":"1/5","inflation_min":"7/100","goal_bonded":"67/100","max_validators":100,"bond_denom":"steak"},"candidates":null,"bonds":null}}}`, - want: `{"app_hash":"","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"amount":1000,"denom":"Token"},{"amount":50,"denom":"steak"}]}],"stake":{"bonds":null,"candidates":null,"params":{"bond_denom":"steak","goal_bonded":"67/100","inflation_max":"1/5","inflation_min":"7/100","inflation_rate_change":"13/100","max_validators":100},"pool":{"bonded_pool":0,"bonded_shares":"0","inflation":"7/100","inflation_last_time":0,"total_supply":50,"unbonded_pool":0,"unbonded_shares":"0"}}},"chain_id":"test-chain-Q6VeoW","consensus_params":{"block_gossip_params":{"block_part_size_bytes":65536},"block_size_params":{"max_bytes":22020096,"max_gas":-1,"max_txs":100000},"evidence_params":{"max_age":100000},"tx_size_params":{"max_bytes":10240,"max_gas":-1}},"genesis_time":"2018-05-11T15:52:25.424795506Z","validators":[{"name":"","power":100,"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="}}]}`, + want: `{"app_hash":"","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"amount":1000,"denom":"Token"},{"amount":50,"denom":"steak"}]}],"stake":{"bonds":null,"candidates":null,"params":{"bond_denom":"steak","goal_bonded":"67/100","inflation_max":"1/5","inflation_min":"7/100","inflation_rate_change":"13/100","max_validators":100},"pool":{"bonded_pool":0,"bonded_shares":"0","inflation":"7/100","inflation_last_time":0,"total_supply":50,"unbonded_pool":0,"unbonded_shares":"0"}}},"chain_id":"test-chain-Q6VeoW","consensus_params":{"block_gossip_params":{"block_part_size_bytes":65536},"block_size_params":{"max_bytes":22020096,"max_gas":-1,"max_txs":100000},"evidence_params":{"max_age":100000},"tx_size_params":{"max_bytes":10240,"max_gas":-1}},"genesis_time":"2018-05-11T15:52:25.424795506Z","validators":[{"name":"","power":100,"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="}}]}`, wantErr: false}, // from the TXSpec: {unsortedJSON: `{"chain_id":"test-chain-1","sequence":1,"fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"alt_bytes":null}`, From b7f902fba5fcb367d82a2dd9e59600e91d2dfc72 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Fri, 6 Jul 2018 01:09:23 +0100 Subject: [PATCH 41/53] sort *all* GetSignBytes: - call MustSortJSON before return JSON bytes to guarantee alphabetic ordering - moved SortJSON and MustSortJSON to types package to avoid cyclic package dep --- baseapp/baseapp_test.go | 4 +-- docs/core/examples/app1.go | 2 +- docs/core/examples/app2.go | 2 +- examples/democoin/x/cool/types.go | 4 +-- examples/democoin/x/oracle/types.go | 2 +- examples/democoin/x/pow/types.go | 2 +- examples/democoin/x/pow/types_test.go | 2 +- examples/democoin/x/simplestake/msgs.go | 2 +- examples/kvstore/tx.go | 2 +- server/util.go | 18 ----------- server/util_test.go | 31 ------------------ types/tx_msg.go | 2 +- types/utils.go | 31 ++++++++++++++++++ types/utils_test.go | 39 ++++++++++++++++++++++ x/auth/stdtx.go | 7 +--- x/bank/msgs.go | 25 +++----------- x/gov/msgs.go | 19 ++--------- x/ibc/types.go | 4 +-- x/slashing/msg.go | 2 +- x/stake/types/msg.go | 43 ++++--------------------- 20 files changed, 100 insertions(+), 143 deletions(-) create mode 100644 types/utils.go create mode 100644 types/utils_test.go diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index e919375d9..b8c42c4d2 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -662,7 +662,7 @@ const msgType3 = "burn" func (msg testBurnMsg) Type() string { return msgType3 } func (msg testBurnMsg) GetSignBytes() []byte { bz, _ := json.Marshal(msg) - return bz + return sdk.MustSortJSON(bz) } func (msg testBurnMsg) ValidateBasic() sdk.Error { if msg.Addr == nil { @@ -685,7 +685,7 @@ const msgType4 = "send" func (msg testSendMsg) Type() string { return msgType4 } func (msg testSendMsg) GetSignBytes() []byte { bz, _ := json.Marshal(msg) - return bz + return sdk.MustSortJSON(bz) } func (msg testSendMsg) ValidateBasic() sdk.Error { if msg.Sender == nil || msg.Receiver == nil { diff --git a/docs/core/examples/app1.go b/docs/core/examples/app1.go index f9eceecdb..a9580fcc2 100644 --- a/docs/core/examples/app1.go +++ b/docs/core/examples/app1.go @@ -85,7 +85,7 @@ func (msg MsgSend) GetSignBytes() []byte { if err != nil { panic(err) } - return bz + return sdk.MustSortJSON(bz) } // Implements Msg. Return the signer. diff --git a/docs/core/examples/app2.go b/docs/core/examples/app2.go index b4d44dca7..c96a1022f 100644 --- a/docs/core/examples/app2.go +++ b/docs/core/examples/app2.go @@ -100,7 +100,7 @@ func (msg MsgIssue) GetSignBytes() []byte { if err != nil { panic(err) } - return bz + return sdk.MustSortJSON(bz) } // Implements Msg. Return the signer. diff --git a/examples/democoin/x/cool/types.go b/examples/democoin/x/cool/types.go index 77f49a0ba..82c9286c6 100644 --- a/examples/democoin/x/cool/types.go +++ b/examples/democoin/x/cool/types.go @@ -58,7 +58,7 @@ func (msg MsgSetTrend) GetSignBytes() []byte { if err != nil { panic(err) } - return b + return sdk.MustSortJSON(b) } //_______________________________________________________________________ @@ -102,5 +102,5 @@ func (msg MsgQuiz) GetSignBytes() []byte { if err != nil { panic(err) } - return b + return sdk.MustSortJSON(b) } diff --git a/examples/democoin/x/oracle/types.go b/examples/democoin/x/oracle/types.go index 041b9ab34..d06f47a4e 100644 --- a/examples/democoin/x/oracle/types.go +++ b/examples/democoin/x/oracle/types.go @@ -18,7 +18,7 @@ func (msg Msg) GetSignBytes() []byte { if err != nil { panic(err) } - return bz + return sdk.MustSortJSON(bz) } // GetSigners implements sdk.Msg diff --git a/examples/democoin/x/pow/types.go b/examples/democoin/x/pow/types.go index cd77a68af..3529917dc 100644 --- a/examples/democoin/x/pow/types.go +++ b/examples/democoin/x/pow/types.go @@ -76,5 +76,5 @@ func (msg MsgMine) GetSignBytes() []byte { if err != nil { panic(err) } - return b + return sdk.MustSortJSON(b) } diff --git a/examples/democoin/x/pow/types_test.go b/examples/democoin/x/pow/types_test.go index 9ed5dc102..1291cb96a 100644 --- a/examples/democoin/x/pow/types_test.go +++ b/examples/democoin/x/pow/types_test.go @@ -62,7 +62,7 @@ func TestMsgMineGetSignBytes(t *testing.T) { addr := sdk.Address([]byte("sender")) msg := MsgMine{addr, 1, 1, 1, []byte("abc")} res := msg.GetSignBytes() - require.Equal(t, string(res), `{"sender":"73656E646572","difficulty":1,"count":1,"nonce":1,"proof":"YWJj"}`) + require.Equal(t, string(res), `{"count":1,"difficulty":1,"nonce":1,"proof":"YWJj","sender":"73656E646572"}`) } func TestMsgMineGetSigners(t *testing.T) { diff --git a/examples/democoin/x/simplestake/msgs.go b/examples/democoin/x/simplestake/msgs.go index 564e0d979..91729e3ef 100644 --- a/examples/democoin/x/simplestake/msgs.go +++ b/examples/democoin/x/simplestake/msgs.go @@ -48,7 +48,7 @@ func (msg MsgBond) GetSignBytes() []byte { if err != nil { panic(err) } - return bz + return sdk.MustSortJSON(bz) } //_______________________________________________________________ diff --git a/examples/kvstore/tx.go b/examples/kvstore/tx.go index 0e94ace28..e1c5cab3a 100644 --- a/examples/kvstore/tx.go +++ b/examples/kvstore/tx.go @@ -27,7 +27,7 @@ func (tx kvstoreTx) GetMemo() string { } func (tx kvstoreTx) GetSignBytes() []byte { - return tx.bytes + return sdk.MustSortJSON(tx.bytes) } // Should the app be calling this? Or only handlers? diff --git a/server/util.go b/server/util.go index c77222bfe..d1ad001c5 100644 --- a/server/util.go +++ b/server/util.go @@ -135,24 +135,6 @@ func AppendJSON(cdc *wire.Codec, baseJSON []byte, key string, value json.RawMess return json.RawMessage(bz), err } -// SortedJSON takes any JSON and returns it sorted by keys. Also, all white-spaces -// are removed. -// This method can be used to canonicalize JSON to be returned by GetSignBytes, -// e.g. for the ledger integration. -// If the passed JSON isn't valid it will return an error. -func SortJSON(toSortJSON []byte) ([]byte, error) { - var c interface{} - err := json.Unmarshal(toSortJSON, &c) - if err != nil { - return nil, err - } - js, err := json.Marshal(c) - if err != nil { - return nil, err - } - return js, nil -} - // https://stackoverflow.com/questions/23558425/how-do-i-get-the-local-ip-address-in-go // TODO there must be a better way to get external IP func externalIP() (string, error) { diff --git a/server/util_test.go b/server/util_test.go index dc4ba75f2..8f1ab21db 100644 --- a/server/util_test.go +++ b/server/util_test.go @@ -38,34 +38,3 @@ func TestAppendJSON(t *testing.T) { require.Equal(t, bar, resBar, "appended: %v", appended) } - -func TestSortJSON(t *testing.T) { - cases := []struct { - unsortedJSON string - want string - wantErr bool - }{ - // simple case - {unsortedJSON: `{"cosmos":"foo", "atom":"bar", "tendermint":"foobar"}`, - want: `{"atom":"bar","cosmos":"foo","tendermint":"foobar"}`, wantErr: false}, - // failing case (invalid JSON): - {unsortedJSON: `"cosmos":"foo",,,, "atom":"bar", "tendermint":"foobar"}`, - want: "", wantErr: true}, - // genesis.json - {unsortedJSON: `{"consensus_params":{"block_size_params":{"max_bytes":22020096,"max_txs":100000,"max_gas":-1},"tx_size_params":{"max_bytes":10240,"max_gas":-1},"block_gossip_params":{"block_part_size_bytes":65536},"evidence_params":{"max_age":100000}},"validators":[{"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="},"power":100,"name":""}],"app_hash":"","genesis_time":"2018-05-11T15:52:25.424795506Z","chain_id":"test-chain-Q6VeoW","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"denom":"Token","amount":1000},{"denom":"steak","amount":50}]}],"stake":{"pool":{"total_supply":50,"bonded_shares":"0","unbonded_shares":"0","bonded_pool":0,"unbonded_pool":0,"inflation_last_time":0,"inflation":"7/100"},"params":{"inflation_rate_change":"13/100","inflation_max":"1/5","inflation_min":"7/100","goal_bonded":"67/100","max_validators":100,"bond_denom":"steak"},"candidates":null,"bonds":null}}}`, - want: `{"app_hash":"","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"amount":1000,"denom":"Token"},{"amount":50,"denom":"steak"}]}],"stake":{"bonds":null,"candidates":null,"params":{"bond_denom":"steak","goal_bonded":"67/100","inflation_max":"1/5","inflation_min":"7/100","inflation_rate_change":"13/100","max_validators":100},"pool":{"bonded_pool":0,"bonded_shares":"0","inflation":"7/100","inflation_last_time":0,"total_supply":50,"unbonded_pool":0,"unbonded_shares":"0"}}},"chain_id":"test-chain-Q6VeoW","consensus_params":{"block_gossip_params":{"block_part_size_bytes":65536},"block_size_params":{"max_bytes":22020096,"max_gas":-1,"max_txs":100000},"evidence_params":{"max_age":100000},"tx_size_params":{"max_bytes":10240,"max_gas":-1}},"genesis_time":"2018-05-11T15:52:25.424795506Z","validators":[{"name":"","power":100,"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="}}]}`, - wantErr: false}, - // from the TXSpec: - {unsortedJSON: `{"chain_id":"test-chain-1","sequence":1,"fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"alt_bytes":null}`, - want: `{"alt_bytes":null,"chain_id":"test-chain-1","fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"sequence":1}`, - wantErr: false}, - } - - for _, tc := range cases { - got, err := SortJSON([]byte(tc.unsortedJSON)) - if tc.wantErr != (err != nil) { - t.Fatalf("got %t, want: %t, err=%s", err != nil, tc.wantErr, err) - } - require.Equal(t, string(got), tc.want) - } -} diff --git a/types/tx_msg.go b/types/tx_msg.go index c1af91df8..fbadfb49d 100644 --- a/types/tx_msg.go +++ b/types/tx_msg.go @@ -60,7 +60,7 @@ func (msg *TestMsg) GetSignBytes() []byte { if err != nil { panic(err) } - return bz + return MustSortJSON(bz) } func (msg *TestMsg) ValidateBasic() Error { return nil } func (msg *TestMsg) GetSigners() []Address { diff --git a/types/utils.go b/types/utils.go new file mode 100644 index 000000000..2e027676a --- /dev/null +++ b/types/utils.go @@ -0,0 +1,31 @@ +package types + +import "encoding/json" + +// SortedJSON takes any JSON and returns it sorted by keys. Also, all white-spaces +// are removed. +// This method can be used to canonicalize JSON to be returned by GetSignBytes, +// e.g. for the ledger integration. +// If the passed JSON isn't valid it will return an error. +func SortJSON(toSortJSON []byte) ([]byte, error) { + var c interface{} + err := json.Unmarshal(toSortJSON, &c) + if err != nil { + return nil, err + } + js, err := json.Marshal(c) + if err != nil { + return nil, err + } + return js, nil +} + +// MustSortJSON is like SortJSON but panic if an error occurs, e.g., if +// the passed JSON isn't valid. +func MustSortJSON(toSortJSON []byte) []byte { + js, err := SortJSON(toSortJSON) + if err != nil { + panic(err) + } + return js +} diff --git a/types/utils_test.go b/types/utils_test.go new file mode 100644 index 000000000..8c84e2ace --- /dev/null +++ b/types/utils_test.go @@ -0,0 +1,39 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSortJSON(t *testing.T) { + cases := []struct { + unsortedJSON string + want string + wantErr bool + }{ + // simple case + {unsortedJSON: `{"cosmos":"foo", "atom":"bar", "tendermint":"foobar"}`, + want: `{"atom":"bar","cosmos":"foo","tendermint":"foobar"}`, wantErr: false}, + // failing case (invalid JSON): + {unsortedJSON: `"cosmos":"foo",,,, "atom":"bar", "tendermint":"foobar"}`, + want: "", + wantErr: true}, + // genesis.json + {unsortedJSON: `{"consensus_params":{"block_size_params":{"max_bytes":22020096,"max_txs":100000,"max_gas":-1},"tx_size_params":{"max_bytes":10240,"max_gas":-1},"block_gossip_params":{"block_part_size_bytes":65536},"evidence_params":{"max_age":100000}},"validators":[{"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="},"power":100,"name":""}],"app_hash":"","genesis_time":"2018-05-11T15:52:25.424795506Z","chain_id":"test-chain-Q6VeoW","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"denom":"Token","amount":1000},{"denom":"steak","amount":50}]}],"stake":{"pool":{"total_supply":50,"bonded_shares":"0","unbonded_shares":"0","bonded_pool":0,"unbonded_pool":0,"inflation_last_time":0,"inflation":"7/100"},"params":{"inflation_rate_change":"13/100","inflation_max":"1/5","inflation_min":"7/100","goal_bonded":"67/100","max_validators":100,"bond_denom":"steak"},"candidates":null,"bonds":null}}}`, + want: `{"app_hash":"","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"amount":1000,"denom":"Token"},{"amount":50,"denom":"steak"}]}],"stake":{"bonds":null,"candidates":null,"params":{"bond_denom":"steak","goal_bonded":"67/100","inflation_max":"1/5","inflation_min":"7/100","inflation_rate_change":"13/100","max_validators":100},"pool":{"bonded_pool":0,"bonded_shares":"0","inflation":"7/100","inflation_last_time":0,"total_supply":50,"unbonded_pool":0,"unbonded_shares":"0"}}},"chain_id":"test-chain-Q6VeoW","consensus_params":{"block_gossip_params":{"block_part_size_bytes":65536},"block_size_params":{"max_bytes":22020096,"max_gas":-1,"max_txs":100000},"evidence_params":{"max_age":100000},"tx_size_params":{"max_bytes":10240,"max_gas":-1}},"genesis_time":"2018-05-11T15:52:25.424795506Z","validators":[{"name":"","power":100,"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="}}]}`, + wantErr: false}, + // from the TXSpec: + {unsortedJSON: `{"chain_id":"test-chain-1","sequence":1,"fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"alt_bytes":null}`, + want: `{"alt_bytes":null,"chain_id":"test-chain-1","fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"sequence":1}`, + wantErr: false}, + } + + for _, tc := range cases { + got, err := SortJSON([]byte(tc.unsortedJSON)) + if tc.wantErr != (err != nil) { + t.Fatalf("got %t, want: %t, err=%s", err != nil, tc.wantErr, err) + } + require.Equal(t, string(got), tc.want) + } +} diff --git a/x/auth/stdtx.go b/x/auth/stdtx.go index 566940db7..960d9855e 100644 --- a/x/auth/stdtx.go +++ b/x/auth/stdtx.go @@ -3,7 +3,6 @@ package auth import ( "encoding/json" - "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/tendermint/tendermint/crypto" ) @@ -142,11 +141,7 @@ func StdSignBytes(chainID string, accnum int64, sequence int64, fee StdFee, msgs if err != nil { panic(err) } - bz, err = server.SortJSON(bz) - if err != nil { - panic(err) - } - return bz + return sdk.MustSortJSON(bz) } // StdSignMsg is a convenience structure for passing along diff --git a/x/bank/msgs.go b/x/bank/msgs.go index 069ace9ce..46b199563 100644 --- a/x/bank/msgs.go +++ b/x/bank/msgs.go @@ -3,7 +3,6 @@ package bank import ( "encoding/json" - "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -73,11 +72,7 @@ func (msg MsgSend) GetSignBytes() []byte { if err != nil { panic(err) } - b, err = server.SortJSON(b) - if err != nil { - panic(err) - } - return b + return sdk.MustSortJSON(b) } // Implements Msg. @@ -138,11 +133,7 @@ func (msg MsgIssue) GetSignBytes() []byte { if err != nil { panic(err) } - b, err = server.SortJSON(b) - if err != nil { - panic(err) - } - return b + return sdk.MustSortJSON(b) } // Implements Msg. @@ -171,11 +162,7 @@ func (in Input) GetSignBytes() []byte { if err != nil { panic(err) } - bin, err = server.SortJSON(bin) - if err != nil { - panic(err) - } - return bin + return sdk.MustSortJSON(bin) } // ValidateBasic - validate transaction input @@ -222,11 +209,7 @@ func (out Output) GetSignBytes() []byte { if err != nil { panic(err) } - bin, err = server.SortJSON(bin) - if err != nil { - panic(err) - } - return bin + return sdk.MustSortJSON(bin) } // ValidateBasic - validate transaction output diff --git a/x/gov/msgs.go b/x/gov/msgs.go index afe7084c4..75a8d51e3 100644 --- a/x/gov/msgs.go +++ b/x/gov/msgs.go @@ -3,7 +3,6 @@ package gov import ( "fmt" - "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -83,11 +82,7 @@ func (msg MsgSubmitProposal) GetSignBytes() []byte { if err != nil { panic(err) } - b, err = server.SortJSON(b) - if err != nil { - panic(err) - } - return b + return sdk.MustSortJSON(b) } // Implements Msg. @@ -154,11 +149,7 @@ func (msg MsgDeposit) GetSignBytes() []byte { if err != nil { panic(err) } - b, err = server.SortJSON(b) - if err != nil { - panic(err) - } - return b + return sdk.MustSortJSON(b) } // Implements Msg. @@ -222,11 +213,7 @@ func (msg MsgVote) GetSignBytes() []byte { if err != nil { panic(err) } - b, err = server.SortJSON(b) - if err != nil { - panic(err) - } - return b + return sdk.MustSortJSON(b) } // Implements Msg. diff --git a/x/ibc/types.go b/x/ibc/types.go index a311b9869..33f2a9a8d 100644 --- a/x/ibc/types.go +++ b/x/ibc/types.go @@ -59,7 +59,7 @@ func (p IBCPacket) GetSignBytes() []byte { if err != nil { panic(err) } - return b + return sdk.MustSortJSON(b) } // validator the ibc packey @@ -131,5 +131,5 @@ func (msg IBCReceiveMsg) GetSignBytes() []byte { if err != nil { panic(err) } - return b + return sdk.MustSortJSON(b) } diff --git a/x/slashing/msg.go b/x/slashing/msg.go index 561c92266..6060079a4 100644 --- a/x/slashing/msg.go +++ b/x/slashing/msg.go @@ -38,7 +38,7 @@ func (msg MsgUnrevoke) GetSignBytes() []byte { if err != nil { panic(err) } - return b + return sdk.MustSortJSON(b) } // quick validity check diff --git a/x/stake/types/msg.go b/x/stake/types/msg.go index 609935fb0..aa9eea8cb 100644 --- a/x/stake/types/msg.go +++ b/x/stake/types/msg.go @@ -3,7 +3,6 @@ package types import ( "math" - "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/tendermint/tendermint/crypto" ) @@ -64,11 +63,7 @@ func (msg MsgCreateValidator) GetSignBytes() []byte { if err != nil { panic(err) } - b, err = server.SortJSON(b) - if err != nil { - panic(err) - } - return b + return sdk.MustSortJSON(b) } // quick validity check @@ -119,11 +114,7 @@ func (msg MsgEditValidator) GetSignBytes() []byte { if err != nil { panic(err) } - b, err = server.SortJSON(b) - if err != nil { - panic(err) - } - return b + return sdk.MustSortJSON(b) } // quick validity check @@ -175,11 +166,7 @@ func (msg MsgDelegate) GetSignBytes() []byte { if err != nil { panic(err) } - b, err = server.SortJSON(b) - if err != nil { - panic(err) - } - return b + return sdk.MustSortJSON(b) } // quick validity check @@ -239,11 +226,7 @@ func (msg MsgBeginRedelegate) GetSignBytes() []byte { if err != nil { panic(err) } - b, err = server.SortJSON(b) - if err != nil { - panic(err) - } - return b + return sdk.MustSortJSON(b) } // quick validity check @@ -303,11 +286,7 @@ func (msg MsgCompleteRedelegate) GetSignBytes() []byte { if err != nil { panic(err) } - b, err = server.SortJSON(b) - if err != nil { - panic(err) - } - return b + return sdk.MustSortJSON(b) } // quick validity check @@ -359,11 +338,7 @@ func (msg MsgBeginUnbonding) GetSignBytes() []byte { if err != nil { panic(err) } - b, err = server.SortJSON(b) - if err != nil { - panic(err) - } - return b + return sdk.MustSortJSON(b) } // quick validity check @@ -412,11 +387,7 @@ func (msg MsgCompleteUnbonding) GetSignBytes() []byte { if err != nil { panic(err) } - b, err = server.SortJSON(b) - if err != nil { - panic(err) - } - return b + return sdk.MustSortJSON(b) } // quick validity check From bf8cde1d3a7c5e948c5b04dd83f96c7df17486bb Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 5 Jul 2018 17:07:03 -0700 Subject: [PATCH 42/53] cli: deprecate --name in favor of --from --- CHANGELOG.md | 3 + Gopkg.lock | 512 +++++++++++++++++++++++++++++++++ client/context/viper.go | 9 +- client/flags.go | 4 +- cmd/gaia/cli_test/cli_test.go | 18 +- cmd/gaia/testnets/README.md | 12 +- docs/_attic/staking/intro.rst | 12 +- docs/_attic/staking/testnet.md | 4 +- docs/clients/ledger.md | 2 +- examples/README.md | 10 +- tests/check_basecli.sh | 2 +- x/bank/client/cli/sendtx.go | 2 +- x/ibc/client/cli/README.md | 4 +- 13 files changed, 559 insertions(+), 35 deletions(-) create mode 100644 Gopkg.lock diff --git a/CHANGELOG.md b/CHANGELOG.md index bb9672c5e..c62577320 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,9 @@ BREAKING CHANGES * [lcd] Switch key creation output to return bech32 * [x/stake] store-value for delegation, validator, ubd, and red do not hold duplicate information contained store-key +DEPRECATED +* [cli] Deprecate `--name` flag in commands that send txs, in favor of `--from` + FEATURES * [gaiacli] You can now attach a simple text-only memo to any transaction, with the `--memo` flag * [lcd] Queried TXs now include the tx hash to identify each tx diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 000000000..879453988 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,512 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/bartekn/go-bip39" + packages = ["."] + revision = "a05967ea095d81c8fe4833776774cfaff8e5036c" + +[[projects]] + branch = "master" + name = "github.com/beorn7/perks" + packages = ["quantile"] + revision = "3a771d992973f24aa725d07868b467d1ddfceafb" + +[[projects]] + name = "github.com/bgentry/speakeasy" + packages = ["."] + revision = "4aabc24848ce5fd31929f7d1e4ea74d3709c14cd" + version = "v0.1.0" + +[[projects]] + branch = "master" + name = "github.com/brejski/hid" + packages = ["."] + revision = "06112dcfcc50a7e0e4fd06e17f9791e788fdaafc" + +[[projects]] + branch = "master" + name = "github.com/btcsuite/btcd" + packages = ["btcec"] + revision = "86fed781132ac890ee03e906e4ecd5d6fa180c64" + +[[projects]] + branch = "master" + name = "github.com/btcsuite/btcutil" + packages = ["bech32"] + revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + branch = "master" + name = "github.com/ebuchman/fail-test" + packages = ["."] + revision = "95f809107225be108efcf10a3509e4ea6ceef3c4" + +[[projects]] + name = "github.com/fsnotify/fsnotify" + packages = ["."] + revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" + version = "v1.4.7" + +[[projects]] + name = "github.com/go-kit/kit" + packages = [ + "log", + "log/level", + "log/term", + "metrics", + "metrics/discard", + "metrics/internal/lv", + "metrics/prometheus" + ] + revision = "4dc7be5d2d12881735283bcab7352178e190fc71" + version = "v0.6.0" + +[[projects]] + name = "github.com/go-logfmt/logfmt" + packages = ["."] + revision = "390ab7935ee28ec6b286364bba9b4dd6410cb3d5" + version = "v0.3.0" + +[[projects]] + name = "github.com/go-stack/stack" + packages = ["."] + revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc" + version = "v1.7.0" + +[[projects]] + name = "github.com/gogo/protobuf" + packages = [ + "gogoproto", + "jsonpb", + "proto", + "protoc-gen-gogo/descriptor", + "sortkeys", + "types" + ] + revision = "1adfc126b41513cc696b209667c8656ea7aac67c" + version = "v1.0.0" + +[[projects]] + name = "github.com/golang/protobuf" + packages = [ + "proto", + "ptypes", + "ptypes/any", + "ptypes/duration", + "ptypes/timestamp" + ] + revision = "925541529c1fa6821df4e44ce2723319eb2be768" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/golang/snappy" + packages = ["."] + revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a" + +[[projects]] + name = "github.com/gorilla/context" + packages = ["."] + revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42" + version = "v1.1.1" + +[[projects]] + name = "github.com/gorilla/mux" + packages = ["."] + revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf" + version = "v1.6.2" + +[[projects]] + name = "github.com/gorilla/websocket" + packages = ["."] + revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b" + version = "v1.2.0" + +[[projects]] + branch = "master" + name = "github.com/hashicorp/hcl" + packages = [ + ".", + "hcl/ast", + "hcl/parser", + "hcl/printer", + "hcl/scanner", + "hcl/strconv", + "hcl/token", + "json/parser", + "json/scanner", + "json/token" + ] + revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168" + +[[projects]] + name = "github.com/inconshreveable/mousetrap" + packages = ["."] + revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" + version = "v1.0" + +[[projects]] + branch = "master" + name = "github.com/jmhodges/levigo" + packages = ["."] + revision = "c42d9e0ca023e2198120196f842701bb4c55d7b9" + +[[projects]] + branch = "master" + name = "github.com/kr/logfmt" + packages = ["."] + revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0" + +[[projects]] + name = "github.com/magiconair/properties" + packages = ["."] + revision = "c2353362d570a7bfa228149c62842019201cfb71" + version = "v1.8.0" + +[[projects]] + name = "github.com/mattn/go-isatty" + packages = ["."] + revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" + version = "v0.0.3" + +[[projects]] + name = "github.com/matttproud/golang_protobuf_extensions" + packages = ["pbutil"] + revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" + version = "v1.0.1" + +[[projects]] + branch = "master" + name = "github.com/mitchellh/mapstructure" + packages = ["."] + revision = "bb74f1db0675b241733089d5a1faa5dd8b0ef57b" + +[[projects]] + name = "github.com/pelletier/go-toml" + packages = ["."] + revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194" + version = "v1.2.0" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "645ef00459ed84a119197bfb8d8205042c6df63d" + version = "v0.8.0" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + name = "github.com/prometheus/client_golang" + packages = [ + "prometheus", + "prometheus/promhttp" + ] + revision = "c5b7fccd204277076155f10851dad72b76a49317" + version = "v0.8.0" + +[[projects]] + branch = "master" + name = "github.com/prometheus/client_model" + packages = ["go"] + revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c" + +[[projects]] + branch = "master" + name = "github.com/prometheus/common" + packages = [ + "expfmt", + "internal/bitbucket.org/ww/goautoneg", + "model" + ] + revision = "7600349dcfe1abd18d72d3a1770870d9800a7801" + +[[projects]] + branch = "master" + name = "github.com/prometheus/procfs" + packages = [ + ".", + "internal/util", + "nfs", + "xfs" + ] + revision = "ae68e2d4c00fed4943b5f6698d504a5fe083da8a" + +[[projects]] + branch = "master" + name = "github.com/rcrowley/go-metrics" + packages = ["."] + revision = "e2704e165165ec55d062f5919b4b29494e9fa790" + +[[projects]] + name = "github.com/spf13/afero" + packages = [ + ".", + "mem" + ] + revision = "787d034dfe70e44075ccc060d346146ef53270ad" + version = "v1.1.1" + +[[projects]] + name = "github.com/spf13/cast" + packages = ["."] + revision = "8965335b8c7107321228e3e3702cab9832751bac" + version = "v1.2.0" + +[[projects]] + name = "github.com/spf13/cobra" + packages = ["."] + revision = "7b2c5ac9fc04fc5efafb60700713d4fa609b777b" + version = "v0.0.1" + +[[projects]] + branch = "master" + name = "github.com/spf13/jwalterweatherman" + packages = ["."] + revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" + +[[projects]] + name = "github.com/spf13/pflag" + packages = ["."] + revision = "583c0c0531f06d5278b7d917446061adc344b5cd" + version = "v1.0.1" + +[[projects]] + name = "github.com/spf13/viper" + packages = ["."] + revision = "25b30aa063fc18e48662b86996252eabdcf2f0c7" + version = "v1.0.0" + +[[projects]] + name = "github.com/stretchr/testify" + packages = [ + "assert", + "require" + ] + revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" + version = "v1.2.1" + +[[projects]] + branch = "master" + name = "github.com/syndtr/goleveldb" + packages = [ + "leveldb", + "leveldb/cache", + "leveldb/comparer", + "leveldb/errors", + "leveldb/filter", + "leveldb/iterator", + "leveldb/journal", + "leveldb/memdb", + "leveldb/opt", + "leveldb/storage", + "leveldb/table", + "leveldb/util" + ] + revision = "0d5a0ceb10cf9ab89fdd744cc8c50a83134f6697" + +[[projects]] + branch = "master" + name = "github.com/tendermint/ed25519" + packages = [ + ".", + "edwards25519", + "extra25519" + ] + revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057" + +[[projects]] + name = "github.com/tendermint/go-amino" + packages = ["."] + revision = "2106ca61d91029c931fd54968c2bb02dc96b1412" + version = "0.10.1" + +[[projects]] + name = "github.com/tendermint/iavl" + packages = ["."] + revision = "9e5dc3e61f70b285bb25414452d47aca1ff34c1d" + version = "v0.8.2-rc0" + +[[projects]] + name = "github.com/tendermint/tendermint" + packages = [ + "abci/client", + "abci/example/code", + "abci/example/kvstore", + "abci/server", + "abci/types", + "blockchain", + "cmd/tendermint/commands", + "config", + "consensus", + "consensus/types", + "crypto", + "crypto/merkle", + "crypto/tmhash", + "evidence", + "libs/autofile", + "libs/bech32", + "libs/cli", + "libs/cli/flags", + "libs/clist", + "libs/common", + "libs/db", + "libs/events", + "libs/flowrate", + "libs/log", + "libs/pubsub", + "libs/pubsub/query", + "lite", + "lite/client", + "lite/errors", + "lite/files", + "lite/proxy", + "mempool", + "node", + "p2p", + "p2p/conn", + "p2p/pex", + "p2p/upnp", + "privval", + "proxy", + "rpc/client", + "rpc/core", + "rpc/core/types", + "rpc/grpc", + "rpc/lib", + "rpc/lib/client", + "rpc/lib/server", + "rpc/lib/types", + "state", + "state/txindex", + "state/txindex/kv", + "state/txindex/null", + "types", + "version" + ] + revision = "5923b6288fe8ce9581936ee97c2bf9cf9c02c2f4" + version = "v0.22.0-rc2" + +[[projects]] + name = "github.com/zondax/ledger-goclient" + packages = ["."] + revision = "065cbf938a16f20335c40cfe180f9cd4955c6a5a" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = [ + "blowfish", + "curve25519", + "internal/subtle", + "nacl/box", + "nacl/secretbox", + "openpgp/armor", + "openpgp/errors", + "pbkdf2", + "poly1305", + "ripemd160", + "salsa20/salsa" + ] + revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = [ + "context", + "http/httpguts", + "http2", + "http2/hpack", + "idna", + "internal/timeseries", + "netutil", + "trace" + ] + revision = "ed29d75add3d7c4bf7ca65aac0c6df3d1420216f" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["unix"] + revision = "151529c776cdc58ddbe7963ba9af779f3577b419" + +[[projects]] + name = "golang.org/x/text" + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable" + ] + revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" + version = "v0.3.0" + +[[projects]] + name = "google.golang.org/genproto" + packages = ["googleapis/rpc/status"] + revision = "7fd901a49ba6a7f87732eb344f6e3c5b19d1b200" + +[[projects]] + name = "google.golang.org/grpc" + packages = [ + ".", + "balancer", + "balancer/base", + "balancer/roundrobin", + "codes", + "connectivity", + "credentials", + "encoding", + "encoding/proto", + "grpclb/grpc_lb_v1/messages", + "grpclog", + "internal", + "keepalive", + "metadata", + "naming", + "peer", + "resolver", + "resolver/dns", + "resolver/passthrough", + "stats", + "status", + "tap", + "transport" + ] + revision = "d11072e7ca9811b1100b80ca0269ac831f06d024" + version = "v1.11.3" + +[[projects]] + name = "gopkg.in/yaml.v2" + packages = ["."] + revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" + version = "v2.2.1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "13ad2a57b6942729e2d08b5c37810d62108aa64a335a4822fcff1ad992c0662b" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/client/context/viper.go b/client/context/viper.go index c0b48fc85..2e3ed0dd3 100644 --- a/client/context/viper.go +++ b/client/context/viper.go @@ -27,13 +27,20 @@ func NewCoreContextFromViper() CoreContext { chainID = def } } + // TODO: Remove the following deprecation code after Gaia-7000 is launched + keyName := viper.GetString(client.FlagName) + if keyName != "" { + fmt.Println("** Note --name is deprecated and will be removed next release. Please use --from instead **") + } else { + keyName = viper.GetString(client.FlagFrom) + } return CoreContext{ ChainID: chainID, Height: viper.GetInt64(client.FlagHeight), Gas: viper.GetInt64(client.FlagGas), Fee: viper.GetString(client.FlagFee), TrustNode: viper.GetBool(client.FlagTrustNode), - FromAddressName: viper.GetString(client.FlagName), + FromAddressName: keyName, NodeURI: nodeURI, AccountNumber: viper.GetInt64(client.FlagAccountNumber), Sequence: viper.GetInt64(client.FlagSequence), diff --git a/client/flags.go b/client/flags.go index 31e9c087b..ef3711be9 100644 --- a/client/flags.go +++ b/client/flags.go @@ -10,6 +10,7 @@ const ( FlagHeight = "height" FlagGas = "gas" FlagTrustNode = "trust-node" + FlagFrom = "from" FlagName = "name" FlagAccountNumber = "account-number" FlagSequence = "sequence" @@ -37,7 +38,8 @@ func GetCommands(cmds ...*cobra.Command) []*cobra.Command { // PostCommands adds common flags for commands to post tx func PostCommands(cmds ...*cobra.Command) []*cobra.Command { for _, c := range cmds { - c.Flags().String(FlagName, "", "Name of private key with which to sign") + c.Flags().String(FlagFrom, "", "Name of private key with which to sign") + c.Flags().String(FlagName, "", "DEPRECATED - Name of private key with which to sign") c.Flags().Int64(FlagAccountNumber, 0, "AccountNumber number to sign the tx") c.Flags().Int64(FlagSequence, 0, "Sequence number to sign the tx") c.Flags().String(FlagMemo, "", "Memo to send along with transaction") diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 0761bd08f..93ef825aa 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -59,7 +59,7 @@ func TestGaiaCLISend(t *testing.T) { fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooCech, flags)) require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64()) - executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --name=foo", flags, barCech), pass) + executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --from=foo", flags, barCech), pass) tests.WaitForNextHeightTM(port) barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barCech, flags)) @@ -68,7 +68,7 @@ func TestGaiaCLISend(t *testing.T) { require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf("steak").Int64()) // test autosequencing - executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --name=foo", flags, barCech), pass) + executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --from=foo", flags, barCech), pass) tests.WaitForNextHeightTM(port) barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barCech, flags)) @@ -77,7 +77,7 @@ func TestGaiaCLISend(t *testing.T) { require.Equal(t, int64(30), fooAcc.GetCoins().AmountOf("steak").Int64()) // test memo - executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --name=foo --memo 'testmemo'", flags, barCech), pass) + executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --from=foo --memo 'testmemo'", flags, barCech), pass) tests.WaitForNextHeightTM(port) barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barCech, flags)) @@ -111,7 +111,7 @@ func TestGaiaCLICreateValidator(t *testing.T) { barCech := sdk.MustBech32ifyAcc(barAddr) barCeshPubKey := sdk.MustBech32ifyValPub(barPubKey) - executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --name=foo", flags, barCech), pass) + executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --from=foo", flags, barCech), pass) tests.WaitForNextHeightTM(port) barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barCech, flags)) @@ -121,7 +121,7 @@ func TestGaiaCLICreateValidator(t *testing.T) { // create validator cvStr := fmt.Sprintf("gaiacli stake create-validator %v", flags) - cvStr += fmt.Sprintf(" --name=%v", "bar") + cvStr += fmt.Sprintf(" --from=%v", "bar") cvStr += fmt.Sprintf(" --address-validator=%v", barCech) cvStr += fmt.Sprintf(" --pubkey=%v", barCeshPubKey) cvStr += fmt.Sprintf(" --amount=%v", "2steak") @@ -139,7 +139,7 @@ func TestGaiaCLICreateValidator(t *testing.T) { // unbond a single share unbondStr := fmt.Sprintf("gaiacli stake unbond begin %v", flags) - unbondStr += fmt.Sprintf(" --name=%v", "bar") + unbondStr += fmt.Sprintf(" --from=%v", "bar") unbondStr += fmt.Sprintf(" --address-validator=%v", barCech) unbondStr += fmt.Sprintf(" --address-delegator=%v", barCech) unbondStr += fmt.Sprintf(" --shares-amount=%v", "1") @@ -181,7 +181,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) { fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooCech, flags)) require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64()) - executeWrite(t, fmt.Sprintf("gaiacli gov submitproposal %v --proposer=%v --deposit=5steak --type=Text --title=Test --description=test --name=foo", flags, fooCech), pass) + executeWrite(t, fmt.Sprintf("gaiacli gov submitproposal %v --proposer=%v --deposit=5steak --type=Text --title=Test --description=test --from=foo", flags, fooCech), pass) tests.WaitForNextHeightTM(port) fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooCech, flags)) @@ -191,7 +191,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) { require.Equal(t, int64(1), proposal1.ProposalID) require.Equal(t, gov.StatusToString(gov.StatusDepositPeriod), proposal1.Status) - executeWrite(t, fmt.Sprintf("gaiacli gov deposit %v --depositer=%v --deposit=10steak --proposalID=1 --name=foo", flags, fooCech), pass) + executeWrite(t, fmt.Sprintf("gaiacli gov deposit %v --depositer=%v --deposit=10steak --proposalID=1 --from=foo", flags, fooCech), pass) tests.WaitForNextHeightTM(port) fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooCech, flags)) @@ -200,7 +200,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) { require.Equal(t, int64(1), proposal1.ProposalID) require.Equal(t, gov.StatusToString(gov.StatusVotingPeriod), proposal1.Status) - executeWrite(t, fmt.Sprintf("gaiacli gov vote %v --proposalID=1 --voter=%v --option=Yes --name=foo", flags, fooCech), pass) + executeWrite(t, fmt.Sprintf("gaiacli gov vote %v --proposalID=1 --voter=%v --option=Yes --from=foo", flags, fooCech), pass) tests.WaitForNextHeightTM(port) vote := executeGetVote(t, fmt.Sprintf("gaiacli gov query-vote --proposalID=1 --voter=%v --output=json %v", fooCech, flags)) diff --git a/cmd/gaia/testnets/README.md b/cmd/gaia/testnets/README.md index f65b9267e..e8d1f83e4 100644 --- a/cmd/gaia/testnets/README.md +++ b/cmd/gaia/testnets/README.md @@ -220,7 +220,7 @@ gaiacli stake create-validator \ --address-validator= --moniker="choose a moniker" \ --chain-id=gaia-6002 \ - --name= + --from= ``` ### Edit Validator Description @@ -237,7 +237,7 @@ gaiacli stake edit-validator --keybase-sig="6A0D65E29A4CBC8E" --details="To infinity and beyond!" --chain-id=gaia-6002 \ - --name= + --from= ``` ### View Validator Description @@ -272,7 +272,7 @@ gaiad start Wait for your full node to catch up to the latest block. Next, run the following command. Note that `` is the address of your validator account, and `` is the name of the validator account. You can find this info by running `gaiacli keys list`. ```bash -gaiacli stake unrevoke --chain-id=gaia-6002 --name= +gaiacli stake unrevoke --chain-id=gaia-6002 --from= ``` **WARNING:** If you don't wait for `gaiad` to sync before running `unrevoke`, you will receive an error message telling you your validator is still jailed. @@ -321,7 +321,7 @@ gaiacli stake delegate \ --amount=10steak \ --address-delegator= \ --address-validator= \ - --name= \ + --from= \ --chain-id=gaia-6002 ``` @@ -338,7 +338,7 @@ gaiacli stake unbond \ --address-delegator= \ --address-validator= \ --shares=MAX \ - --name= \ + --from= \ --chain-id=gaia-6002 ``` @@ -361,7 +361,7 @@ gaiacli stake delegation \ gaiacli send \ --amount=10faucetToken \ --chain-id=gaia-6002 \ - --name= \ + --from= \ --to= ``` diff --git a/docs/_attic/staking/intro.rst b/docs/_attic/staking/intro.rst index 3ed20852b..14735ef33 100644 --- a/docs/_attic/staking/intro.rst +++ b/docs/_attic/staking/intro.rst @@ -197,9 +197,9 @@ We'll have ``alice`` send some ``mycoin`` to ``bob``, who has now joined the net :: - gaiacli send --amount=1000mycoin --sequence=0 --name=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 --chain-id=test-chain-Uv1EVU + gaiacli send --amount=1000mycoin --sequence=0 --from=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 --chain-id=test-chain-Uv1EVU -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: +where the ``--sequence`` flag is to be incremented for each transaction, the ``--from`` flag is the sender (alice), and the ``--to`` flag takes ``bob``'s address. You'll see something like: :: @@ -264,7 +264,7 @@ Now ``bob`` can create a validator with that pubkey. :: - gaiacli stake create-validator --amount=10mycoin --name=bob --address-validator=
--pub-key= --moniker=bobby + gaiacli stake create-validator --amount=10mycoin --from=bob --address-validator=
--pub-key= --moniker=bobby with an output like: @@ -306,13 +306,13 @@ First let's have ``alice`` send some coins to ``charlie``: :: - gaiacli send --amount=1000mycoin --sequence=2 --name=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF + gaiacli send --amount=1000mycoin --sequence=2 --from=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF Then ``charlie`` will delegate some mycoin to ``bob``: :: - gaiacli stake delegate --amount=10mycoin --address-delegator= --address-validator= --name=charlie + gaiacli stake delegate --amount=10mycoin --address-delegator= --address-validator= --from=charlie You'll see output like: @@ -396,7 +396,7 @@ your VotingPower reduce and your account balance increase. :: - gaiacli stake unbond --amount=5mycoin --name=charlie --address-delegator=
--address-validator=
+ gaiacli stake unbond --amount=5mycoin --from=charlie --address-delegator=
--address-validator=
gaiacli account 48F74F48281C89E5E4BE9092F735EA519768E8EF See the bond decrease with ``gaiacli stake delegation`` like above. diff --git a/docs/_attic/staking/testnet.md b/docs/_attic/staking/testnet.md index b2bbd8f1a..5228070cf 100644 --- a/docs/_attic/staking/testnet.md +++ b/docs/_attic/staking/testnet.md @@ -63,7 +63,7 @@ Then, we try to transfer some `steak` to another account: ``` gaiacli account gaiacli account -gaiacli send --amount=10steak --to= --name=foo --chain-id=test-chain +gaiacli send --amount=10steak --to= --from=foo --chain-id=test-chain ``` **Note:** We need to be careful with the `chain-id` and `sequence` @@ -84,7 +84,7 @@ Finally, to relinquish all your power, unbond some coins. You should see your VotingPower reduce and your account balance increase. ``` -gaiacli unbond --chain-id= --name=test +gaiacli unbond --chain-id= --from=test ``` That's it! diff --git a/docs/clients/ledger.md b/docs/clients/ledger.md index 9f6386715..5ea1224ea 100644 --- a/docs/clients/ledger.md +++ b/docs/clients/ledger.md @@ -23,7 +23,7 @@ NAME: TYPE: ADDRESS: PUBKEY: This key will only be accessible while the Ledger is plugged in and unlocked. To send some coins with this key, run the following: ```bash -$ gaiacli send --name {{ .Key.Name }} --to {{ .Destination.AccAddr }} --chain-id=gaia-7000 +$ gaiacli send --from {{ .Key.Name }} --to {{ .Destination.AccAddr }} --chain-id=gaia-7000 ``` You will be asked to review and confirm the transaction on the Ledger. Once you do this you should see the result in the console! Now you can use your Ledger to manage your Atoms and Stake! diff --git a/examples/README.md b/examples/README.md index a8a483ee6..e3016fb70 100644 --- a/examples/README.md +++ b/examples/README.md @@ -123,12 +123,12 @@ Where `90B0B9BE0914ECEE0B6DB74E67B07A00056B9BBD` is alice's address we got from The following command will send coins from alice, to bob: ``` -basecli send --name=alice --amount=10000mycoin --to=29D721F054537C91F618A0FDBF770DA51EF8C48D +basecli send --from=alice --amount=10000mycoin --to=29D721F054537C91F618A0FDBF770DA51EF8C48D --sequence=0 --chain-id=test-chain-AE4XQo ``` Flag Descriptions: -- `name` is the name you gave your key +- `from` is the name you gave your key - `mycoin` is the name of the token for this basecoin demo, initialized in the genesis.json file - `sequence` is a tally of how many transactions have been made by this account. Since this is the first tx on this account, it is 0 - `chain-id` is the unique ID that helps tendermint identify which network to connect to. You can find it in the terminal output from the gaiad daemon in the header block , or in the genesis.json file at `~/.basecoind/config/genesis.json` @@ -142,16 +142,16 @@ basecli account 29D721F054537C91F618A0FDBF770DA51EF8C48D Now lets send some from bob to charlie. Make sure you send less than bob has, otherwise the transaction will fail: ``` -basecli send --name=bob --amount=5000mycoin --to=2E8E13EEB8E3F0411ACCBC9BE0384732C24FBD5E +basecli send --from=bob --amount=5000mycoin --to=2E8E13EEB8E3F0411ACCBC9BE0384732C24FBD5E --sequence=0 --chain-id=test-chain-AE4XQo ``` -Note how we use the ``--name`` flag to select a different account to send from. +Note how we use the ``--from`` flag to select a different account to send from. Lets now try to send from bob back to alice: ``` -basecli send --name=bob --amount=3000mycoin --to=90B0B9BE0914ECEE0B6DB74E67B07A00056B9BBD +basecli send --from=bob --amount=3000mycoin --to=90B0B9BE0914ECEE0B6DB74E67B07A00056B9BBD --sequence=1 --chain-id=test-chain-AE4XQo ``` diff --git a/tests/check_basecli.sh b/tests/check_basecli.sh index ec2c458cb..ffcf39a51 100755 --- a/tests/check_basecli.sh +++ b/tests/check_basecli.sh @@ -36,7 +36,7 @@ echo; echo "Empty account:" $TO ./build/basecli account $TO # send some money -TX=`echo $PASS | ./build/basecli send --to=$TO --amount=1000mycoin --name=demo --seq=0` +TX=`echo $PASS | ./build/basecli send --to=$TO --amount=1000mycoin --from=demo --seq=0` echo; echo "SendTx"; echo $TX HASH=`echo $TX | cut -d' ' -f6` echo "tx hash:" $HASH diff --git a/x/bank/client/cli/sendtx.go b/x/bank/client/cli/sendtx.go index e3ce4c4d2..11f25b4ba 100644 --- a/x/bank/client/cli/sendtx.go +++ b/x/bank/client/cli/sendtx.go @@ -78,7 +78,7 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command { if err != nil { return err } - fmt.Println("Async tx sent. tx hash: ", res.Hash.String()) + fmt.Printf("Async tx sent. tx hash: %s\n", res.Hash.String()) return nil } res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) diff --git a/x/ibc/client/cli/README.md b/x/ibc/client/cli/README.md index e91fb55bf..ab9e8e555 100644 --- a/x/ibc/client/cli/README.md +++ b/x/ibc/client/cli/README.md @@ -109,7 +109,7 @@ key2 DC26002735D3AA9573707CFA6D77C12349E49868 ## Transfer coins (addr1:chain1 -> addr2:chain2) ```console -> basecli transfer --name key1 --to $ADDR2 --amount 10mycoin --chain $ID2 --chain-id $ID1 --node $NODE1 +> basecli transfer --from key1 --to $ADDR2 --amount 10mycoin --chain $ID2 --chain-id $ID1 --node $NODE1 Password to sign with 'key1': Committed at block 1022. Hash: E16019DCC4AA08CA70AFCFBC96028ABCC51B6AD0 > basecli account $ADDR1 --node $NODE1 @@ -133,7 +133,7 @@ Committed at block 1022. Hash: E16019DCC4AA08CA70AFCFBC96028ABCC51B6AD0 ## Relay IBC packets ```console -> basecli relay --name key2 --from-chain-id $ID1 --from-chain-node $NODE1 --to-chain-id $ID2 --to-chain-node $NODE2 --chain-id $ID2 +> basecli relay --from key2 --from-chain-id $ID1 --from-chain-node $NODE1 --to-chain-id $ID2 --to-chain-node $NODE2 --chain-id $ID2 Password to sign with 'key2': I[04-03|16:18:59.984] Detected IBC packet number=0 I[04-03|16:19:00.869] Relayed IBC packet number=0 From 0b10430d65f8313d5a387c0aaf1d26a73d912e1d Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 5 Jul 2018 18:03:41 -0700 Subject: [PATCH 43/53] gaiacli, keys: Improve error message when deleting non-existant key --- CHANGELOG.md | 3 ++- client/keys/delete.go | 13 +++++++++---- crypto/keys/keybase.go | 3 +++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb9672c5e..f46475843 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,8 +80,9 @@ IMPROVEMENTS * [stake] module reorganized to include `types` and `keeper` package * [stake] keeper always loads the store (instead passing around which doesn't really boost efficiency) * [stake] edit-validator changes now can use the keyword [do-not-modify] to not modify unspecified `--flag` (aka won't set them to `""` value) -* [types] added common tag constants * [stake] offload more generic functionality from the handler into the keeper +* [types] added common tag constants +* [keys] improve error message when deleting non-existent key * added contributing guidelines BUG FIXES diff --git a/client/keys/delete.go b/client/keys/delete.go index f38c529a6..944feb4b1 100644 --- a/client/keys/delete.go +++ b/client/keys/delete.go @@ -25,14 +25,19 @@ func deleteKeyCommand() *cobra.Command { func runDeleteCmd(cmd *cobra.Command, args []string) error { name := args[0] - buf := client.BufferStdin() - oldpass, err := client.GetPassword( - "DANGER - enter password to permanently delete key:", buf) + kb, err := GetKeyBase() if err != nil { return err } - kb, err := GetKeyBase() + _, err = kb.Get(name) + if err != nil { + return err + } + + buf := client.BufferStdin() + oldpass, err := client.GetPassword( + "DANGER - enter password to permanently delete key:", buf) if err != nil { return err } diff --git a/crypto/keys/keybase.go b/crypto/keys/keybase.go index 82adc53dd..7cf43eea6 100644 --- a/crypto/keys/keybase.go +++ b/crypto/keys/keybase.go @@ -188,6 +188,9 @@ func (kb dbKeybase) List() ([]Info, error) { // Get returns the public information about one key. func (kb dbKeybase) Get(name string) (Info, error) { bs := kb.db.Get(infoKey(name)) + if len(bs) == 0 { + return nil, fmt.Errorf("Key %s not found", name) + } return readInfo(bs) } From 8fc6e685111ff1168af533eb2214b0de2796a4e3 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 5 Jul 2018 18:24:00 -0700 Subject: [PATCH 44/53] stake/client: Fix panic on if validator doesn't exist Closes #1505 --- CHANGELOG.md | 1 + x/stake/client/cli/query.go | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb9672c5e..57bea2f9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -101,6 +101,7 @@ BUG FIXES * \#1258 - printing big.rat's can no longer overflow int64 * \#887 - limit the size of rationals that can be passed in from user input * \#1461 - CLI tests now no longer reset your local environment data +* \#1505 - `gaiacli stake validator` no longer panics if validator doesn't exist ## 0.19.0 diff --git a/x/stake/client/cli/query.go b/x/stake/client/cli/query.go index 82149a2fa..30f833c02 100644 --- a/x/stake/client/cli/query.go +++ b/x/stake/client/cli/query.go @@ -31,8 +31,9 @@ func GetCmdQueryValidator(storeName string, cdc *wire.Codec) *cobra.Command { res, err := ctx.QueryStore(key, storeName) if err != nil { return err + } else if len(res) == 0 { + return fmt.Errorf("No validator found with address %s", args[0]) } - validator := types.MustUnmarshalValidator(cdc, addr, res) switch viper.Get(cli.OutputFlag) { From 1fabaee2dd0fe53c233c8929ffe94cc11a51726b Mon Sep 17 00:00:00 2001 From: Liamsi Date: Fri, 6 Jul 2018 02:37:55 +0100 Subject: [PATCH 45/53] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b35664140..7b5834035 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ *TBD* BREAKING CHANGES +* msg.GetSignBytes() returns sorted JSON (by key) * Update Tendermint to v0.22.0 * Default ports changed from 466xx to 266xx * Amino JSON uses type names instead of prefix bytes From 6f94dd64c0bafdd31f0c7b751f12d2449c7cff14 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 5 Jul 2018 19:15:35 -0700 Subject: [PATCH 46/53] cli: Add async flag to all broadcasting txs closes #1436 --- client/context/helpers.go | 25 ++++++++++--------- client/flags.go | 2 ++ examples/democoin/x/cool/client/cli/tx.go | 8 ++---- examples/democoin/x/pow/client/cli/tx.go | 6 ++--- .../x/simplestake/client/cli/commands.go | 4 +-- x/bank/client/cli/sendtx.go | 20 +++------------ x/gov/client/cli/tx.go | 11 +++----- x/ibc/client/cli/ibctx.go | 5 +--- x/slashing/client/cli/tx.go | 8 +++--- x/stake/client/cli/tx.go | 22 ++++++---------- 10 files changed, 41 insertions(+), 70 deletions(-) diff --git a/client/context/helpers.go b/client/context/helpers.go index 89c171353..06914be8c 100644 --- a/client/context/helpers.go +++ b/client/context/helpers.go @@ -224,25 +224,26 @@ func (ctx CoreContext) ensureSignBuild(name string, msgs []sdk.Msg, cdc *wire.Co } // sign and build the transaction from the msg -func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msgs []sdk.Msg, cdc *wire.Codec) (res *ctypes.ResultBroadcastTxCommit, err error) { +func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msgs []sdk.Msg, cdc *wire.Codec, async bool, printResponse bool) (err error) { txBytes, err := ctx.ensureSignBuild(name, msgs, cdc) if err != nil { - return nil, err + return err } - return ctx.BroadcastTx(txBytes) -} - -// sign and build the async transaction from the msg -func (ctx CoreContext) EnsureSignBuildBroadcastAsync(name string, msgs []sdk.Msg, cdc *wire.Codec) (res *ctypes.ResultBroadcastTx, err error) { - - txBytes, err := ctx.ensureSignBuild(name, msgs, cdc) - if err != nil { - return nil, err + if async { + res, err := ctx.BroadcastTxAsync(txBytes) + fmt.Println("Async tx sent. tx hash: ", res.Hash.String()) + return err } + res, err := ctx.BroadcastTx(txBytes) + if printResponse { + fmt.Printf("Committed at block %d. Hash: %s Response:%+v \n", res.Height, res.Hash.String(), res.DeliverTx) + } else { - return ctx.BroadcastTxAsync(txBytes) + fmt.Printf("Committed at block %d. Hash: %s \n", res.Height, res.Hash.String()) + } + return err } // get the next sequence for the account address diff --git a/client/flags.go b/client/flags.go index 31e9c087b..9fb73ad41 100644 --- a/client/flags.go +++ b/client/flags.go @@ -15,6 +15,7 @@ const ( FlagSequence = "sequence" FlagMemo = "memo" FlagFee = "fee" + FlagAsync = "async" ) // LineBreak can be included in a command list to provide a blank line @@ -46,6 +47,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().String(FlagNode, "tcp://localhost:26657", ": to tendermint rpc interface for this chain") c.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device") c.Flags().Int64(FlagGas, 200000, "gas limit to set per-transaction") + c.Flags().Bool(FlagAsync, false, "broadcast transactions asynchronously") } return cmds } diff --git a/examples/democoin/x/cool/client/cli/tx.go b/examples/democoin/x/cool/client/cli/tx.go index cb65830c9..a6ad09b61 100644 --- a/examples/democoin/x/cool/client/cli/tx.go +++ b/examples/democoin/x/cool/client/cli/tx.go @@ -1,8 +1,6 @@ package cli import ( - "fmt" - "github.com/spf13/cobra" "github.com/spf13/viper" @@ -37,12 +35,11 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command { name := viper.GetString(client.FlagName) // build and sign the transaction, then broadcast to Tendermint - res, err := ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) if err != nil { return err } - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } @@ -70,12 +67,11 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command { msg := cool.NewMsgSetTrend(from, args[0]) // build and sign the transaction, then broadcast to Tendermint - res, err := ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) if err != nil { return err } - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } diff --git a/examples/democoin/x/pow/client/cli/tx.go b/examples/democoin/x/pow/client/cli/tx.go index 49527c8c0..7953c3177 100644 --- a/examples/democoin/x/pow/client/cli/tx.go +++ b/examples/democoin/x/pow/client/cli/tx.go @@ -1,11 +1,12 @@ package cli import ( - "fmt" "strconv" "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/examples/democoin/x/pow" @@ -49,12 +50,11 @@ func MineCmd(cdc *wire.Codec) *cobra.Command { name := ctx.FromAddressName // build and sign the transaction, then broadcast to Tendermint - res, err := ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) if err != nil { return err } - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } diff --git a/examples/democoin/x/simplestake/client/cli/commands.go b/examples/democoin/x/simplestake/client/cli/commands.go index fcd0c84b4..a895a4154 100644 --- a/examples/democoin/x/simplestake/client/cli/commands.go +++ b/examples/democoin/x/simplestake/client/cli/commands.go @@ -9,6 +9,7 @@ import ( "github.com/tendermint/tendermint/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" @@ -87,11 +88,10 @@ func UnbondTxCmd(cdc *wire.Codec) *cobra.Command { func sendMsg(cdc *wire.Codec, msg sdk.Msg) error { ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) + err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) if err != nil { return err } - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil } diff --git a/x/bank/client/cli/sendtx.go b/x/bank/client/cli/sendtx.go index e3ce4c4d2..6b5a54b26 100644 --- a/x/bank/client/cli/sendtx.go +++ b/x/bank/client/cli/sendtx.go @@ -2,23 +2,21 @@ package cli import ( "errors" - "fmt" - - "github.com/spf13/cobra" - "github.com/spf13/viper" + baseClient "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" "github.com/cosmos/cosmos-sdk/x/auth" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" "github.com/cosmos/cosmos-sdk/x/bank/client" + "github.com/spf13/cobra" + "github.com/spf13/viper" ) const ( flagTo = "to" flagAmount = "amount" - flagAsync = "async" ) // SendTxCmd will create a send tx and sign it with the given key @@ -73,19 +71,10 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint msg := client.BuildMsg(from, to, coins) - if viper.GetBool(flagAsync) { - res, err := ctx.EnsureSignBuildBroadcastAsync(ctx.FromAddressName, []sdk.Msg{msg}, cdc) - if err != nil { - return err - } - fmt.Println("Async tx sent. tx hash: ", res.Hash.String()) - return nil - } - res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(baseClient.FlagAsync), false) if err != nil { return err } - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, @@ -93,7 +82,6 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command { cmd.Flags().String(flagTo, "", "Address to send coins") cmd.Flags().String(flagAmount, "", "Amount of coins to send") - cmd.Flags().Bool(flagAsync, false, "Pass the async flag to send a tx without waiting for the tx to be included in a block") return cmd } diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 00933284e..8b0be208d 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -6,6 +6,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + "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" @@ -64,12 +65,10 @@ func GetCmdSubmitProposal(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), true) if err != nil { return err } - - fmt.Printf("Committed at block:%d. Hash:%s.Response:%+v \n", res.Height, res.Hash.String(), res.DeliverTx) return nil }, } @@ -113,11 +112,10 @@ func GetCmdDeposit(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) if err != nil { return err } - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } @@ -164,11 +162,10 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) if err != nil { return err } - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } diff --git a/x/ibc/client/cli/ibctx.go b/x/ibc/client/cli/ibctx.go index 9df58d6a8..7e56fc4cf 100644 --- a/x/ibc/client/cli/ibctx.go +++ b/x/ibc/client/cli/ibctx.go @@ -2,7 +2,6 @@ package cli import ( "encoding/hex" - "fmt" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -43,12 +42,10 @@ func IBCTransferCmd(cdc *wire.Codec) *cobra.Command { } // get password - res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) if err != nil { return err } - - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } diff --git a/x/slashing/client/cli/tx.go b/x/slashing/client/cli/tx.go index de390ce23..7a0411628 100644 --- a/x/slashing/client/cli/tx.go +++ b/x/slashing/client/cli/tx.go @@ -1,10 +1,10 @@ package cli import ( - "fmt" - "github.com/spf13/cobra" + "github.com/spf13/viper" + "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" @@ -29,12 +29,10 @@ func GetCmdUnrevoke(cdc *wire.Codec) *cobra.Command { msg := slashing.NewMsgUnrevoke(validatorAddr) // build and sign the transaction, then broadcast to Tendermint - res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) if err != nil { return err } - - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index 7200caef3..c633d83df 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -53,12 +53,10 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgCreateValidator(validatorAddr, pk, amount, description) // build and sign the transaction, then broadcast to Tendermint - res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) if err != nil { return err } - - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } @@ -92,12 +90,11 @@ func GetCmdEditValidator(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) if err != nil { return err } - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } @@ -132,12 +129,11 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) if err != nil { return err } - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } @@ -197,12 +193,11 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) if err != nil { return err } - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } @@ -282,12 +277,11 @@ func GetCmdCompleteRedelegate(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) if err != nil { return err } - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } @@ -340,12 +334,11 @@ func GetCmdBeginUnbonding(storeName string, cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) if err != nil { return err } - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } @@ -377,12 +370,11 @@ func GetCmdCompleteUnbonding(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) if err != nil { return err } - fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } From 27a31cae44da7738de909da67cf016ae6e2b2a17 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 5 Jul 2018 20:05:17 -0700 Subject: [PATCH 47/53] add Async to context --- client/context/types.go | 1 + client/context/viper.go | 1 + examples/democoin/x/cool/client/cli/tx.go | 4 ++-- examples/democoin/x/pow/client/cli/tx.go | 4 +--- .../democoin/x/simplestake/client/cli/commands.go | 3 +-- x/bank/client/cli/sendtx.go | 3 +-- x/gov/client/cli/tx.go | 7 +++---- x/ibc/client/cli/ibctx.go | 2 +- x/slashing/client/cli/tx.go | 4 +--- x/stake/client/cli/tx.go | 14 +++++++------- 10 files changed, 19 insertions(+), 24 deletions(-) diff --git a/client/context/types.go b/client/context/types.go index 58df9b5bf..017ed9565 100644 --- a/client/context/types.go +++ b/client/context/types.go @@ -22,6 +22,7 @@ type CoreContext struct { Decoder auth.AccountDecoder AccountStore string UseLedger bool + Async bool } // WithChainID - return a copy of the context with an updated chainID diff --git a/client/context/viper.go b/client/context/viper.go index c0b48fc85..948cd7a7d 100644 --- a/client/context/viper.go +++ b/client/context/viper.go @@ -42,6 +42,7 @@ func NewCoreContextFromViper() CoreContext { Decoder: nil, AccountStore: "acc", UseLedger: viper.GetBool(client.FlagUseLedger), + Async: viper.GetBool(client.FlagAsync), } } diff --git a/examples/democoin/x/cool/client/cli/tx.go b/examples/democoin/x/cool/client/cli/tx.go index a6ad09b61..5148e0561 100644 --- a/examples/democoin/x/cool/client/cli/tx.go +++ b/examples/democoin/x/cool/client/cli/tx.go @@ -35,7 +35,7 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command { name := viper.GetString(client.FlagName) // build and sign the transaction, then broadcast to Tendermint - err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) + err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } @@ -67,7 +67,7 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command { msg := cool.NewMsgSetTrend(from, args[0]) // build and sign the transaction, then broadcast to Tendermint - err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) + err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } diff --git a/examples/democoin/x/pow/client/cli/tx.go b/examples/democoin/x/pow/client/cli/tx.go index 7953c3177..bc6588f03 100644 --- a/examples/democoin/x/pow/client/cli/tx.go +++ b/examples/democoin/x/pow/client/cli/tx.go @@ -4,9 +4,7 @@ import ( "strconv" "github.com/spf13/cobra" - "github.com/spf13/viper" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/examples/democoin/x/pow" @@ -50,7 +48,7 @@ func MineCmd(cdc *wire.Codec) *cobra.Command { name := ctx.FromAddressName // build and sign the transaction, then broadcast to Tendermint - err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) + err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } diff --git a/examples/democoin/x/simplestake/client/cli/commands.go b/examples/democoin/x/simplestake/client/cli/commands.go index a895a4154..c907a8b8f 100644 --- a/examples/democoin/x/simplestake/client/cli/commands.go +++ b/examples/democoin/x/simplestake/client/cli/commands.go @@ -9,7 +9,6 @@ import ( "github.com/tendermint/tendermint/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" @@ -88,7 +87,7 @@ func UnbondTxCmd(cdc *wire.Codec) *cobra.Command { func sendMsg(cdc *wire.Codec, msg sdk.Msg) error { ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) + err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } diff --git a/x/bank/client/cli/sendtx.go b/x/bank/client/cli/sendtx.go index 6b5a54b26..4d142b90d 100644 --- a/x/bank/client/cli/sendtx.go +++ b/x/bank/client/cli/sendtx.go @@ -3,7 +3,6 @@ package cli import ( "errors" - baseClient "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" @@ -71,7 +70,7 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint msg := client.BuildMsg(from, to, coins) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(baseClient.FlagAsync), false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 8b0be208d..626259ad0 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -6,7 +6,6 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "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" @@ -65,7 +64,7 @@ func GetCmdSubmitProposal(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), true) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, true) if err != nil { return err } @@ -112,7 +111,7 @@ func GetCmdDeposit(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } @@ -162,7 +161,7 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } diff --git a/x/ibc/client/cli/ibctx.go b/x/ibc/client/cli/ibctx.go index 7e56fc4cf..4ab5217a0 100644 --- a/x/ibc/client/cli/ibctx.go +++ b/x/ibc/client/cli/ibctx.go @@ -42,7 +42,7 @@ func IBCTransferCmd(cdc *wire.Codec) *cobra.Command { } // get password - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } diff --git a/x/slashing/client/cli/tx.go b/x/slashing/client/cli/tx.go index 7a0411628..133ddf090 100644 --- a/x/slashing/client/cli/tx.go +++ b/x/slashing/client/cli/tx.go @@ -2,9 +2,7 @@ package cli import ( "github.com/spf13/cobra" - "github.com/spf13/viper" - "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" @@ -29,7 +27,7 @@ func GetCmdUnrevoke(cdc *wire.Codec) *cobra.Command { msg := slashing.NewMsgUnrevoke(validatorAddr) // build and sign the transaction, then broadcast to Tendermint - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index c633d83df..ce35c3de8 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -53,7 +53,7 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgCreateValidator(validatorAddr, pk, amount, description) // build and sign the transaction, then broadcast to Tendermint - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } @@ -90,7 +90,7 @@ func GetCmdEditValidator(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } @@ -129,7 +129,7 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } @@ -193,7 +193,7 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } @@ -277,7 +277,7 @@ func GetCmdCompleteRedelegate(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } @@ -334,7 +334,7 @@ func GetCmdBeginUnbonding(storeName string, cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } @@ -370,7 +370,7 @@ func GetCmdCompleteUnbonding(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, viper.GetBool(client.FlagAsync), false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) if err != nil { return err } From 8857b69d02ebceb8d07058fee9c0be90a93b47fe Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 5 Jul 2018 20:15:40 -0700 Subject: [PATCH 48/53] Use async flag directly from context --- client/context/helpers.go | 2 +- examples/democoin/x/cool/client/cli/tx.go | 4 ++-- examples/democoin/x/pow/client/cli/tx.go | 2 +- .../democoin/x/simplestake/client/cli/commands.go | 2 +- x/bank/client/cli/sendtx.go | 2 +- x/gov/client/cli/tx.go | 6 +++--- x/ibc/client/cli/ibctx.go | 2 +- x/slashing/client/cli/tx.go | 2 +- x/stake/client/cli/tx.go | 14 +++++++------- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/client/context/helpers.go b/client/context/helpers.go index 06914be8c..9b7891431 100644 --- a/client/context/helpers.go +++ b/client/context/helpers.go @@ -231,7 +231,7 @@ func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msgs []sdk.Msg, cdc return err } - if async { + if ctx.Async { res, err := ctx.BroadcastTxAsync(txBytes) fmt.Println("Async tx sent. tx hash: ", res.Hash.String()) return err diff --git a/examples/democoin/x/cool/client/cli/tx.go b/examples/democoin/x/cool/client/cli/tx.go index 5148e0561..9300f46c2 100644 --- a/examples/democoin/x/cool/client/cli/tx.go +++ b/examples/democoin/x/cool/client/cli/tx.go @@ -35,7 +35,7 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command { name := viper.GetString(client.FlagName) // build and sign the transaction, then broadcast to Tendermint - err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, ctx.Async, false) + err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, false) if err != nil { return err } @@ -67,7 +67,7 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command { msg := cool.NewMsgSetTrend(from, args[0]) // build and sign the transaction, then broadcast to Tendermint - err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, ctx.Async, false) + err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, false) if err != nil { return err } diff --git a/examples/democoin/x/pow/client/cli/tx.go b/examples/democoin/x/pow/client/cli/tx.go index bc6588f03..43b33bd6e 100644 --- a/examples/democoin/x/pow/client/cli/tx.go +++ b/examples/democoin/x/pow/client/cli/tx.go @@ -48,7 +48,7 @@ func MineCmd(cdc *wire.Codec) *cobra.Command { name := ctx.FromAddressName // build and sign the transaction, then broadcast to Tendermint - err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, ctx.Async, false) + err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, false) if err != nil { return err } diff --git a/examples/democoin/x/simplestake/client/cli/commands.go b/examples/democoin/x/simplestake/client/cli/commands.go index c907a8b8f..197d98671 100644 --- a/examples/democoin/x/simplestake/client/cli/commands.go +++ b/examples/democoin/x/simplestake/client/cli/commands.go @@ -87,7 +87,7 @@ func UnbondTxCmd(cdc *wire.Codec) *cobra.Command { func sendMsg(cdc *wire.Codec, msg sdk.Msg) error { ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) + err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) if err != nil { return err } diff --git a/x/bank/client/cli/sendtx.go b/x/bank/client/cli/sendtx.go index 4d142b90d..aa51c5a19 100644 --- a/x/bank/client/cli/sendtx.go +++ b/x/bank/client/cli/sendtx.go @@ -70,7 +70,7 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint msg := client.BuildMsg(from, to, coins) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) if err != nil { return err } diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 626259ad0..cde0d7498 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -64,7 +64,7 @@ func GetCmdSubmitProposal(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, true) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, true) if err != nil { return err } @@ -111,7 +111,7 @@ func GetCmdDeposit(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) if err != nil { return err } @@ -161,7 +161,7 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) if err != nil { return err } diff --git a/x/ibc/client/cli/ibctx.go b/x/ibc/client/cli/ibctx.go index 4ab5217a0..e4e6a5b76 100644 --- a/x/ibc/client/cli/ibctx.go +++ b/x/ibc/client/cli/ibctx.go @@ -42,7 +42,7 @@ func IBCTransferCmd(cdc *wire.Codec) *cobra.Command { } // get password - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) if err != nil { return err } diff --git a/x/slashing/client/cli/tx.go b/x/slashing/client/cli/tx.go index 133ddf090..eaeaf3eb8 100644 --- a/x/slashing/client/cli/tx.go +++ b/x/slashing/client/cli/tx.go @@ -27,7 +27,7 @@ func GetCmdUnrevoke(cdc *wire.Codec) *cobra.Command { msg := slashing.NewMsgUnrevoke(validatorAddr) // build and sign the transaction, then broadcast to Tendermint - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) if err != nil { return err } diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index ce35c3de8..d7f91e29d 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -53,7 +53,7 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgCreateValidator(validatorAddr, pk, amount, description) // build and sign the transaction, then broadcast to Tendermint - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) if err != nil { return err } @@ -90,7 +90,7 @@ func GetCmdEditValidator(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) if err != nil { return err } @@ -129,7 +129,7 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) if err != nil { return err } @@ -193,7 +193,7 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) if err != nil { return err } @@ -277,7 +277,7 @@ func GetCmdCompleteRedelegate(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) if err != nil { return err } @@ -334,7 +334,7 @@ func GetCmdBeginUnbonding(storeName string, cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) if err != nil { return err } @@ -370,7 +370,7 @@ func GetCmdCompleteUnbonding(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, ctx.Async, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) if err != nil { return err } From 8e20200abe4ad42c319c95713d5bd1d418c925fa Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 5 Jul 2018 20:42:41 -0700 Subject: [PATCH 49/53] Add --json flag --- CHANGELOG.md | 3 ++- client/context/helpers.go | 41 ++++++++++++++++++++++++++++++++++++--- client/context/types.go | 1 + client/context/viper.go | 1 + client/flags.go | 2 ++ 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ebcd3221..d914eb9fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,7 +75,7 @@ FEATURES - You can now use a Ledger with `gaiacli --ledger` for all key-related commands - Ledger keys can be named and tracked locally in the key DB * [gaiacli] added an --async flag to the cli to deliver transactions without waiting for a tendermint response -* [gaiacli] improve error messages on `send` and `account` commands +* [gaiacli] added a --json flag to the cli for deliver transactions IMPROVEMENTS * bank module uses go-wire codec instead of 'encoding/json' @@ -87,6 +87,7 @@ IMPROVEMENTS * [stake] offload more generic functionality from the handler into the keeper * [types] added common tag constants * [keys] improve error message when deleting non-existent key +* [gaiacli] improve error messages on `send` and `account` commands * added contributing guidelines BUG FIXES diff --git a/client/context/helpers.go b/client/context/helpers.go index e5002e0b5..e567eea7d 100644 --- a/client/context/helpers.go +++ b/client/context/helpers.go @@ -233,17 +233,52 @@ func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msgs []sdk.Msg, cdc if ctx.Async { res, err := ctx.BroadcastTxAsync(txBytes) - fmt.Println("Async tx sent. tx hash: ", res.Hash.String()) - return err + if err != nil { + return err + } + if ctx.JSON { + type toJSON struct { + TxHash string + } + valueToJSON := toJSON{res.Hash.String()} + JSON, err := cdc.MarshalJSON(valueToJSON) + if err != nil { + return err + } + fmt.Println(string(JSON)) + } else { + fmt.Println("Async tx sent. tx hash: ", res.Hash.String()) + } + return nil } res, err := ctx.BroadcastTx(txBytes) + if err != nil { + return err + } + if ctx.JSON { + type toJSON struct { + Height int64 + TxHash string + Response string + } + valueToJSON := toJSON{res.Height, res.Hash.String(), ""} + if printResponse { + valueToJSON.Response = fmt.Sprintf("%+v", res.DeliverTx) + } + JSON, err := cdc.MarshalJSON(valueToJSON) + if err != nil { + return err + } + fmt.Println(string(JSON)) + return nil + } if printResponse { fmt.Printf("Committed at block %d. Hash: %s Response:%+v \n", res.Height, res.Hash.String(), res.DeliverTx) } else { fmt.Printf("Committed at block %d. Hash: %s \n", res.Height, res.Hash.String()) } - return err + return nil } // get the next sequence for the account address diff --git a/client/context/types.go b/client/context/types.go index 017ed9565..fd407883b 100644 --- a/client/context/types.go +++ b/client/context/types.go @@ -23,6 +23,7 @@ type CoreContext struct { AccountStore string UseLedger bool Async bool + JSON bool } // WithChainID - return a copy of the context with an updated chainID diff --git a/client/context/viper.go b/client/context/viper.go index c3b83c63a..7b8546cd3 100644 --- a/client/context/viper.go +++ b/client/context/viper.go @@ -50,6 +50,7 @@ func NewCoreContextFromViper() CoreContext { AccountStore: "acc", UseLedger: viper.GetBool(client.FlagUseLedger), Async: viper.GetBool(client.FlagAsync), + JSON: viper.GetBool(client.FlagJson), } } diff --git a/client/flags.go b/client/flags.go index a8cf15e53..985359de8 100644 --- a/client/flags.go +++ b/client/flags.go @@ -17,6 +17,7 @@ const ( FlagMemo = "memo" FlagFee = "fee" FlagAsync = "async" + FlagJson = "json" ) // LineBreak can be included in a command list to provide a blank line @@ -50,6 +51,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device") c.Flags().Int64(FlagGas, 200000, "gas limit to set per-transaction") c.Flags().Bool(FlagAsync, false, "broadcast transactions asynchronously") + c.Flags().Bool(FlagJson, false, "return output in json format") } return cmds } From c708c799fd5d013620569bef3c4cda76d54d7686 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 5 Jul 2018 22:19:50 -0700 Subject: [PATCH 50/53] Add print-response flag --- CHANGELOG.md | 6 ++++-- client/context/helpers.go | 11 ++++------- client/context/types.go | 1 + client/context/viper.go | 1 + client/flags.go | 2 ++ examples/democoin/x/cool/client/cli/tx.go | 4 ++-- examples/democoin/x/pow/client/cli/tx.go | 2 +- .../democoin/x/simplestake/client/cli/commands.go | 2 +- x/bank/client/cli/sendtx.go | 2 +- x/gov/client/cli/tx.go | 8 +++++--- x/ibc/client/cli/ibctx.go | 2 +- x/slashing/client/cli/tx.go | 2 +- x/stake/client/cli/tx.go | 14 +++++++------- 13 files changed, 31 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d914eb9fe..6c06a7c03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,8 +74,10 @@ FEATURES * [gaiacli] Ledger support added - You can now use a Ledger with `gaiacli --ledger` for all key-related commands - Ledger keys can be named and tracked locally in the key DB -* [gaiacli] added an --async flag to the cli to deliver transactions without waiting for a tendermint response -* [gaiacli] added a --json flag to the cli for deliver transactions +* [gaiacli] added the following flags for commands that post transactions to the chain: + * async -- send the tx without waiting for a tendermint response + * json -- return the output in json format for increased readability + * print-response -- return the tx response. (includes fields like gas cost) IMPROVEMENTS * bank module uses go-wire codec instead of 'encoding/json' diff --git a/client/context/helpers.go b/client/context/helpers.go index e567eea7d..e0fa45580 100644 --- a/client/context/helpers.go +++ b/client/context/helpers.go @@ -224,7 +224,7 @@ func (ctx CoreContext) ensureSignBuild(name string, msgs []sdk.Msg, cdc *wire.Co } // sign and build the transaction from the msg -func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msgs []sdk.Msg, cdc *wire.Codec, printResponse bool) (err error) { +func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msgs []sdk.Msg, cdc *wire.Codec) (err error) { txBytes, err := ctx.ensureSignBuild(name, msgs, cdc) if err != nil { @@ -256,15 +256,13 @@ func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msgs []sdk.Msg, cdc return err } if ctx.JSON { + // Since JSON is intended for automated scripts, always include response in JSON mode type toJSON struct { Height int64 TxHash string Response string } - valueToJSON := toJSON{res.Height, res.Hash.String(), ""} - if printResponse { - valueToJSON.Response = fmt.Sprintf("%+v", res.DeliverTx) - } + valueToJSON := toJSON{res.Height, res.Hash.String(), fmt.Sprintf("%+v", res.DeliverTx)} JSON, err := cdc.MarshalJSON(valueToJSON) if err != nil { return err @@ -272,10 +270,9 @@ func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msgs []sdk.Msg, cdc fmt.Println(string(JSON)) return nil } - if printResponse { + if ctx.PrintResponse { fmt.Printf("Committed at block %d. Hash: %s Response:%+v \n", res.Height, res.Hash.String(), res.DeliverTx) } else { - fmt.Printf("Committed at block %d. Hash: %s \n", res.Height, res.Hash.String()) } return nil diff --git a/client/context/types.go b/client/context/types.go index fd407883b..03dd6b9d0 100644 --- a/client/context/types.go +++ b/client/context/types.go @@ -24,6 +24,7 @@ type CoreContext struct { UseLedger bool Async bool JSON bool + PrintResponse bool } // WithChainID - return a copy of the context with an updated chainID diff --git a/client/context/viper.go b/client/context/viper.go index 7b8546cd3..611ad1b92 100644 --- a/client/context/viper.go +++ b/client/context/viper.go @@ -51,6 +51,7 @@ func NewCoreContextFromViper() CoreContext { UseLedger: viper.GetBool(client.FlagUseLedger), Async: viper.GetBool(client.FlagAsync), JSON: viper.GetBool(client.FlagJson), + PrintResponse: viper.GetBool(client.FlagPrintResponse), } } diff --git a/client/flags.go b/client/flags.go index 985359de8..b96012da7 100644 --- a/client/flags.go +++ b/client/flags.go @@ -18,6 +18,7 @@ const ( FlagFee = "fee" FlagAsync = "async" FlagJson = "json" + FlagPrintResponse = "print-response" ) // LineBreak can be included in a command list to provide a blank line @@ -52,6 +53,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().Int64(FlagGas, 200000, "gas limit to set per-transaction") c.Flags().Bool(FlagAsync, false, "broadcast transactions asynchronously") c.Flags().Bool(FlagJson, false, "return output in json format") + c.Flags().Bool(FlagPrintResponse, false, "return tx response (only works with async = false)") } return cmds } diff --git a/examples/democoin/x/cool/client/cli/tx.go b/examples/democoin/x/cool/client/cli/tx.go index 9300f46c2..3e034600b 100644 --- a/examples/democoin/x/cool/client/cli/tx.go +++ b/examples/democoin/x/cool/client/cli/tx.go @@ -35,7 +35,7 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command { name := viper.GetString(client.FlagName) // build and sign the transaction, then broadcast to Tendermint - err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, false) + err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc) if err != nil { return err } @@ -67,7 +67,7 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command { msg := cool.NewMsgSetTrend(from, args[0]) // build and sign the transaction, then broadcast to Tendermint - err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, false) + err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc) if err != nil { return err } diff --git a/examples/democoin/x/pow/client/cli/tx.go b/examples/democoin/x/pow/client/cli/tx.go index 43b33bd6e..bc958ffae 100644 --- a/examples/democoin/x/pow/client/cli/tx.go +++ b/examples/democoin/x/pow/client/cli/tx.go @@ -48,7 +48,7 @@ func MineCmd(cdc *wire.Codec) *cobra.Command { name := ctx.FromAddressName // build and sign the transaction, then broadcast to Tendermint - err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc, false) + err = ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc) if err != nil { return err } diff --git a/examples/democoin/x/simplestake/client/cli/commands.go b/examples/democoin/x/simplestake/client/cli/commands.go index 197d98671..20b5d9522 100644 --- a/examples/democoin/x/simplestake/client/cli/commands.go +++ b/examples/democoin/x/simplestake/client/cli/commands.go @@ -87,7 +87,7 @@ func UnbondTxCmd(cdc *wire.Codec) *cobra.Command { func sendMsg(cdc *wire.Codec, msg sdk.Msg) error { ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) + err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } diff --git a/x/bank/client/cli/sendtx.go b/x/bank/client/cli/sendtx.go index aa51c5a19..8731de40e 100644 --- a/x/bank/client/cli/sendtx.go +++ b/x/bank/client/cli/sendtx.go @@ -70,7 +70,7 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint msg := client.BuildMsg(from, to, coins) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index cde0d7498..633890f4b 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -63,8 +63,10 @@ func GetCmdSubmitProposal(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) + // proposalID must be returned, and it is a part of response + ctx.PrintResponse = true - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, true) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } @@ -111,7 +113,7 @@ func GetCmdDeposit(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } @@ -161,7 +163,7 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } diff --git a/x/ibc/client/cli/ibctx.go b/x/ibc/client/cli/ibctx.go index e4e6a5b76..21aa3a308 100644 --- a/x/ibc/client/cli/ibctx.go +++ b/x/ibc/client/cli/ibctx.go @@ -42,7 +42,7 @@ func IBCTransferCmd(cdc *wire.Codec) *cobra.Command { } // get password - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } diff --git a/x/slashing/client/cli/tx.go b/x/slashing/client/cli/tx.go index eaeaf3eb8..c73b2e162 100644 --- a/x/slashing/client/cli/tx.go +++ b/x/slashing/client/cli/tx.go @@ -27,7 +27,7 @@ func GetCmdUnrevoke(cdc *wire.Codec) *cobra.Command { msg := slashing.NewMsgUnrevoke(validatorAddr) // build and sign the transaction, then broadcast to Tendermint - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index d7f91e29d..9b8acb8cc 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -53,7 +53,7 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command { msg := stake.NewMsgCreateValidator(validatorAddr, pk, amount, description) // build and sign the transaction, then broadcast to Tendermint - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } @@ -90,7 +90,7 @@ func GetCmdEditValidator(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } @@ -129,7 +129,7 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } @@ -193,7 +193,7 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } @@ -277,7 +277,7 @@ func GetCmdCompleteRedelegate(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } @@ -334,7 +334,7 @@ func GetCmdBeginUnbonding(storeName string, cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } @@ -370,7 +370,7 @@ func GetCmdCompleteUnbonding(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) - err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc, false) + err = ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } From 12c1eb4d319da41f40438a68cd7ebd526d6ce393 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 5 Jul 2018 22:22:50 -0700 Subject: [PATCH 51/53] gov/client: rename submitproposal to submit-proposal It is standard in the sdk to use a dash for subcommands / flags with multiple words. This makes submitproposal comply with that. --- cmd/gaia/cli_test/cli_test.go | 2 +- x/gov/client/cli/tx.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 93ef825aa..18e967bd3 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -181,7 +181,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) { fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooCech, flags)) require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64()) - executeWrite(t, fmt.Sprintf("gaiacli gov submitproposal %v --proposer=%v --deposit=5steak --type=Text --title=Test --description=test --from=foo", flags, fooCech), pass) + executeWrite(t, fmt.Sprintf("gaiacli gov submit-proposal %v --proposer=%v --deposit=5steak --type=Text --title=Test --description=test --from=foo", flags, fooCech), pass) tests.WaitForNextHeightTM(port) fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooCech, flags)) diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 00933284e..9b918fb65 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -29,7 +29,7 @@ const ( // submit a proposal tx func GetCmdSubmitProposal(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ - Use: "submitproposal", + Use: "submit-proposal", Short: "Submit a proposal along with an initial deposit", RunE: func(cmd *cobra.Command, args []string) error { title := viper.GetString(flagTitle) From 6f8f222ef67bb39d4dfc3bd22128ccca985ee800 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Fri, 6 Jul 2018 13:19:11 -0700 Subject: [PATCH 52/53] Merge pull request #1175: Randomized Module Testing * WIP, ammend this later * Add randomized testing suite * Fix linting * Auth invariant check, method to take in seed, way to run invariant check less frequently * Fix merge conflicts * Update bank * Fix error on zero input by skipping it * Add PeriodicInvariant Function * Abstract verification / send functionality * Fix liniting errors (PeriodicInvariant godoc) * Update formatting and docs of randomization * Minor refactor, update godocs * Update godoc for mock * Export TestAndRunTx * fix cyclic dependencies * Address PR most pr comments * Fix merge conflict: Bring back codec.seal * remove debug code, fix linting * Fix merge conflicts --- CHANGELOG.md | 3 + baseapp/baseapp_test.go | 320 ---------------------------- baseapp/multimsg_test.go | 352 +++++++++++++++++++++++++++++++ x/bank/app_test.go | 24 ++- x/bank/bench_test.go | 13 ++ x/bank/test_helpers.go | 150 +++++++++++++ x/mock/app.go | 85 +++++++- x/mock/doc.go | 15 ++ x/mock/random_simulate_blocks.go | 95 +++++++++ x/mock/types.go | 38 ++++ 10 files changed, 757 insertions(+), 338 deletions(-) create mode 100644 baseapp/multimsg_test.go create mode 100644 x/bank/test_helpers.go create mode 100644 x/mock/doc.go create mode 100644 x/mock/random_simulate_blocks.go create mode 100644 x/mock/types.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c06a7c03..7012336d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,9 @@ FEATURES * [gaiacli] Ledger support added - You can now use a Ledger with `gaiacli --ledger` for all key-related commands - Ledger keys can be named and tracked locally in the key DB +* [testing] created a randomized testing framework. + - Currently bank has limited functionality in the framework + - Auth has its invariants checked within the framework * [gaiacli] added the following flags for commands that post transactions to the chain: * async -- send the tx without waiting for a tendermint response * json -- return the output in json format for increased readability diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index b8c42c4d2..2ed89c53f 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -1,7 +1,6 @@ package baseapp import ( - "encoding/json" "fmt" "os" "testing" @@ -19,7 +18,6 @@ import ( 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" ) func defaultLogger() log.Logger { @@ -651,324 +649,6 @@ func TestValidatorChange(t *testing.T) { //---------------------------------------- -// Use burn and send msg types to test multiple msgs in one tx -type testBurnMsg struct { - Addr sdk.Address - Amount sdk.Coins -} - -const msgType3 = "burn" - -func (msg testBurnMsg) Type() string { return msgType3 } -func (msg testBurnMsg) GetSignBytes() []byte { - bz, _ := json.Marshal(msg) - return sdk.MustSortJSON(bz) -} -func (msg testBurnMsg) ValidateBasic() sdk.Error { - if msg.Addr == nil { - return sdk.ErrInvalidAddress("Cannot use nil as Address") - } - return nil -} -func (msg testBurnMsg) GetSigners() []sdk.Address { - return []sdk.Address{msg.Addr} -} - -type testSendMsg struct { - Sender sdk.Address - Receiver sdk.Address - Amount sdk.Coins -} - -const msgType4 = "send" - -func (msg testSendMsg) Type() string { return msgType4 } -func (msg testSendMsg) GetSignBytes() []byte { - bz, _ := json.Marshal(msg) - return sdk.MustSortJSON(bz) -} -func (msg testSendMsg) ValidateBasic() sdk.Error { - if msg.Sender == nil || msg.Receiver == nil { - return sdk.ErrInvalidAddress("Cannot use nil as Address") - } - return nil -} -func (msg testSendMsg) GetSigners() []sdk.Address { - return []sdk.Address{msg.Sender} -} - -// Simple Handlers for burn and send - -func newHandleBurn(keeper bank.Keeper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { - burnMsg := msg.(testBurnMsg) - _, _, err := keeper.SubtractCoins(ctx, burnMsg.Addr, burnMsg.Amount) - if err != nil { - return err.Result() - } - return sdk.Result{} - } -} - -func newHandleSpend(keeper bank.Keeper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { - spendMsg := msg.(testSendMsg) - _, _, err := keeper.SubtractCoins(ctx, spendMsg.Sender, spendMsg.Amount) - if err != nil { - return err.Result() - } - _, _, err = keeper.AddCoins(ctx, spendMsg.Receiver, spendMsg.Amount) - if err != nil { - return err.Result() - } - return sdk.Result{} - } -} - -// generate a signed transaction -func GenTx(chainID string, msgs []sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKey) auth.StdTx { - // make the transaction free - fee := auth.StdFee{ - sdk.Coins{{"foocoin", sdk.NewInt(0)}}, - 100000, - } - - sigs := make([]auth.StdSignature, len(priv)) - for i, p := range priv { - sig, err := p.Sign(auth.StdSignBytes(chainID, accnums[i], seq[i], fee, msgs, "")) - // TODO: replace with proper error handling: - if err != nil { - panic(err) - } - sigs[i] = auth.StdSignature{ - PubKey: p.PubKey(), - Signature: sig, - AccountNumber: accnums[i], - Sequence: seq[i], - } - } - return auth.NewStdTx(msgs, fee, sigs, "") -} - -// spin up simple app for testing -type testApp struct { - *BaseApp - accountMapper auth.AccountMapper - accountKeeper bank.Keeper -} - -func newTestApp(name string) testApp { - return testApp{ - BaseApp: newBaseApp(name), - } -} - -func MakeCodec() *wire.Codec { - cdc := wire.NewCodec() - cdc.RegisterInterface((*sdk.Msg)(nil), nil) - crypto.RegisterAmino(cdc) - cdc.RegisterInterface((*auth.Account)(nil), nil) - cdc.RegisterConcrete(&auth.BaseAccount{}, "cosmos-sdk/BaseAccount", nil) - cdc.Seal() - return cdc -} - -// tests multiple msgs of same type from same address in single tx -func TestMultipleBurn(t *testing.T) { - // Create app. - app := newTestApp(t.Name()) - capKey := sdk.NewKVStoreKey("key") - app.MountStoresIAVL(capKey) - app.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) { - var tx auth.StdTx - fromJSON(txBytes, &tx) - return tx, nil - }) - - err := app.LoadLatestVersion(capKey) - if err != nil { - panic(err) - } - - app.accountMapper = auth.NewAccountMapper(app.cdc, capKey, &auth.BaseAccount{}) - app.accountKeeper = bank.NewKeeper(app.accountMapper) - - app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, auth.FeeCollectionKeeper{})) - - app.Router(). - AddRoute("burn", newHandleBurn(app.accountKeeper)). - AddRoute("send", newHandleSpend(app.accountKeeper)) - - app.InitChain(abci.RequestInitChain{}) - app.BeginBlock(abci.RequestBeginBlock{}) - - // Set chain-id - app.deliverState.ctx = app.deliverState.ctx.WithChainID(t.Name()) - - priv := makePrivKey("my secret") - addr := priv.PubKey().Address() - - app.accountKeeper.AddCoins(app.deliverState.ctx, addr, sdk.Coins{{"foocoin", sdk.NewInt(100)}}) - require.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, app.accountKeeper.GetCoins(app.deliverState.ctx, addr), "Balance did not update") - - msg := testBurnMsg{addr, sdk.Coins{{"foocoin", sdk.NewInt(50)}}} - tx := GenTx(t.Name(), []sdk.Msg{msg, msg}, []int64{0}, []int64{0}, priv) - - res := app.Deliver(tx) - - require.Equal(t, true, res.IsOK(), res.Log) - require.Equal(t, sdk.Coins(nil), app.accountKeeper.GetCoins(app.deliverState.ctx, addr), "Double burn did not work") -} - -// tests multiples msgs of same type from different addresses in single tx -func TestBurnMultipleOwners(t *testing.T) { - // Create app. - app := newTestApp(t.Name()) - capKey := sdk.NewKVStoreKey("key") - app.MountStoresIAVL(capKey) - app.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) { - var tx auth.StdTx - fromJSON(txBytes, &tx) - return tx, nil - }) - - err := app.LoadLatestVersion(capKey) - if err != nil { - panic(err) - } - - app.accountMapper = auth.NewAccountMapper(app.cdc, capKey, &auth.BaseAccount{}) - app.accountKeeper = bank.NewKeeper(app.accountMapper) - - app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, auth.FeeCollectionKeeper{})) - - app.Router(). - AddRoute("burn", newHandleBurn(app.accountKeeper)). - AddRoute("send", newHandleSpend(app.accountKeeper)) - - app.InitChain(abci.RequestInitChain{}) - app.BeginBlock(abci.RequestBeginBlock{}) - - // Set chain-id - app.deliverState.ctx = app.deliverState.ctx.WithChainID(t.Name()) - - priv1 := makePrivKey("my secret 1") - addr1 := priv1.PubKey().Address() - - priv2 := makePrivKey("my secret 2") - addr2 := priv2.PubKey().Address() - - // fund accounts - app.accountKeeper.AddCoins(app.deliverState.ctx, addr1, sdk.Coins{{"foocoin", sdk.NewInt(100)}}) - app.accountKeeper.AddCoins(app.deliverState.ctx, addr2, sdk.Coins{{"foocoin", sdk.NewInt(100)}}) - - require.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, app.accountKeeper.GetCoins(app.deliverState.ctx, addr1), "Balance1 did not update") - require.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, app.accountKeeper.GetCoins(app.deliverState.ctx, addr2), "Balance2 did not update") - - msg1 := testBurnMsg{addr1, sdk.Coins{{"foocoin", sdk.NewInt(100)}}} - msg2 := testBurnMsg{addr2, sdk.Coins{{"foocoin", sdk.NewInt(100)}}} - - // test wrong signers: Address 1 signs both messages - tx := GenTx(t.Name(), []sdk.Msg{msg1, msg2}, []int64{0, 0}, []int64{0, 0}, priv1, priv1) - - res := app.Deliver(tx) - require.Equal(t, sdk.ABCICodeType(0x10003), res.Code, "Wrong signatures passed") - - require.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, app.accountKeeper.GetCoins(app.deliverState.ctx, addr1), "Balance1 changed after invalid sig") - require.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, app.accountKeeper.GetCoins(app.deliverState.ctx, addr2), "Balance2 changed after invalid sig") - - // test valid tx - tx = GenTx(t.Name(), []sdk.Msg{msg1, msg2}, []int64{0, 1}, []int64{1, 0}, priv1, priv2) - - res = app.Deliver(tx) - require.Equal(t, true, res.IsOK(), res.Log) - - require.Equal(t, sdk.Coins(nil), app.accountKeeper.GetCoins(app.deliverState.ctx, addr1), "Balance1 did not change after valid tx") - require.Equal(t, sdk.Coins(nil), app.accountKeeper.GetCoins(app.deliverState.ctx, addr2), "Balance2 did not change after valid tx") -} - -// tests different msg types in single tx with different addresses -func TestSendBurn(t *testing.T) { - // Create app. - app := newTestApp(t.Name()) - capKey := sdk.NewKVStoreKey("key") - app.MountStoresIAVL(capKey) - app.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) { - var tx auth.StdTx - fromJSON(txBytes, &tx) - return tx, nil - }) - - err := app.LoadLatestVersion(capKey) - if err != nil { - panic(err) - } - - app.accountMapper = auth.NewAccountMapper(app.cdc, capKey, &auth.BaseAccount{}) - app.accountKeeper = bank.NewKeeper(app.accountMapper) - - app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, auth.FeeCollectionKeeper{})) - - app.Router(). - AddRoute("burn", newHandleBurn(app.accountKeeper)). - AddRoute("send", newHandleSpend(app.accountKeeper)) - - app.InitChain(abci.RequestInitChain{}) - app.BeginBlock(abci.RequestBeginBlock{}) - - // Set chain-id - app.deliverState.ctx = app.deliverState.ctx.WithChainID(t.Name()) - - priv1 := makePrivKey("my secret 1") - addr1 := priv1.PubKey().Address() - - priv2 := makePrivKey("my secret 2") - addr2 := priv2.PubKey().Address() - - // fund accounts - app.accountKeeper.AddCoins(app.deliverState.ctx, addr1, sdk.Coins{{"foocoin", sdk.NewInt(100)}}) - acc := app.accountMapper.NewAccountWithAddress(app.deliverState.ctx, addr2) - app.accountMapper.SetAccount(app.deliverState.ctx, acc) - - require.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, app.accountKeeper.GetCoins(app.deliverState.ctx, addr1), "Balance1 did not update") - - sendMsg := testSendMsg{addr1, addr2, sdk.Coins{{"foocoin", sdk.NewInt(50)}}} - - msg1 := testBurnMsg{addr1, sdk.Coins{{"foocoin", sdk.NewInt(50)}}} - msg2 := testBurnMsg{addr2, sdk.Coins{{"foocoin", sdk.NewInt(50)}}} - - // send then burn - tx := GenTx(t.Name(), []sdk.Msg{sendMsg, msg2, msg1}, []int64{0, 1}, []int64{0, 0}, priv1, priv2) - - res := app.Deliver(tx) - require.Equal(t, true, res.IsOK(), res.Log) - - require.Equal(t, sdk.Coins(nil), app.accountKeeper.GetCoins(app.deliverState.ctx, addr1), "Balance1 did not change after valid tx") - require.Equal(t, sdk.Coins(nil), app.accountKeeper.GetCoins(app.deliverState.ctx, addr2), "Balance2 did not change after valid tx") - - // Check that state is only updated if all msgs in tx pass. - app.accountKeeper.AddCoins(app.deliverState.ctx, addr1, sdk.Coins{{"foocoin", sdk.NewInt(50)}}) - - // burn then send - tx = GenTx(t.Name(), []sdk.Msg{msg1, sendMsg}, []int64{0}, []int64{1}, priv1) - - res = app.Deliver(tx) - - // Double check that state is correct after Commit. - app.EndBlock(abci.RequestEndBlock{}) - app.Commit() - - app.BeginBlock(abci.RequestBeginBlock{}) - app.deliverState.ctx = app.deliverState.ctx.WithChainID(t.Name()) - - require.Equal(t, sdk.ABCICodeType(0x1000a), res.Code, "Allowed tx to pass with insufficient funds") - - require.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(50)}}, app.accountKeeper.GetCoins(app.deliverState.ctx, addr1), "Allowed valid msg to pass in invalid tx") - require.Equal(t, sdk.Coins(nil), app.accountKeeper.GetCoins(app.deliverState.ctx, addr2), "Balance2 changed after invalid tx") -} - -//---------------------------------------- - func randPower() int64 { return cmn.RandInt64() } diff --git a/baseapp/multimsg_test.go b/baseapp/multimsg_test.go new file mode 100644 index 000000000..581da4b17 --- /dev/null +++ b/baseapp/multimsg_test.go @@ -0,0 +1,352 @@ +package baseapp + +import ( + "encoding/json" + "fmt" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/wire" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" +) + +// tests multiple msgs of same type from same address in single tx +func TestMultipleBurn(t *testing.T) { + // Create app. + app := newTestApp(t.Name()) + capKey := sdk.NewKVStoreKey("key") + app.MountStoresIAVL(capKey) + app.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) { + var tx auth.StdTx + fromJSON(txBytes, &tx) + return tx, nil + }) + + err := app.LoadLatestVersion(capKey) + if err != nil { + panic(err) + } + + app.accountMapper = auth.NewAccountMapper(app.cdc, capKey, &auth.BaseAccount{}) + + app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, auth.FeeCollectionKeeper{})) + + app.Router(). + AddRoute("burn", newHandleBurn(app.accountMapper)). + AddRoute("send", newHandleSpend(app.accountMapper)) + + app.InitChain(abci.RequestInitChain{}) + app.BeginBlock(abci.RequestBeginBlock{}) + + // Set chain-id + app.deliverState.ctx = app.deliverState.ctx.WithChainID(t.Name()) + + priv := makePrivKey("my secret") + addr := priv.PubKey().Address() + + addCoins(app.accountMapper, app.deliverState.ctx, addr, sdk.Coins{{"foocoin", sdk.NewInt(100)}}) + + require.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, app.accountMapper.GetAccount(app.deliverState.ctx, addr).GetCoins(), "Balance did not update") + + msg := testBurnMsg{addr, sdk.Coins{{"foocoin", sdk.NewInt(50)}}} + tx := GenTx(t.Name(), []sdk.Msg{msg, msg}, []int64{0}, []int64{0}, priv) + + res := app.Deliver(tx) + + require.Equal(t, true, res.IsOK(), res.Log) + require.Equal(t, sdk.Coins(nil), getCoins(app.accountMapper, app.deliverState.ctx, addr), "Double burn did not work") +} + +// tests multiples msgs of same type from different addresses in single tx +func TestBurnMultipleOwners(t *testing.T) { + // Create app. + app := newTestApp(t.Name()) + capKey := sdk.NewKVStoreKey("key") + app.MountStoresIAVL(capKey) + app.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) { + var tx auth.StdTx + fromJSON(txBytes, &tx) + return tx, nil + }) + + err := app.LoadLatestVersion(capKey) + if err != nil { + panic(err) + } + + app.accountMapper = auth.NewAccountMapper(app.cdc, capKey, &auth.BaseAccount{}) + + app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, auth.FeeCollectionKeeper{})) + + app.Router(). + AddRoute("burn", newHandleBurn(app.accountMapper)). + AddRoute("send", newHandleSpend(app.accountMapper)) + + app.InitChain(abci.RequestInitChain{}) + app.BeginBlock(abci.RequestBeginBlock{}) + + // Set chain-id + app.deliverState.ctx = app.deliverState.ctx.WithChainID(t.Name()) + + priv1 := makePrivKey("my secret 1") + addr1 := priv1.PubKey().Address() + + priv2 := makePrivKey("my secret 2") + addr2 := priv2.PubKey().Address() + + // fund accounts + addCoins(app.accountMapper, app.deliverState.ctx, addr1, sdk.Coins{{"foocoin", sdk.NewInt(100)}}) + addCoins(app.accountMapper, app.deliverState.ctx, addr2, sdk.Coins{{"foocoin", sdk.NewInt(100)}}) + + require.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, getCoins(app.accountMapper, app.deliverState.ctx, addr1), "Balance1 did not update") + require.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, getCoins(app.accountMapper, app.deliverState.ctx, addr2), "Balance2 did not update") + + msg1 := testBurnMsg{addr1, sdk.Coins{{"foocoin", sdk.NewInt(100)}}} + msg2 := testBurnMsg{addr2, sdk.Coins{{"foocoin", sdk.NewInt(100)}}} + + // test wrong signers: Address 1 signs both messages + tx := GenTx(t.Name(), []sdk.Msg{msg1, msg2}, []int64{0, 0}, []int64{0, 0}, priv1, priv1) + + res := app.Deliver(tx) + require.Equal(t, sdk.ABCICodeType(0x10003), res.Code, "Wrong signatures passed") + + require.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, getCoins(app.accountMapper, app.deliverState.ctx, addr1), "Balance1 changed after invalid sig") + require.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, getCoins(app.accountMapper, app.deliverState.ctx, addr2), "Balance2 changed after invalid sig") + + // test valid tx + tx = GenTx(t.Name(), []sdk.Msg{msg1, msg2}, []int64{0, 1}, []int64{1, 0}, priv1, priv2) + + res = app.Deliver(tx) + require.Equal(t, true, res.IsOK(), res.Log) + + require.Equal(t, sdk.Coins(nil), getCoins(app.accountMapper, app.deliverState.ctx, addr1), "Balance1 did not change after valid tx") + require.Equal(t, sdk.Coins(nil), getCoins(app.accountMapper, app.deliverState.ctx, addr2), "Balance2 did not change after valid tx") +} + +func getCoins(am auth.AccountMapper, ctx sdk.Context, addr sdk.Address) sdk.Coins { + return am.GetAccount(ctx, addr).GetCoins() +} + +func addCoins(am auth.AccountMapper, ctx sdk.Context, addr sdk.Address, coins sdk.Coins) sdk.Error { + acc := am.GetAccount(ctx, addr) + if acc == nil { + acc = am.NewAccountWithAddress(ctx, addr) + } + err := acc.SetCoins(acc.GetCoins().Plus(coins)) + if err != nil { + fmt.Println(err) + return sdk.ErrInternal(err.Error()) + } + am.SetAccount(ctx, acc) + return nil +} + +// tests different msg types in single tx with different addresses +func TestSendBurn(t *testing.T) { + // Create app. + app := newTestApp(t.Name()) + capKey := sdk.NewKVStoreKey("key") + app.MountStoresIAVL(capKey) + app.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) { + var tx auth.StdTx + fromJSON(txBytes, &tx) + return tx, nil + }) + + err := app.LoadLatestVersion(capKey) + if err != nil { + panic(err) + } + + app.accountMapper = auth.NewAccountMapper(app.cdc, capKey, &auth.BaseAccount{}) + + app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, auth.FeeCollectionKeeper{})) + + app.Router(). + AddRoute("burn", newHandleBurn(app.accountMapper)). + AddRoute("send", newHandleSpend(app.accountMapper)) + + app.InitChain(abci.RequestInitChain{}) + app.BeginBlock(abci.RequestBeginBlock{}) + + // Set chain-id + app.deliverState.ctx = app.deliverState.ctx.WithChainID(t.Name()) + + priv1 := makePrivKey("my secret 1") + addr1 := priv1.PubKey().Address() + + priv2 := makePrivKey("my secret 2") + addr2 := priv2.PubKey().Address() + + // fund accounts + addCoins(app.accountMapper, app.deliverState.ctx, addr1, sdk.Coins{{"foocoin", sdk.NewInt(100)}}) + acc := app.accountMapper.NewAccountWithAddress(app.deliverState.ctx, addr2) + app.accountMapper.SetAccount(app.deliverState.ctx, acc) + + require.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, getCoins(app.accountMapper, app.deliverState.ctx, addr1), "Balance1 did not update") + + sendMsg := testSendMsg{addr1, addr2, sdk.Coins{{"foocoin", sdk.NewInt(50)}}} + + msg1 := testBurnMsg{addr1, sdk.Coins{{"foocoin", sdk.NewInt(50)}}} + msg2 := testBurnMsg{addr2, sdk.Coins{{"foocoin", sdk.NewInt(50)}}} + + // send then burn + tx := GenTx(t.Name(), []sdk.Msg{sendMsg, msg2, msg1}, []int64{0, 1}, []int64{0, 0}, priv1, priv2) + + res := app.Deliver(tx) + require.Equal(t, true, res.IsOK(), res.Log) + + require.Equal(t, sdk.Coins(nil), getCoins(app.accountMapper, app.deliverState.ctx, addr1), "Balance1 did not change after valid tx") + require.Equal(t, sdk.Coins(nil), getCoins(app.accountMapper, app.deliverState.ctx, addr2), "Balance2 did not change after valid tx") + + // Check that state is only updated if all msgs in tx pass. + addCoins(app.accountMapper, app.deliverState.ctx, addr1, sdk.Coins{{"foocoin", sdk.NewInt(50)}}) + + // burn then send, with fee thats greater than individual tx, but less than combination + tx = GenTxWithFeeAmt(50000, t.Name(), []sdk.Msg{msg1, sendMsg}, []int64{0}, []int64{1}, priv1) + + res = app.Deliver(tx) + require.Equal(t, sdk.ABCICodeType(0x1000c), res.Code, "Allowed tx to pass with insufficient funds") + + // Double check that state is correct after Commit. + app.EndBlock(abci.RequestEndBlock{}) + app.Commit() + + app.BeginBlock(abci.RequestBeginBlock{}) + app.deliverState.ctx = app.deliverState.ctx.WithChainID(t.Name()) + + require.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(50)}}, getCoins(app.accountMapper, app.deliverState.ctx, addr1), "Allowed valid msg to pass in invalid tx") + require.Equal(t, sdk.Coins(nil), getCoins(app.accountMapper, app.deliverState.ctx, addr2), "Balance2 changed after invalid tx") +} + +// Use burn and send msg types to test multiple msgs in one tx +type testBurnMsg struct { + Addr sdk.Address + Amount sdk.Coins +} + +const msgType3 = "burn" + +func (msg testBurnMsg) Type() string { return msgType3 } +func (msg testBurnMsg) GetSignBytes() []byte { + bz, _ := json.Marshal(msg) + return sdk.MustSortJSON(bz) +} +func (msg testBurnMsg) ValidateBasic() sdk.Error { + if msg.Addr == nil { + return sdk.ErrInvalidAddress("Cannot use nil as Address") + } + return nil +} +func (msg testBurnMsg) GetSigners() []sdk.Address { + return []sdk.Address{msg.Addr} +} + +type testSendMsg struct { + Sender sdk.Address + Receiver sdk.Address + Amount sdk.Coins +} + +const msgType4 = "send" + +func (msg testSendMsg) Type() string { return msgType4 } +func (msg testSendMsg) GetSignBytes() []byte { + bz, _ := json.Marshal(msg) + return sdk.MustSortJSON(bz) +} +func (msg testSendMsg) ValidateBasic() sdk.Error { + if msg.Sender == nil || msg.Receiver == nil { + return sdk.ErrInvalidAddress("Cannot use nil as Address") + } + return nil +} +func (msg testSendMsg) GetSigners() []sdk.Address { + return []sdk.Address{msg.Sender} +} + +// Simple Handlers for burn and send + +func newHandleBurn(am auth.AccountMapper) sdk.Handler { + return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + ctx.GasMeter().ConsumeGas(20000, "burning coins") + burnMsg := msg.(testBurnMsg) + err := addCoins(am, ctx, burnMsg.Addr, burnMsg.Amount.Negative()) + if err != nil { + return err.Result() + } + return sdk.Result{} + } +} + +func newHandleSpend(am auth.AccountMapper) sdk.Handler { + return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + ctx.GasMeter().ConsumeGas(40000, "spending coins") + spendMsg := msg.(testSendMsg) + err := addCoins(am, ctx, spendMsg.Sender, spendMsg.Amount.Negative()) + if err != nil { + return err.Result() + } + + err = addCoins(am, ctx, spendMsg.Receiver, spendMsg.Amount) + if err != nil { + return err.Result() + } + return sdk.Result{} + } +} + +// generate a signed transaction +func GenTx(chainID string, msgs []sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKey) auth.StdTx { + return GenTxWithFeeAmt(100000, chainID, msgs, accnums, seq, priv...) +} + +// generate a signed transaction with the given fee amount +func GenTxWithFeeAmt(feeAmt int64, chainID string, msgs []sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKey) auth.StdTx { + // make the transaction free + fee := auth.StdFee{ + sdk.Coins{{"foocoin", sdk.NewInt(0)}}, + feeAmt, + } + + sigs := make([]auth.StdSignature, len(priv)) + for i, p := range priv { + sig, err := p.Sign(auth.StdSignBytes(chainID, accnums[i], seq[i], fee, msgs, "")) + // TODO: replace with proper error handling: + if err != nil { + panic(err) + } + sigs[i] = auth.StdSignature{ + PubKey: p.PubKey(), + Signature: sig, + AccountNumber: accnums[i], + Sequence: seq[i], + } + } + return auth.NewStdTx(msgs, fee, sigs, "") +} + +// spin up simple app for testing +type testApp struct { + *BaseApp + accountMapper auth.AccountMapper +} + +func newTestApp(name string) testApp { + return testApp{ + BaseApp: newBaseApp(name), + } +} + +func MakeCodec() *wire.Codec { + cdc := wire.NewCodec() + cdc.RegisterInterface((*sdk.Msg)(nil), nil) + crypto.RegisterAmino(cdc) + cdc.RegisterInterface((*auth.Account)(nil), nil) + cdc.RegisterConcrete(&auth.BaseAccount{}, "cosmos-sdk/BaseAccount", nil) + cdc.Seal() + return cdc +} diff --git a/x/bank/app_test.go b/x/bank/app_test.go index 425e9aa2d..a89806d12 100644 --- a/x/bank/app_test.go +++ b/x/bank/app_test.go @@ -5,6 +5,8 @@ import ( "github.com/stretchr/testify/require" + "math/rand" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/mock" @@ -81,17 +83,19 @@ func getMockApp(t *testing.T) *mock.App { return mapp } -// getBenchmarkMockApp initializes a mock application for this module, for purposes of benchmarking -// Any long term API support commitments do not apply to this function. -func getBenchmarkMockApp() (*mock.App, error) { - mapp := mock.NewApp() +func TestBankWithRandomMessages(t *testing.T) { + mapp := getMockApp(t) + setup := func(r *rand.Rand, keys []crypto.PrivKey) { + return + } - RegisterWire(mapp.Cdc) - coinKeeper := NewKeeper(mapp.AccountMapper) - mapp.Router().AddRoute("bank", NewHandler(coinKeeper)) - - err := mapp.CompleteSetup([]*sdk.KVStoreKey{}) - return mapp, err + mapp.RandomizedTesting( + t, + []mock.TestAndRunTx{TestAndRunSingleInputMsgSend}, + []mock.RandSetup{setup}, + []mock.Invariant{ModuleInvariants}, + 100, 30, 30, + ) } func TestMsgSendWithAccounts(t *testing.T) { diff --git a/x/bank/bench_test.go b/x/bank/bench_test.go index be8319f9f..b90d56955 100644 --- a/x/bank/bench_test.go +++ b/x/bank/bench_test.go @@ -10,6 +10,19 @@ import ( abci "github.com/tendermint/tendermint/abci/types" ) +// getBenchmarkMockApp initializes a mock application for this module, for purposes of benchmarking +// Any long term API support commitments do not apply to this function. +func getBenchmarkMockApp() (*mock.App, error) { + mapp := mock.NewApp() + + RegisterWire(mapp.Cdc) + coinKeeper := NewKeeper(mapp.AccountMapper) + mapp.Router().AddRoute("bank", NewHandler(coinKeeper)) + + err := mapp.CompleteSetup([]*sdk.KVStoreKey{}) + return mapp, err +} + func BenchmarkOneBankSendTxPerBlock(b *testing.B) { benchmarkApp, _ := getBenchmarkMockApp() diff --git a/x/bank/test_helpers.go b/x/bank/test_helpers.go new file mode 100644 index 000000000..ecaae6281 --- /dev/null +++ b/x/bank/test_helpers.go @@ -0,0 +1,150 @@ +package bank + +import ( + "errors" + "fmt" + "math/big" + "math/rand" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/mock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" +) + +// ModuleInvariants runs all invariants of the bank module. +// Currently runs non-negative balance invariant and TotalCoinsInvariant +func ModuleInvariants(t *testing.T, app *mock.App, log string) { + NonnegativeBalanceInvariant(t, app, log) + TotalCoinsInvariant(t, app, log) +} + +// NonnegativeBalanceInvariant checks that all accounts in the application have non-negative balances +func NonnegativeBalanceInvariant(t *testing.T, app *mock.App, log string) { + ctx := app.NewContext(false, abci.Header{}) + accts := mock.GetAllAccounts(app.AccountMapper, ctx) + for _, acc := range accts { + coins := acc.GetCoins() + assert.True(t, coins.IsNotNegative(), + fmt.Sprintf("%s has a negative denomination of %s\n%s", + acc.GetAddress().String(), + coins.String(), + log), + ) + } +} + +// TotalCoinsInvariant checks that the sum of the coins across all accounts +// is what is expected +func TotalCoinsInvariant(t *testing.T, app *mock.App, log string) { + ctx := app.BaseApp.NewContext(false, abci.Header{}) + totalCoins := sdk.Coins{} + + chkAccount := func(acc auth.Account) bool { + coins := acc.GetCoins() + totalCoins = totalCoins.Plus(coins) + return false + } + + app.AccountMapper.IterateAccounts(ctx, chkAccount) + require.Equal(t, app.TotalCoinsSupply, totalCoins, log) +} + +// TestAndRunSingleInputMsgSend tests and runs a single msg send, with one input and one output, where both +// accounts already exist. +func TestAndRunSingleInputMsgSend(t *testing.T, r *rand.Rand, app *mock.App, ctx sdk.Context, keys []crypto.PrivKey, log string) (action string, err sdk.Error) { + fromKey := keys[r.Intn(len(keys))] + fromAddr := fromKey.PubKey().Address() + toKey := keys[r.Intn(len(keys))] + // Disallow sending money to yourself + for { + if !fromKey.Equals(toKey) { + break + } + toKey = keys[r.Intn(len(keys))] + } + toAddr := toKey.PubKey().Address() + initFromCoins := app.AccountMapper.GetAccount(ctx, fromAddr).GetCoins() + + denomIndex := r.Intn(len(initFromCoins)) + amt, goErr := randPositiveInt(r, initFromCoins[denomIndex].Amount) + if goErr != nil { + return "skipping bank send due to account having no coins of denomination " + initFromCoins[denomIndex].Denom, nil + } + + action = fmt.Sprintf("%s is sending %s %s to %s", + fromAddr.String(), + amt.String(), + initFromCoins[denomIndex].Denom, + toAddr.String(), + ) + log = fmt.Sprintf("%s\n%s", log, action) + + coins := sdk.Coins{{initFromCoins[denomIndex].Denom, amt}} + var msg = MsgSend{ + Inputs: []Input{NewInput(fromAddr, coins)}, + Outputs: []Output{NewOutput(toAddr, coins)}, + } + sendAndVerifyMsgSend(t, app, msg, ctx, log, []crypto.PrivKey{fromKey}) + + return action, nil +} + +// Sends and verifies the transition of a msg send. This fails if there are repeated inputs or outputs +func sendAndVerifyMsgSend(t *testing.T, app *mock.App, msg MsgSend, ctx sdk.Context, log string, privkeys []crypto.PrivKey) { + initialInputAddrCoins := make([]sdk.Coins, len(msg.Inputs)) + initialOutputAddrCoins := make([]sdk.Coins, len(msg.Outputs)) + AccountNumbers := make([]int64, len(msg.Inputs)) + SequenceNumbers := make([]int64, len(msg.Inputs)) + + for i := 0; i < len(msg.Inputs); i++ { + acc := app.AccountMapper.GetAccount(ctx, msg.Inputs[i].Address) + AccountNumbers[i] = acc.GetAccountNumber() + SequenceNumbers[i] = acc.GetSequence() + initialInputAddrCoins[i] = acc.GetCoins() + } + for i := 0; i < len(msg.Outputs); i++ { + acc := app.AccountMapper.GetAccount(ctx, msg.Outputs[i].Address) + initialOutputAddrCoins[i] = acc.GetCoins() + } + tx := mock.GenTx([]sdk.Msg{msg}, + AccountNumbers, + SequenceNumbers, + privkeys...) + res := app.Deliver(tx) + if !res.IsOK() { + // TODO: Do this in a more 'canonical' way + fmt.Println(res) + fmt.Println(log) + t.FailNow() + } + + for i := 0; i < len(msg.Inputs); i++ { + terminalInputCoins := app.AccountMapper.GetAccount(ctx, msg.Inputs[i].Address).GetCoins() + require.Equal(t, + initialInputAddrCoins[i].Minus(msg.Inputs[i].Coins), + terminalInputCoins, + fmt.Sprintf("Input #%d had an incorrect amount of coins\n%s", i, log), + ) + } + for i := 0; i < len(msg.Outputs); i++ { + terminalOutputCoins := app.AccountMapper.GetAccount(ctx, msg.Outputs[i].Address).GetCoins() + require.Equal(t, + initialOutputAddrCoins[i].Plus(msg.Outputs[i].Coins), + terminalOutputCoins, + fmt.Sprintf("Output #%d had an incorrect amount of coins\n%s", i, log), + ) + } +} + +func randPositiveInt(r *rand.Rand, max sdk.Int) (sdk.Int, error) { + if !max.GT(sdk.OneInt()) { + return sdk.Int{}, errors.New("max too small") + } + max = max.Sub(sdk.OneInt()) + return sdk.NewIntFromBigInt(new(big.Int).Rand(r, max.BigInt())).Add(sdk.OneInt()), nil +} diff --git a/x/mock/app.go b/x/mock/app.go index e16a32268..dd8edb102 100644 --- a/x/mock/app.go +++ b/x/mock/app.go @@ -1,6 +1,7 @@ package mock import ( + "math/rand" "os" bam "github.com/cosmos/cosmos-sdk/baseapp" @@ -15,7 +16,9 @@ import ( const chainID = "" -// App extends an ABCI application. +// App extends an ABCI application, but with most of its parameters exported. +// They are exported for convenience in creating helper functions, as object +// capabilities aren't needed for testing. type App struct { *bam.BaseApp Cdc *wire.Codec // Cdc is public since the codec is passed into the module anyways @@ -26,7 +29,8 @@ type App struct { AccountMapper auth.AccountMapper FeeCollectionKeeper auth.FeeCollectionKeeper - GenesisAccounts []auth.Account + GenesisAccounts []auth.Account + TotalCoinsSupply sdk.Coins } // NewApp partially constructs a new app on the memstore for module and genesis @@ -43,10 +47,11 @@ func NewApp() *App { // Create your application object app := &App{ - BaseApp: bam.NewBaseApp("mock", cdc, logger, db), - Cdc: cdc, - KeyMain: sdk.NewKVStoreKey("main"), - KeyAccount: sdk.NewKVStoreKey("acc"), + BaseApp: bam.NewBaseApp("mock", cdc, logger, db), + Cdc: cdc, + KeyMain: sdk.NewKVStoreKey("main"), + KeyAccount: sdk.NewKVStoreKey("acc"), + TotalCoinsSupply: sdk.Coins{}, } // Define the accountMapper @@ -124,8 +129,8 @@ func SetGenesis(app *App, accs []auth.Account) { func GenTx(msgs []sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKey) auth.StdTx { // Make the transaction free fee := auth.StdFee{ - sdk.Coins{sdk.NewCoin("foocoin", 0)}, - 100000, + Amount: sdk.Coins{sdk.NewCoin("foocoin", 0)}, + Gas: 100000, } sigs := make([]auth.StdSignature, len(priv)) @@ -148,6 +153,70 @@ func GenTx(msgs []sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKey) return auth.NewStdTx(msgs, fee, sigs, memo) } +// GeneratePrivKeys generates a total n Ed25519 private keys. +func GeneratePrivKeys(n int) (keys []crypto.PrivKey) { + // TODO: Randomize this between ed25519 and secp256k1 + keys = make([]crypto.PrivKey, n, n) + for i := 0; i < n; i++ { + keys[i] = crypto.GenPrivKeyEd25519() + } + + return +} + +// GeneratePrivKeyAddressPairs generates a total of n private key, address +// pairs. +func GeneratePrivKeyAddressPairs(n int) (keys []crypto.PrivKey, addrs []sdk.Address) { + keys = make([]crypto.PrivKey, n, n) + addrs = make([]sdk.Address, n, n) + for i := 0; i < n; i++ { + keys[i] = crypto.GenPrivKeyEd25519() + addrs[i] = keys[i].PubKey().Address() + } + return +} + +// RandomSetGenesis set genesis accounts with random coin values using the +// provided addresses and coin denominations. +func RandomSetGenesis(r *rand.Rand, app *App, addrs []sdk.Address, denoms []string) { + accts := make([]auth.Account, len(addrs), len(addrs)) + randCoinIntervals := []BigInterval{ + {sdk.NewIntWithDecimal(1, 0), sdk.NewIntWithDecimal(1, 1)}, + {sdk.NewIntWithDecimal(1, 2), sdk.NewIntWithDecimal(1, 3)}, + {sdk.NewIntWithDecimal(1, 40), sdk.NewIntWithDecimal(1, 50)}, + } + + for i := 0; i < len(accts); i++ { + coins := make([]sdk.Coin, len(denoms), len(denoms)) + + // generate a random coin for each denomination + for j := 0; j < len(denoms); j++ { + coins[j] = sdk.Coin{Denom: denoms[j], + Amount: RandFromBigInterval(r, randCoinIntervals), + } + } + + app.TotalCoinsSupply = app.TotalCoinsSupply.Plus(coins) + baseAcc := auth.NewBaseAccountWithAddress(addrs[i]) + + (&baseAcc).SetCoins(coins) + accts[i] = &baseAcc + } + + SetGenesis(app, accts) +} + +// GetAllAccounts returns all accounts in the accountMapper. +func GetAllAccounts(mapper auth.AccountMapper, ctx sdk.Context) []auth.Account { + accounts := []auth.Account{} + appendAccount := func(acc auth.Account) (stop bool) { + accounts = append(accounts, acc) + return false + } + mapper.IterateAccounts(ctx, appendAccount) + return accounts +} + // GenSequenceOfTxs generates a set of signed transactions of messages, such // that they differ only by having the sequence numbers incremented between // every transaction. diff --git a/x/mock/doc.go b/x/mock/doc.go new file mode 100644 index 000000000..d23aac393 --- /dev/null +++ b/x/mock/doc.go @@ -0,0 +1,15 @@ +/* +Package mock provides functions for creating applications for testing. + +This module also features randomized testing, so that various modules can test +that their operations are interoperable. + +The intended method of using this randomized testing framework is that every +module provides TestAndRunTx methods for each of its desired methods of fuzzing +its own txs, and it also provides the invariants that it assumes to be true. +You then pick and choose from these tx types and invariants. To pick and choose +these, you first build a mock app with the correct keepers. Then you call the +app.RandomizedTesting method with the set of desired txs, invariants, along +with the setups each module requires. +*/ +package mock diff --git a/x/mock/random_simulate_blocks.go b/x/mock/random_simulate_blocks.go new file mode 100644 index 000000000..a37913065 --- /dev/null +++ b/x/mock/random_simulate_blocks.go @@ -0,0 +1,95 @@ +package mock + +import ( + "fmt" + "math/big" + "math/rand" + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" +) + +// RandomizedTesting tests application by sending random messages. +func (app *App) RandomizedTesting( + t *testing.T, ops []TestAndRunTx, setups []RandSetup, + invariants []Invariant, numKeys int, numBlocks int, blockSize int, +) { + time := time.Now().UnixNano() + app.RandomizedTestingFromSeed(t, time, ops, setups, invariants, numKeys, numBlocks, blockSize) +} + +// RandomizedTestingFromSeed tests an application by running the provided +// operations, testing the provided invariants, but using the provided seed. +func (app *App) RandomizedTestingFromSeed( + t *testing.T, seed int64, ops []TestAndRunTx, setups []RandSetup, + invariants []Invariant, numKeys int, numBlocks int, blockSize int, +) { + log := fmt.Sprintf("Starting SingleModuleTest with randomness created with seed %d", int(seed)) + keys, addrs := GeneratePrivKeyAddressPairs(numKeys) + r := rand.New(rand.NewSource(seed)) + + for i := 0; i < len(setups); i++ { + setups[i](r, keys) + } + + RandomSetGenesis(r, app, addrs, []string{"foocoin"}) + header := abci.Header{Height: 0} + + for i := 0; i < numBlocks; i++ { + app.BeginBlock(abci.RequestBeginBlock{}) + + // Make sure invariants hold at beginning of block and when nothing was + // done. + app.assertAllInvariants(t, invariants, log) + + ctx := app.NewContext(false, header) + + // TODO: Add modes to simulate "no load", "medium load", and + // "high load" blocks. + for j := 0; j < blockSize; j++ { + logUpdate, err := ops[r.Intn(len(ops))](t, r, app, ctx, keys, log) + log += "\n" + logUpdate + + require.Nil(t, err, log) + app.assertAllInvariants(t, invariants, log) + } + + app.EndBlock(abci.RequestEndBlock{}) + header.Height++ + } +} + +func (app *App) assertAllInvariants(t *testing.T, tests []Invariant, log string) { + for i := 0; i < len(tests); i++ { + tests[i](t, app, log) + } +} + +// BigInterval is a representation of the interval [lo, hi), where +// lo and hi are both of type sdk.Int +type BigInterval struct { + lo sdk.Int + hi sdk.Int +} + +// RandFromBigInterval chooses an interval uniformly from the provided list of +// BigIntervals, and then chooses an element from an interval uniformly at random. +func RandFromBigInterval(r *rand.Rand, intervals []BigInterval) sdk.Int { + if len(intervals) == 0 { + return sdk.ZeroInt() + } + + interval := intervals[r.Intn(len(intervals))] + + lo := interval.lo + hi := interval.hi + + diff := hi.Sub(lo) + result := sdk.NewIntFromBigInt(new(big.Int).Rand(r, diff.BigInt())) + result = result.Add(lo) + + return result +} diff --git a/x/mock/types.go b/x/mock/types.go new file mode 100644 index 000000000..50957e1c4 --- /dev/null +++ b/x/mock/types.go @@ -0,0 +1,38 @@ +package mock + +import ( + "math/rand" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/tendermint/tendermint/crypto" +) + +type ( + // TestAndRunTx produces a fuzzed transaction, and ensures the state + // transition was as expected. It returns a descriptive message "action" + // about what this fuzzed tx actually did, for ease of debugging. + TestAndRunTx func( + t *testing.T, r *rand.Rand, app *App, ctx sdk.Context, + privKeys []crypto.PrivKey, log string, + ) (action string, err sdk.Error) + + // RandSetup performs the random setup the mock module needs. + RandSetup func(r *rand.Rand, privKeys []crypto.PrivKey) + + // An Invariant is a function which tests a particular invariant. + // If the invariant has been broken, the function should halt the + // test and output the log. + Invariant func(t *testing.T, app *App, log string) +) + +// PeriodicInvariant returns an Invariant function closure that asserts +// a given invariant if the mock application's last block modulo the given +// period is congruent to the given offset. +func PeriodicInvariant(invariant Invariant, period int, offset int) Invariant { + return func(t *testing.T, app *App, log string) { + if int(app.LastBlockHeight())%period == offset { + invariant(t, app, log) + } + } +} From 723e057d955e23852b4b3ea8a1cc5da3e72bb227 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Sat, 7 Jul 2018 00:00:00 +0200 Subject: [PATCH 53/53] Merge pull request #1566: Fix validator power decrease bug * Demonstrative testcase * Update when decreasing but still bonded * Only update when decreasing, not when equal * Cleanup conditional; changelog * Clarify comments * Simplify conditional --- CHANGELOG.md | 1 + x/stake/keeper/validator.go | 7 ++++++ x/stake/keeper/validator_test.go | 40 ++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7012336d9..4808b6db8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -97,6 +97,7 @@ IMPROVEMENTS BUG FIXES * [x/slashing] \#1510 Unrevoked validators cannot un-revoke themselves +* [x/stake] \#1567 Validators decreased in power but not unbonded are now updated in Tendermint * [gaia] Added self delegation for validators in the genesis creation * [lcd] tests now don't depend on raw json text * [stake] error strings lower case diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 164c50049..c32b536ce 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -261,6 +261,13 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type if updatedVal.Owner != nil { // updates to validator occurred to be updated validator = updatedVal } + // if decreased in power but still bonded, update Tendermint validator + // (if updatedVal is set, the validator has changed bonding status) + stillBonded := oldFound && oldValidator.Status() == sdk.Bonded && updatedVal.Owner == nil + if stillBonded && oldValidator.PoolShares.Bonded().GT(validator.PoolShares.Bonded()) { + bz := k.cdc.MustMarshalBinary(validator.ABCIValidator()) + store.Set(GetTendermintUpdatesKey(ownerAddr), bz) + } return validator } diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index c4d197a36..9ad6e12bc 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -674,3 +674,43 @@ func TestGetTendermintUpdatesNotValidatorCliff(t *testing.T) { require.Equal(t, validators[0].ABCIValidatorZero(), updates[0]) require.Equal(t, validators[2].ABCIValidator(), updates[1]) } + +func TestGetTendermintUpdatesPowerDecrease(t *testing.T) { + ctx, _, keeper := CreateTestInput(t, false, 1000) + + amts := []int64{100, 100} + var validators [2]types.Validator + for i, amt := range amts { + pool := keeper.GetPool(ctx) + validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) + keeper.SetPool(ctx, pool) + } + validators[0] = keeper.UpdateValidator(ctx, validators[0]) + validators[1] = keeper.UpdateValidator(ctx, validators[1]) + keeper.ClearTendermintUpdates(ctx) + require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) + + // check initial power + require.Equal(t, sdk.NewRat(100).RoundInt64(), validators[0].GetPower().RoundInt64()) + require.Equal(t, sdk.NewRat(100).RoundInt64(), validators[1].GetPower().RoundInt64()) + + // test multiple value change + // tendermintUpdate set: {c1, c3} -> {c1', c3'} + pool := keeper.GetPool(ctx) + validators[0], pool, _ = validators[0].RemoveDelShares(pool, sdk.NewRat(20)) + validators[1], pool, _ = validators[1].RemoveDelShares(pool, sdk.NewRat(30)) + keeper.SetPool(ctx, pool) + validators[0] = keeper.UpdateValidator(ctx, validators[0]) + validators[1] = keeper.UpdateValidator(ctx, validators[1]) + + // power has changed + require.Equal(t, sdk.NewRat(80).RoundInt64(), validators[0].GetPower().RoundInt64()) + require.Equal(t, sdk.NewRat(70).RoundInt64(), validators[1].GetPower().RoundInt64()) + + // Tendermint updates should reflect power change + updates := keeper.GetTendermintUpdates(ctx) + require.Equal(t, 2, len(updates)) + require.Equal(t, validators[0].ABCIValidator(), updates[0]) + require.Equal(t, validators[1].ABCIValidator(), updates[1]) +}