Skip to content

Commit

Permalink
Refactor x/staking Validation and Delegation tests based on MsgCreate…
Browse files Browse the repository at this point in the history
…Validator.Pubkey type change. (#7526)

* testing: refactore Validation and Delegation handling of x/staking

This Changeset introduces set of improvements for writing tests.

The idea is to create a testing subpackage which will provide functions
to make tests more dev-friendly and wrap higher level use-cases.
Here is a show-up of of creating a service for staking module
for tests.

This PR also changes the `x/staking/types.MsgCreateValidator.Pubkey` from string
to types.Any. This change motivated the other change to show the pattern I'm describing here.

* add validator checks

* type change fixes

* use deprecated

* adding test slashing

* new network comment update

* working on tests

* Fix TestMsgPkDecode test

* Add UnpackInterfaces to MsgCreateValidator

* Fix tests

* Convert bech32 pubkey to proto

* Fix test

* fix v039/migrate_test/TestMigrate

* fix tests

* testslashing: rename Service to Helper

* file rename

* update TestMsgDecode

Co-authored-by: blushi <marie.gauthier63@gmail.com>
Co-authored-by: Amaury Martiny <amaury.martiny@protonmail.com>
Co-authored-by: Cory Levinson <cjlevinson@gmail.com>
  • Loading branch information
4 people committed Oct 29, 2020
1 parent 1db641d commit 95f4fc8
Show file tree
Hide file tree
Showing 39 changed files with 776 additions and 1,090 deletions.
3 changes: 1 addition & 2 deletions codec/any_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import (
"errors"
"testing"

"github.com/cosmos/cosmos-sdk/codec"

"github.com/stretchr/testify/require"

"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
)
Expand Down
18 changes: 18 additions & 0 deletions codec/types/any.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package types

import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/gogo/protobuf/proto"
)

Expand Down Expand Up @@ -98,6 +99,23 @@ func UnsafePackAny(x interface{}) *Any {
return &Any{cachedValue: x}
}

// PackAny is a checked and safe version of UnsafePackAny. It assures that
// `x` implements the proto.Message interface and uses it to serialize `x`.
// [DEPRECATED]: should be moved away: https://github.com/cosmos/cosmos-sdk/issues/7479
func PackAny(x interface{}) (*Any, error) {
if x == nil {
return nil, nil
}
if intoany, ok := x.(IntoAny); ok {
return intoany.AsAny(), nil
}
protoMsg, ok := x.(proto.Message)
if !ok {
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "Expecting %T to implement proto.Message", x)
}
return NewAnyWithValue(protoMsg)
}

// GetCachedValue returns the cached value from the Any if present
func (any *Any) GetCachedValue() interface{} {
return any.cachedValue
Expand Down
3 changes: 2 additions & 1 deletion proto/cosmos/staking/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
import "google/protobuf/timestamp.proto";
import "cosmos/staking/v1beta1/staking.proto";
import "google/protobuf/any.proto";

option go_package = "github.com/cosmos/cosmos-sdk/x/staking/types";

Expand Down Expand Up @@ -43,7 +44,7 @@ message MsgCreateValidator {
];
string delegator_address = 4 [(gogoproto.moretags) = "yaml:\"delegator_address\""];
string validator_address = 5 [(gogoproto.moretags) = "yaml:\"validator_address\""];
string pubkey = 6;
google.protobuf.Any pubkey = 6;
cosmos.base.v1beta1.Coin value = 7 [(gogoproto.nullable) = false];
}

