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