2019-08-19 06:29:17 -07:00
|
|
|
package simapp
|
|
|
|
|
|
|
|
import (
|
2020-02-20 07:09:25 -08:00
|
|
|
"bytes"
|
|
|
|
"encoding/hex"
|
2020-08-11 07:22:30 -07:00
|
|
|
"encoding/json"
|
2020-02-26 07:05:12 -08:00
|
|
|
"fmt"
|
2020-02-20 07:09:25 -08:00
|
|
|
"strconv"
|
2019-08-19 06:29:17 -07:00
|
|
|
"testing"
|
2020-06-26 09:36:04 -07:00
|
|
|
"time"
|
2019-08-19 06:29:17 -07:00
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
2021-09-15 14:18:01 -07:00
|
|
|
tmjson "github.com/tendermint/tendermint/libs/json"
|
2019-08-19 06:29:17 -07:00
|
|
|
"github.com/tendermint/tendermint/libs/log"
|
2020-08-14 10:58:53 -07:00
|
|
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
2020-04-16 08:10:39 -07:00
|
|
|
tmtypes "github.com/tendermint/tendermint/types"
|
2019-08-19 06:29:17 -07:00
|
|
|
dbm "github.com/tendermint/tm-db"
|
|
|
|
|
|
|
|
bam "github.com/cosmos/cosmos-sdk/baseapp"
|
2020-07-14 10:33:31 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/client"
|
2020-10-23 05:07:52 -07:00
|
|
|
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
2020-11-09 08:01:43 -08:00
|
|
|
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
|
2020-09-25 01:41:16 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
2021-09-15 14:18:01 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
2020-11-09 08:01:43 -08:00
|
|
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
2021-09-15 14:18:01 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/server/types"
|
2019-10-23 02:14:45 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/simapp/helpers"
|
2021-09-15 14:18:01 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/simapp/params"
|
|
|
|
"github.com/cosmos/cosmos-sdk/testutil/mock"
|
2019-08-19 06:29:17 -07:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2020-09-25 01:41:16 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/types/errors"
|
2020-06-17 11:42:27 -07:00
|
|
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
2020-06-14 16:06:16 -07:00
|
|
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
2021-02-17 10:20:33 -08:00
|
|
|
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
2020-06-26 09:36:04 -07:00
|
|
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
2019-08-19 06:29:17 -07:00
|
|
|
)
|
|
|
|
|
2020-04-16 08:10:39 -07:00
|
|
|
// DefaultConsensusParams defines the default Tendermint consensus params used in
|
|
|
|
// SimApp testing.
|
|
|
|
var DefaultConsensusParams = &abci.ConsensusParams{
|
|
|
|
Block: &abci.BlockParams{
|
|
|
|
MaxBytes: 200000,
|
|
|
|
MaxGas: 2000000,
|
|
|
|
},
|
2020-08-14 10:58:53 -07:00
|
|
|
Evidence: &tmproto.EvidenceParams{
|
2020-04-16 08:10:39 -07:00
|
|
|
MaxAgeNumBlocks: 302400,
|
2020-08-14 01:47:13 -07:00
|
|
|
MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration
|
2020-10-13 23:20:52 -07:00
|
|
|
MaxBytes: 10000,
|
2020-04-16 08:10:39 -07:00
|
|
|
},
|
2020-08-14 10:58:53 -07:00
|
|
|
Validator: &tmproto.ValidatorParams{
|
2020-04-16 08:10:39 -07:00
|
|
|
PubKeyTypes: []string{
|
|
|
|
tmtypes.ABCIPubKeyTypeEd25519,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2021-09-15 14:18:01 -07:00
|
|
|
// SetupOptions defines arguments that are passed into `Simapp` constructor.
|
|
|
|
type SetupOptions struct {
|
|
|
|
Logger log.Logger
|
|
|
|
DB *dbm.MemDB
|
|
|
|
InvCheckPeriod uint
|
|
|
|
HomePath string
|
|
|
|
SkipUpgradeHeights map[int64]bool
|
|
|
|
EncConfig params.EncodingConfig
|
|
|
|
AppOpts types.AppOptions
|
|
|
|
}
|
|
|
|
|
2021-01-06 07:20:12 -08:00
|
|
|
func setup(withGenesis bool, invCheckPeriod uint) (*SimApp, GenesisState) {
|
|
|
|
db := dbm.NewMemDB()
|
|
|
|
encCdc := MakeTestEncodingConfig()
|
|
|
|
app := NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, invCheckPeriod, encCdc, EmptyAppOptions{})
|
|
|
|
if withGenesis {
|
2021-07-01 01:52:38 -07:00
|
|
|
return app, NewDefaultGenesisState(encCdc.Codec)
|
2021-01-06 07:20:12 -08:00
|
|
|
}
|
|
|
|
return app, GenesisState{}
|
|
|
|
}
|
|
|
|
|
2021-09-15 14:18:01 -07:00
|
|
|
// NewSimappWithCustomOptions initializes a new SimApp with custom options.
|
|
|
|
func NewSimappWithCustomOptions(t *testing.T, isCheckTx bool, options SetupOptions) *SimApp {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
privVal := mock.NewPV()
|
|
|
|
pubKey, err := privVal.GetPubKey()
|
|
|
|
require.NoError(t, err)
|
|
|
|
// create validator set with single validator
|
|
|
|
validator := tmtypes.NewValidator(pubKey, 1)
|
|
|
|
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
|
|
|
|
|
|
|
|
// generate genesis account
|
|
|
|
senderPrivKey := secp256k1.GenPrivKey()
|
|
|
|
acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0)
|
|
|
|
balance := banktypes.Balance{
|
|
|
|
Address: acc.GetAddress().String(),
|
|
|
|
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))),
|
|
|
|
}
|
|
|
|
|
|
|
|
app := NewSimApp(options.Logger, options.DB, nil, true, options.SkipUpgradeHeights, options.HomePath, options.InvCheckPeriod, options.EncConfig, options.AppOpts)
|
|
|
|
genesisState := NewDefaultGenesisState(app.appCodec)
|
|
|
|
genesisState = genesisStateWithValSet(t, app, genesisState, valSet, []authtypes.GenesisAccount{acc}, balance)
|
|
|
|
|
|
|
|
if !isCheckTx {
|
|
|
|
// init chain must be called to stop deliverState from being nil
|
|
|
|
stateBytes, err := tmjson.MarshalIndent(genesisState, "", " ")
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Initialize the chain
|
|
|
|
app.InitChain(
|
|
|
|
abci.RequestInitChain{
|
|
|
|
Validators: []abci.ValidatorUpdate{},
|
|
|
|
ConsensusParams: DefaultConsensusParams,
|
|
|
|
AppStateBytes: stateBytes,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return app
|
|
|
|
}
|
|
|
|
|
2019-08-19 06:29:17 -07:00
|
|
|
// Setup initializes a new SimApp. A Nop logger is set in SimApp.
|
2021-08-16 17:52:06 -07:00
|
|
|
func Setup(t *testing.T, isCheckTx bool) *SimApp {
|
|
|
|
t.Helper()
|
|
|
|
|
2021-10-05 05:02:51 -07:00
|
|
|
privVal := mock.NewPV()
|
|
|
|
pubKey, err := privVal.GetPubKey()
|
|
|
|
require.NoError(t, err)
|
2019-08-19 06:29:17 -07:00
|
|
|
|
2021-10-05 05:02:51 -07:00
|
|
|
// create validator set with single validator
|
|
|
|
validator := tmtypes.NewValidator(pubKey, 1)
|
|
|
|
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
|
|
|
|
|
|
|
|
// generate genesis account
|
|
|
|
senderPrivKey := secp256k1.GenPrivKey()
|
|
|
|
acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0)
|
|
|
|
balance := banktypes.Balance{
|
|
|
|
Address: acc.GetAddress().String(),
|
|
|
|
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))),
|
2019-08-19 06:29:17 -07:00
|
|
|
}
|
|
|
|
|
2021-10-05 05:02:51 -07:00
|
|
|
app := SetupWithGenesisValSet(t, valSet, []authtypes.GenesisAccount{acc}, balance)
|
|
|
|
|
2019-08-19 06:29:17 -07:00
|
|
|
return app
|
|
|
|
}
|
|
|
|
|
2021-09-15 14:18:01 -07:00
|
|
|
func genesisStateWithValSet(t *testing.T,
|
|
|
|
app *SimApp, genesisState GenesisState,
|
|
|
|
valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount,
|
|
|
|
balances ...banktypes.Balance) GenesisState {
|
2020-06-26 09:36:04 -07:00
|
|
|
// set genesis accounts
|
|
|
|
authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs)
|
2020-08-13 06:20:02 -07:00
|
|
|
genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis)
|
2020-06-26 09:36:04 -07:00
|
|
|
|
|
|
|
validators := make([]stakingtypes.Validator, 0, len(valSet.Validators))
|
|
|
|
delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators))
|
|
|
|
|
2021-09-15 14:18:01 -07:00
|
|
|
bondAmt := sdk.DefaultPowerReduction
|
2020-06-26 09:36:04 -07:00
|
|
|
|
|
|
|
for _, val := range valSet.Validators {
|
2020-11-09 08:01:43 -08:00
|
|
|
pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey)
|
2020-10-23 05:07:52 -07:00
|
|
|
require.NoError(t, err)
|
2020-12-18 06:55:25 -08:00
|
|
|
pkAny, err := codectypes.NewAnyWithValue(pk)
|
2020-10-23 05:07:52 -07:00
|
|
|
require.NoError(t, err)
|
2020-06-26 09:36:04 -07:00
|
|
|
validator := stakingtypes.Validator{
|
2020-09-25 03:25:37 -07:00
|
|
|
OperatorAddress: sdk.ValAddress(val.Address).String(),
|
2020-10-23 05:07:52 -07:00
|
|
|
ConsensusPubkey: pkAny,
|
2020-06-26 09:36:04 -07:00
|
|
|
Jailed: false,
|
2020-10-12 06:56:02 -07:00
|
|
|
Status: stakingtypes.Bonded,
|
2020-06-26 09:36:04 -07:00
|
|
|
Tokens: bondAmt,
|
|
|
|
DelegatorShares: sdk.OneDec(),
|
|
|
|
Description: stakingtypes.Description{},
|
|
|
|
UnbondingHeight: int64(0),
|
|
|
|
UnbondingTime: time.Unix(0, 0).UTC(),
|
|
|
|
Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
|
|
|
|
MinSelfDelegation: sdk.ZeroInt(),
|
|
|
|
}
|
|
|
|
validators = append(validators, validator)
|
|
|
|
delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec()))
|
|
|
|
|
|
|
|
}
|
|
|
|
// set validators and delegations
|
|
|
|
stakingGenesis := stakingtypes.NewGenesisState(stakingtypes.DefaultParams(), validators, delegations)
|
2020-08-13 06:20:02 -07:00
|
|
|
genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis)
|
2020-06-26 09:36:04 -07:00
|
|
|
|
|
|
|
totalSupply := sdk.NewCoins()
|
|
|
|
for _, b := range balances {
|
2021-10-05 05:02:51 -07:00
|
|
|
// add genesis acc tokens to total supply
|
|
|
|
totalSupply = totalSupply.Add(b.Coins...)
|
|
|
|
}
|
|
|
|
|
|
|
|
for range delegations {
|
|
|
|
// add delegated tokens to total supply
|
|
|
|
totalSupply = totalSupply.Add(sdk.NewCoin(sdk.DefaultBondDenom, bondAmt))
|
2020-06-26 09:36:04 -07:00
|
|
|
}
|
|
|
|
|
2021-02-17 10:20:33 -08:00
|
|
|
// add bonded amount to bonded pool module account
|
|
|
|
balances = append(balances, banktypes.Balance{
|
|
|
|
Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(),
|
|
|
|
Coins: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)},
|
|
|
|
})
|
|
|
|
|
2020-06-26 09:36:04 -07:00
|
|
|
// update total supply
|
2020-07-28 00:49:56 -07:00
|
|
|
bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{})
|
2020-08-13 06:20:02 -07:00
|
|
|
genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis)
|
2020-06-26 09:36:04 -07:00
|
|
|
|
2021-09-15 14:18:01 -07:00
|
|
|
return genesisState
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetupWithGenesisValSet initializes a new SimApp with a validator set and genesis accounts
|
|
|
|
// that also act as delegators. For simplicity, each validator is bonded with a delegation
|
|
|
|
// of one consensus engine unit in the default token of the simapp from first genesis
|
|
|
|
// account. A Nop logger is set in SimApp.
|
|
|
|
func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) *SimApp {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
app, genesisState := setup(true, 5)
|
|
|
|
genesisState = genesisStateWithValSet(t, app, genesisState, valSet, genAccs, balances...)
|
|
|
|
|
2020-08-13 06:20:02 -07:00
|
|
|
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
|
2020-06-26 09:36:04 -07:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// init chain will set the validator set and initialize the genesis accounts
|
|
|
|
app.InitChain(
|
|
|
|
abci.RequestInitChain{
|
|
|
|
Validators: []abci.ValidatorUpdate{},
|
|
|
|
ConsensusParams: DefaultConsensusParams,
|
|
|
|
AppStateBytes: stateBytes,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
// commit genesis changes
|
|
|
|
app.Commit()
|
2020-08-14 10:58:53 -07:00
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{
|
2020-08-04 02:05:03 -07:00
|
|
|
Height: app.LastBlockHeight() + 1,
|
|
|
|
AppHash: app.LastCommitID().Hash,
|
|
|
|
ValidatorsHash: valSet.Hash(),
|
|
|
|
NextValidatorsHash: valSet.Hash(),
|
|
|
|
}})
|
2020-06-26 09:36:04 -07:00
|
|
|
|
|
|
|
return app
|
|
|
|
}
|
|
|
|
|
2020-02-14 07:30:51 -08:00
|
|
|
// SetupWithGenesisAccounts initializes a new SimApp with the provided genesis
|
|
|
|
// accounts and possible balances.
|
2021-09-15 14:18:01 -07:00
|
|
|
func SetupWithGenesisAccounts(t *testing.T, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) *SimApp {
|
|
|
|
t.Helper()
|
|
|
|
|
2021-10-05 05:02:51 -07:00
|
|
|
privVal := mock.NewPV()
|
|
|
|
pubKey, err := privVal.GetPubKey()
|
|
|
|
require.NoError(t, err)
|
2020-02-14 07:30:51 -08:00
|
|
|
|
2021-10-05 05:02:51 -07:00
|
|
|
// create validator set with single validator
|
|
|
|
validator := tmtypes.NewValidator(pubKey, 1)
|
|
|
|
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
|
2020-04-20 08:22:12 -07:00
|
|
|
|
2021-10-05 05:02:51 -07:00
|
|
|
return SetupWithGenesisValSet(t, valSet, genAccs, balances...)
|
|
|
|
}
|
2019-09-12 12:22:25 -07:00
|
|
|
|
2021-10-05 05:02:51 -07:00
|
|
|
// SetupWithGenesisValSet initializes GenesisState with a single validator and genesis accounts
|
|
|
|
// that also act as delegators.
|
|
|
|
func GenesisStateWithSingleValidator(t *testing.T, app *SimApp) GenesisState {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
privVal := mock.NewPV()
|
|
|
|
pubKey, err := privVal.GetPubKey()
|
2021-09-15 14:18:01 -07:00
|
|
|
require.NoError(t, err)
|
2019-08-19 06:29:17 -07:00
|
|
|
|
2021-10-05 05:02:51 -07:00
|
|
|
// create validator set with single validator
|
|
|
|
validator := tmtypes.NewValidator(pubKey, 1)
|
|
|
|
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
|
|
|
|
|
|
|
|
// generate genesis account
|
|
|
|
senderPrivKey := secp256k1.GenPrivKey()
|
|
|
|
acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0)
|
|
|
|
balances := []banktypes.Balance{
|
|
|
|
{
|
|
|
|
Address: acc.GetAddress().String(),
|
|
|
|
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))),
|
2019-08-19 06:29:17 -07:00
|
|
|
},
|
2021-10-05 05:02:51 -07:00
|
|
|
}
|
2019-08-19 06:29:17 -07:00
|
|
|
|
2021-10-05 05:02:51 -07:00
|
|
|
genesisState := NewDefaultGenesisState(app.appCodec)
|
|
|
|
genesisState = genesisStateWithValSet(t, app, genesisState, valSet, []authtypes.GenesisAccount{acc}, balances...)
|
2019-08-19 06:29:17 -07:00
|
|
|
|
2021-10-05 05:02:51 -07:00
|
|
|
return genesisState
|
2019-08-19 06:29:17 -07:00
|
|
|
}
|
|
|
|
|
2020-02-21 10:34:07 -08:00
|
|
|
type GenerateAccountStrategy func(int) []sdk.AccAddress
|
|
|
|
|
2020-02-27 07:49:53 -08:00
|
|
|
// createRandomAccounts is a strategy used by addTestAddrs() in order to generated addresses in random order.
|
|
|
|
func createRandomAccounts(accNum int) []sdk.AccAddress {
|
2019-08-27 06:19:26 -07:00
|
|
|
testAddrs := make([]sdk.AccAddress, accNum)
|
|
|
|
for i := 0; i < accNum; i++ {
|
|
|
|
pk := ed25519.GenPrivKey().PubKey()
|
|
|
|
testAddrs[i] = sdk.AccAddress(pk.Address())
|
|
|
|
}
|
|
|
|
|
2020-02-21 10:34:07 -08:00
|
|
|
return testAddrs
|
|
|
|
}
|
|
|
|
|
2020-02-27 07:49:53 -08:00
|
|
|
// createIncrementalAccounts is a strategy used by addTestAddrs() in order to generated addresses in ascending order.
|
|
|
|
func createIncrementalAccounts(accNum int) []sdk.AccAddress {
|
2020-02-21 10:34:07 -08:00
|
|
|
var addresses []sdk.AccAddress
|
|
|
|
var buffer bytes.Buffer
|
|
|
|
|
|
|
|
// start at 100 so we can make up to 999 test addresses with valid test addresses
|
|
|
|
for i := 100; i < (accNum + 100); i++ {
|
|
|
|
numString := strconv.Itoa(i)
|
2021-02-23 00:46:01 -08:00
|
|
|
buffer.WriteString("A58856F0FD53BF058B4909A21AEC019107BA6") // base address string
|
2020-02-21 10:34:07 -08:00
|
|
|
|
2021-02-23 00:46:01 -08:00
|
|
|
buffer.WriteString(numString) // adding on final two digits to make addresses unique
|
2020-02-21 10:34:07 -08:00
|
|
|
res, _ := sdk.AccAddressFromHex(buffer.String())
|
|
|
|
bech := res.String()
|
2020-02-26 07:05:12 -08:00
|
|
|
addr, _ := TestAddr(buffer.String(), bech)
|
|
|
|
|
|
|
|
addresses = append(addresses, addr)
|
2020-02-21 10:34:07 -08:00
|
|
|
buffer.Reset()
|
|
|
|
}
|
|
|
|
|
|
|
|
return addresses
|
|
|
|
}
|
|
|
|
|
2020-03-03 02:05:20 -08:00
|
|
|
// AddTestAddrsFromPubKeys adds the addresses into the SimApp providing only the public keys.
|
2020-11-09 08:01:43 -08:00
|
|
|
func AddTestAddrsFromPubKeys(app *SimApp, ctx sdk.Context, pubKeys []cryptotypes.PubKey, accAmt sdk.Int) {
|
2020-03-03 01:51:06 -08:00
|
|
|
initCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt))
|
2020-03-03 02:05:20 -08:00
|
|
|
|
2021-02-17 10:20:33 -08:00
|
|
|
for _, pk := range pubKeys {
|
|
|
|
initAccountWithCoins(app, ctx, sdk.AccAddress(pk.Address()), initCoins)
|
2020-03-03 01:51:06 -08:00
|
|
|
}
|
2020-03-03 02:05:20 -08:00
|
|
|
}
|
|
|
|
|
2020-02-21 10:34:07 -08:00
|
|
|
// AddTestAddrs constructs and returns accNum amount of accounts with an
|
|
|
|
// initial balance of accAmt in random order
|
|
|
|
func AddTestAddrs(app *SimApp, ctx sdk.Context, accNum int, accAmt sdk.Int) []sdk.AccAddress {
|
2020-02-27 07:49:53 -08:00
|
|
|
return addTestAddrs(app, ctx, accNum, accAmt, createRandomAccounts)
|
2020-02-21 10:34:07 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// AddTestAddrs constructs and returns accNum amount of accounts with an
|
|
|
|
// initial balance of accAmt in random order
|
|
|
|
func AddTestAddrsIncremental(app *SimApp, ctx sdk.Context, accNum int, accAmt sdk.Int) []sdk.AccAddress {
|
2020-02-27 07:49:53 -08:00
|
|
|
return addTestAddrs(app, ctx, accNum, accAmt, createIncrementalAccounts)
|
2020-02-21 10:34:07 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func addTestAddrs(app *SimApp, ctx sdk.Context, accNum int, accAmt sdk.Int, strategy GenerateAccountStrategy) []sdk.AccAddress {
|
|
|
|
testAddrs := strategy(accNum)
|
|
|
|
|
2019-08-27 06:19:26 -07:00
|
|
|
initCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt))
|
|
|
|
|
|
|
|
for _, addr := range testAddrs {
|
2021-02-17 10:20:33 -08:00
|
|
|
initAccountWithCoins(app, ctx, addr, initCoins)
|
2019-08-27 06:19:26 -07:00
|
|
|
}
|
2020-03-03 02:05:20 -08:00
|
|
|
|
2019-08-27 06:19:26 -07:00
|
|
|
return testAddrs
|
|
|
|
}
|
|
|
|
|
2021-02-17 10:20:33 -08:00
|
|
|
func initAccountWithCoins(app *SimApp, ctx sdk.Context, addr sdk.AccAddress, coins sdk.Coins) {
|
|
|
|
err := app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, coins)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = app.BankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins)
|
2020-03-03 02:05:20 -08:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-28 09:59:17 -08:00
|
|
|
// ConvertAddrsToValAddrs converts the provided addresses to ValAddress.
|
2020-02-26 07:05:12 -08:00
|
|
|
func ConvertAddrsToValAddrs(addrs []sdk.AccAddress) []sdk.ValAddress {
|
2020-02-26 07:16:56 -08:00
|
|
|
valAddrs := make([]sdk.ValAddress, len(addrs))
|
2020-02-26 07:05:12 -08:00
|
|
|
|
2020-02-26 07:16:56 -08:00
|
|
|
for i, addr := range addrs {
|
|
|
|
valAddrs[i] = sdk.ValAddress(addr)
|
2020-02-21 11:51:11 -08:00
|
|
|
}
|
|
|
|
|
2020-02-26 07:05:12 -08:00
|
|
|
return valAddrs
|
2020-02-21 11:51:11 -08:00
|
|
|
}
|
|
|
|
|
2020-02-26 07:05:12 -08:00
|
|
|
func TestAddr(addr string, bech string) (sdk.AccAddress, error) {
|
2020-02-21 10:34:07 -08:00
|
|
|
res, err := sdk.AccAddressFromHex(addr)
|
|
|
|
if err != nil {
|
2020-02-26 07:05:12 -08:00
|
|
|
return nil, err
|
2020-02-21 10:34:07 -08:00
|
|
|
}
|
|
|
|
bechexpected := res.String()
|
|
|
|
if bech != bechexpected {
|
2020-02-26 07:05:12 -08:00
|
|
|
return nil, fmt.Errorf("bech encoding doesn't match reference")
|
2020-02-21 10:34:07 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
bechres, err := sdk.AccAddressFromBech32(bech)
|
|
|
|
if err != nil {
|
2020-02-26 07:05:12 -08:00
|
|
|
return nil, err
|
2020-02-21 10:34:07 -08:00
|
|
|
}
|
|
|
|
if !bytes.Equal(bechres, res) {
|
2020-02-26 07:05:12 -08:00
|
|
|
return nil, err
|
2020-02-21 10:34:07 -08:00
|
|
|
}
|
|
|
|
|
2020-02-26 07:05:12 -08:00
|
|
|
return res, nil
|
2020-02-21 10:34:07 -08:00
|
|
|
}
|
|
|
|
|
2019-08-19 06:29:17 -07:00
|
|
|
// CheckBalance checks the balance of an account.
|
2020-01-30 13:31:16 -08:00
|
|
|
func CheckBalance(t *testing.T, app *SimApp, addr sdk.AccAddress, balances sdk.Coins) {
|
2020-08-14 10:58:53 -07:00
|
|
|
ctxCheck := app.BaseApp.NewContext(true, tmproto.Header{})
|
2020-01-30 13:31:16 -08:00
|
|
|
require.True(t, balances.IsEqual(app.BankKeeper.GetAllBalances(ctxCheck, addr)))
|
2019-08-19 06:29:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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(
|
2020-10-19 11:04:44 -07:00
|
|
|
t *testing.T, txCfg client.TxConfig, app *bam.BaseApp, header tmproto.Header, msgs []sdk.Msg,
|
2020-11-09 08:01:43 -08:00
|
|
|
chainID string, accNums, accSeqs []uint64, expSimPass, expPass bool, priv ...cryptotypes.PrivKey,
|
2019-12-27 09:57:54 -08:00
|
|
|
) (sdk.GasInfo, *sdk.Result, error) {
|
2019-08-19 06:29:17 -07:00
|
|
|
|
2020-07-14 10:33:31 -07:00
|
|
|
tx, err := helpers.GenTx(
|
2020-10-19 11:04:44 -07:00
|
|
|
txCfg,
|
2019-10-23 02:14:45 -07:00
|
|
|
msgs,
|
|
|
|
sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)},
|
2019-12-18 06:48:22 -08:00
|
|
|
helpers.DefaultGenTxGas,
|
2020-08-20 15:05:41 -07:00
|
|
|
chainID,
|
2019-10-23 02:14:45 -07:00
|
|
|
accNums,
|
2020-08-21 07:20:47 -07:00
|
|
|
accSeqs,
|
2019-10-23 02:14:45 -07:00
|
|
|
priv...,
|
|
|
|
)
|
2020-07-14 10:33:31 -07:00
|
|
|
require.NoError(t, err)
|
2020-10-19 11:04:44 -07:00
|
|
|
txBytes, err := txCfg.TxEncoder()(tx)
|
2019-08-19 06:29:17 -07:00
|
|
|
require.Nil(t, err)
|
|
|
|
|
|
|
|
// Must simulate now as CheckTx doesn't run Msgs anymore
|
2020-10-19 11:04:44 -07:00
|
|
|
_, res, err := app.Simulate(txBytes)
|
2019-08-19 06:29:17 -07:00
|
|
|
|
|
|
|
if expSimPass {
|
2019-12-27 09:57:54 -08:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, res)
|
2019-08-19 06:29:17 -07:00
|
|
|
} else {
|
2019-12-27 09:57:54 -08:00
|
|
|
require.Error(t, err)
|
|
|
|
require.Nil(t, res)
|
2019-08-19 06:29:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Simulate a sending a transaction and committing a block
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
refactor!: BaseApp {Check,Deliver}Tx with middleware design (#9920)
<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->
## Description
ref: #9585
This PR if the 1st step (out of 2) in the #9585 refactor. It transforms baseapp's ABCI {Check,Deliver}Tx into middleware stacks. A middleware is defined by the following interfaces:
```go
// types/tx package
type Handler interface {
CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error)
DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error)
SimulateTx(ctx context.Context, tx sdk.Tx, req RequestSimulateTx) (ResponseSimulateTx, error)
}
type Middleware func(Handler) Handler
```
This Pr doesn't migrate antehandlers, but only baseapp's runTx and runMsgs as middlewares. It bundles antehandlers into one single middleware (for now).
More specifically, it introduces the 5 following middlewares:
| Middleware | Description |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| RunMsgsTxMiddleware | This middleware replaces the old baseapp's `runMsgs`. |
| LegacyAnteMiddleware | This middleware is temporary, it bundles all antehandlers into one middleware. It's only created for the purpose of breaking the refactor into 2 pieces. **It will be removed in Part 2**, and each antehandler will be replaced by its own middleware. |
| IndexEventsTxMiddleware | This is a simple middleware that chooses which events to index in Tendermint. Replaces `baseapp.indexEvents` (which unfortunately still exists in baseapp too, because it's used to index Begin/EndBlock events) |
| RecoveryTxMiddleware | This index recovers from panics. It replaces baseapp.runTx's panic recovery. |
| GasTxMiddleware | This replaces the [`Setup`](https://github.com/cosmos/cosmos-sdk/blob/master/x/auth/ante/setup.go) Antehandler. It sets a GasMeter on sdk.Context. Note that before, GasMeter was set on sdk.Context inside the antehandlers, and there was some mess around the fact that antehandlers had their own panic recovery system so that the GasMeter could be read by baseapp's recovery system. Now, this mess is all removed: one middleware sets GasMeter, another one handles recovery. |
---
### Author Checklist
*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*
I have...
- [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [x] added `!` to the type prefix if API or client breaking change
- [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [x] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [x] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [x] added a changelog entry to `CHANGELOG.md`
- [x] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [x] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed
### Reviewers Checklist
*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*
I have...
- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
2021-08-25 07:40:33 -07:00
|
|
|
gInfo, res, err := app.SimDeliver(txCfg.TxEncoder(), tx)
|
2019-08-19 06:29:17 -07:00
|
|
|
|
|
|
|
if expPass {
|
2019-12-27 09:57:54 -08:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, res)
|
2019-08-19 06:29:17 -07:00
|
|
|
} else {
|
2019-12-27 09:57:54 -08:00
|
|
|
require.Error(t, err)
|
|
|
|
require.Nil(t, res)
|
2019-08-19 06:29:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
app.EndBlock(abci.RequestEndBlock{})
|
|
|
|
app.Commit()
|
|
|
|
|
2019-12-27 09:57:54 -08:00
|
|
|
return gInfo, res, err
|
2019-08-19 06:29:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// GenSequenceOfTxs generates a set of signed transactions of messages, such
|
|
|
|
// that they differ only by having the sequence numbers incremented between
|
|
|
|
// every transaction.
|
2020-11-09 08:01:43 -08:00
|
|
|
func GenSequenceOfTxs(txGen client.TxConfig, msgs []sdk.Msg, accNums []uint64, initSeqNums []uint64, numToGenerate int, priv ...cryptotypes.PrivKey) ([]sdk.Tx, error) {
|
2020-07-14 10:33:31 -07:00
|
|
|
txs := make([]sdk.Tx, numToGenerate)
|
|
|
|
var err error
|
2019-08-19 06:29:17 -07:00
|
|
|
for i := 0; i < numToGenerate; i++ {
|
2020-07-14 10:33:31 -07:00
|
|
|
txs[i], err = helpers.GenTx(
|
|
|
|
txGen,
|
2019-10-23 02:14:45 -07:00
|
|
|
msgs,
|
|
|
|
sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)},
|
2019-12-18 06:48:22 -08:00
|
|
|
helpers.DefaultGenTxGas,
|
2019-10-23 02:14:45 -07:00
|
|
|
"",
|
|
|
|
accNums,
|
|
|
|
initSeqNums,
|
|
|
|
priv...,
|
|
|
|
)
|
2020-07-14 10:33:31 -07:00
|
|
|
if err != nil {
|
|
|
|
break
|
|
|
|
}
|
2019-08-19 06:29:17 -07:00
|
|
|
incrementAllSequenceNumbers(initSeqNums)
|
|
|
|
}
|
|
|
|
|
2020-07-14 10:33:31 -07:00
|
|
|
return txs, err
|
2019-08-19 06:29:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func incrementAllSequenceNumbers(initSeqNums []uint64) {
|
|
|
|
for i := 0; i < len(initSeqNums); i++ {
|
|
|
|
initSeqNums[i]++
|
|
|
|
}
|
|
|
|
}
|
2020-02-20 07:09:25 -08:00
|
|
|
|
2020-02-28 10:07:10 -08:00
|
|
|
// CreateTestPubKeys returns a total of numPubKeys public keys in ascending order.
|
2020-11-09 08:01:43 -08:00
|
|
|
func CreateTestPubKeys(numPubKeys int) []cryptotypes.PubKey {
|
|
|
|
var publicKeys []cryptotypes.PubKey
|
2020-02-20 07:09:25 -08:00
|
|
|
var buffer bytes.Buffer
|
|
|
|
|
2020-02-28 09:58:55 -08:00
|
|
|
// start at 10 to avoid changing 1 to 01, 2 to 02, etc
|
2020-02-20 07:09:25 -08:00
|
|
|
for i := 100; i < (numPubKeys + 100); i++ {
|
|
|
|
numString := strconv.Itoa(i)
|
2020-02-28 09:59:26 -08:00
|
|
|
buffer.WriteString("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AF") // base pubkey string
|
|
|
|
buffer.WriteString(numString) // adding on final two digits to make pubkeys unique
|
2020-02-26 07:05:12 -08:00
|
|
|
publicKeys = append(publicKeys, NewPubKeyFromHex(buffer.String()))
|
2020-02-20 07:09:25 -08:00
|
|
|
buffer.Reset()
|
|
|
|
}
|
|
|
|
|
|
|
|
return publicKeys
|
|
|
|
}
|
|
|
|
|
2020-02-28 10:06:03 -08:00
|
|
|
// NewPubKeyFromHex returns a PubKey from a hex string.
|
2020-11-09 08:01:43 -08:00
|
|
|
func NewPubKeyFromHex(pk string) (res cryptotypes.PubKey) {
|
2020-02-20 07:09:25 -08:00
|
|
|
pkBytes, err := hex.DecodeString(pk)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2020-09-25 01:41:16 -07:00
|
|
|
if len(pkBytes) != ed25519.PubKeySize {
|
|
|
|
panic(errors.Wrap(errors.ErrInvalidPubKey, "invalid pubkey size"))
|
|
|
|
}
|
|
|
|
return &ed25519.PubKey{Key: pkBytes}
|
2020-02-20 07:09:25 -08:00
|
|
|
}
|
2020-11-02 11:10:14 -08:00
|
|
|
|
|
|
|
// EmptyAppOptions is a stub implementing AppOptions
|
|
|
|
type EmptyAppOptions struct{}
|
|
|
|
|
|
|
|
// Get implements AppOptions
|
|
|
|
func (ao EmptyAppOptions) Get(o string) interface{} {
|
|
|
|
return nil
|
|
|
|
}
|