Skip to content

Commit

Permalink
testing: refactore Validation and Delegation handling of x/staking
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
robert-zaremba committed Oct 13, 2020
1 parent bbbc0e1 commit 73c846b
Show file tree
Hide file tree
Showing 32 changed files with 467 additions and 580 deletions.
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`.
// TODO: 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
5 changes: 3 additions & 2 deletions proto/cosmos/staking/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package cosmos.staking.v1beta1;
import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
import "cosmos/staking/v1beta1/staking.proto";
import "google/protobuf/any.proto";

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

Expand All @@ -21,7 +22,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 Expand Up @@ -80,4 +81,4 @@ message MsgUndelegate {
string delegator_address = 1 [(gogoproto.moretags) = "yaml:\"delegator_address\""];
string validator_address = 2 [(gogoproto.moretags) = "yaml:\"validator_address\""];
cosmos.base.v1beta1.Coin amount = 3 [(gogoproto.nullable) = false];
}
}
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 mock 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
1 change: 1 addition & 0 deletions types/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,7 @@ func Bech32ifyPubKey(pkt Bech32PubKeyType, pubkey crypto.PubKey) (string, error)
// TM's ed25519 bech32 encoding, we explicitly say to bech32-encode our own
// ed25519 the same way as TM's ed25519.
// TODO: Remove Bech32ifyPubKey and all usages (cosmos/cosmos-sdk/issues/#7357)
// TODO RZ: check if this is handled by the protobuf any serialization
pkToMarshal := pubkey
if ed25519Pk, ok := pubkey.(*ed25519.PubKey); ok {
pkToMarshal = ed25519Pk.AsTmPubKey()
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.NewService(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(t, 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.NewService(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(t, 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(t, 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.NewService(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(t, 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(t, 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(t, 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 73c846b

Please sign in to comment.