Expand Down
5 changes: 4 additions & 1 deletion simapp/simd/cmd/testnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,17 @@ func InitTestnet(
genAccounts = append(genAccounts, authtypes.NewBaseAccount(addr, nil, 0, 0))

valTokens := sdk.TokensFromConsensusPower(100)
createValMsg := stakingtypes.NewMsgCreateValidator(
createValMsg, err := stakingtypes.NewMsgCreateValidator(
sdk.ValAddress(addr),
valPubKeys[i],
sdk.NewCoin(sdk.DefaultBondDenom, valTokens),
stakingtypes.NewDescription(nodeDirName, "", "", "", ""),
stakingtypes.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
sdk.OneInt(),
)
if err != nil {
return err
}

txBuilder := clientCtx.TxConfig.NewTxBuilder()
if err := txBuilder.SetMsgs(createValMsg); err != nil {
Expand Down
4 changes: 3 additions & 1 deletion testutil/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ type (
}
)

// New creates a new Network for integration tests.
func New(t *testing.T, cfg Config) *Network {
// only one caller/test can create and use a network at a time
t.Log("acquiring test network lock")
Expand Down Expand Up @@ -293,14 +294,15 @@ func New(t *testing.T, cfg Config) *Network {
commission, err := sdk.NewDecFromStr("0.5")
require.NoError(t, err)

createValMsg := stakingtypes.NewMsgCreateValidator(
createValMsg, err := stakingtypes.NewMsgCreateValidator(
sdk.ValAddress(addr),
valPubKeys[i],
sdk.NewCoin(sdk.DefaultBondDenom, cfg.BondedTokens),
stakingtypes.NewDescription(nodeDirName, "", "", "", ""),
stakingtypes.NewCommissionRates(commission, sdk.OneDec(), sdk.OneDec()),
sdk.OneInt(),
)
require.NoError(t, err)

p2pURL, err := url.Parse(p2pAddr)
require.NoError(t, err)
Expand Down
27 changes: 25 additions & 2 deletions types/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ import (
"strings"

"github.com/tendermint/tendermint/crypto"
tmed25519 "github.com/tendermint/tendermint/crypto/ed25519"
yaml "gopkg.in/yaml.v2"

"github.com/cosmos/cosmos-sdk/codec/legacy"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/types/bech32"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

const (
Expand Down Expand Up @@ -674,12 +677,32 @@ func GetPubKeyFromBech32(pkt Bech32PubKeyType, pubkeyStr string) (crypto.PubKey,
return nil, err
}

pk, err := cryptocodec.PubKeyFromBytes(bz)
aminoPk, err := cryptocodec.PubKeyFromBytes(bz)
if err != nil {
return nil, err
}

return pk, nil
var protoPk crypto.PubKey
switch aminoPk.(type) {

// We are bech32ifying some secp256k1 keys in tests.
case *secp256k1.PubKey:
protoPk = aminoPk
case *ed25519.PubKey:
protoPk = aminoPk

// Real-life case.
case tmed25519.PubKey:
protoPk = &ed25519.PubKey{
Key: aminoPk.Bytes(),
}

default:
// We only allow ed25519 pubkeys to be bech32-ed right now.
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "bech32 pubkey does not support %T", aminoPk)
}

return protoPk, nil
}

// MustGetPubKeyFromBech32 calls GetPubKeyFromBech32 except it panics on error.
Expand Down
20 changes: 4 additions & 16 deletions x/auth/types/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

var (
Expand Down Expand Up @@ -84,22 +83,11 @@ func (acc BaseAccount) GetPubKey() (pk crypto.PubKey) {

// SetPubKey - Implements sdk.AccountI.
func (acc *BaseAccount) SetPubKey(pubKey crypto.PubKey) error {
if pubKey == nil {
acc.PubKey = nil
} else {
protoMsg, ok := pubKey.(proto.Message)
if !ok {
return sdkerrors.ErrInvalidPubKey
}

any, err := codectypes.NewAnyWithValue(protoMsg)
if err != nil {
return err
}

acc.PubKey = any
any, err := codectypes.PackAny(pubKey)
if err != nil {
return err
}

acc.PubKey = any
return nil
}

Expand Down
67 changes: 18 additions & 49 deletions x/distribution/keeper/allocation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/staking"
"github.com/cosmos/cosmos-sdk/x/staking/teststaking"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

Expand All @@ -20,20 +20,11 @@ func TestAllocateTokensToValidatorWithCommission(t *testing.T) {

addrs := simapp.AddTestAddrs(app, ctx, 3, sdk.NewInt(1234))
valAddrs := simapp.ConvertAddrsToValAddrs(addrs)

sh := staking.NewHandler(app.StakingKeeper)
tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)

// create validator with 50% commission
commission := stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := stakingtypes.NewMsgCreateValidator(
sdk.ValAddress(addrs[0]), valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), stakingtypes.Description{}, commission, sdk.OneInt(),
)

res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)

tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
tstaking.CreateValidator(sdk.ValAddress(addrs[0]), valConsPk1, 100, true)
val := app.StakingKeeper.Validator(ctx, valAddrs[0])

// allocate tokens
Expand All @@ -56,27 +47,17 @@ func TestAllocateTokensToManyValidators(t *testing.T) {
app := simapp.Setup(false)
ctx := app.BaseApp.NewContext(false, tmproto.Header{})

sh := staking.NewHandler(app.StakingKeeper)
addrs := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(1234))
valAddrs := simapp.ConvertAddrsToValAddrs(addrs)
tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)

// create validator with 50% commission
commission := stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := stakingtypes.NewMsgCreateValidator(valAddrs[0], valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), stakingtypes.Description{}, commission, sdk.OneInt())

res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
tstaking.CreateValidator(valAddrs[0], valConsPk1, 100, true)

// create second validator with 0% commission
commission = stakingtypes.NewCommissionRates(sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0))
msg = stakingtypes.NewMsgCreateValidator(valAddrs[1], valConsPk2,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), stakingtypes.Description{}, commission, sdk.OneInt())

res, err = sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0))
tstaking.CreateValidator(valAddrs[1], valConsPk2, 100, true)

abciValA := abci.Validator{
Address: valConsPk1.Address(),
Expand All @@ -101,7 +82,7 @@ func TestAllocateTokensToManyValidators(t *testing.T) {
feeCollector := app.AccountKeeper.GetModuleAccount(ctx, types.FeeCollectorName)
require.NotNil(t, feeCollector)

err = app.BankKeeper.SetBalances(ctx, feeCollector.GetAddress(), fees)
err := app.BankKeeper.SetBalances(ctx, feeCollector.GetAddress(), fees)
require.NoError(t, err)
app.AccountKeeper.SetAccount(ctx, feeCollector)

Expand Down Expand Up @@ -138,31 +119,19 @@ func TestAllocateTokensTruncation(t *testing.T) {

addrs := simapp.AddTestAddrs(app, ctx, 3, sdk.NewInt(1234))
valAddrs := simapp.ConvertAddrsToValAddrs(addrs)
sh := staking.NewHandler(app.StakingKeeper)
tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)

// create validator with 10% commission
commission := stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), sdk.NewDec(0))
msg := stakingtypes.NewMsgCreateValidator(valAddrs[0], valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(110)), stakingtypes.Description{}, commission, sdk.OneInt())
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), sdk.NewDec(0))
tstaking.CreateValidator(valAddrs[0], valConsPk1, 110, true)

// create second validator with 10% commission
commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), sdk.NewDec(0))
msg = stakingtypes.NewMsgCreateValidator(valAddrs[1], valConsPk2,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), stakingtypes.Description{}, commission, sdk.OneInt())
res, err = sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), sdk.NewDec(0))
tstaking.CreateValidator(valAddrs[1], valConsPk2, 100, true)

// create third validator with 10% commission
commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), sdk.NewDec(0))
msg = stakingtypes.NewMsgCreateValidator(valAddrs[2], valConsPk3,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), stakingtypes.Description{}, commission, sdk.OneInt())
res, err = sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), sdk.NewDec(0))
tstaking.CreateValidator(valAddrs[2], valConsPk3, 100, true)

abciValA := abci.Validator{
Address: valConsPk1.Address(),
Expand Down Expand Up @@ -193,7 +162,7 @@ func TestAllocateTokensTruncation(t *testing.T) {
feeCollector := app.AccountKeeper.GetModuleAccount(ctx, types.FeeCollectorName)
require.NotNil(t, feeCollector)

err = app.BankKeeper.SetBalances(ctx, feeCollector.GetAddress(), fees)
err := app.BankKeeper.SetBalances(ctx, feeCollector.GetAddress(), fees)
require.NoError(t, err)

app.AccountKeeper.SetAccount(ctx, feeCollector)
Expand Down
Loading

0 comments on commit 95f4fc8

Please sign in to comment.