Merge PR #3447: Consume Gas Proportional to Tx Size

This commit is contained in:
Alexander Bezobchuk 2019-02-04 15:35:12 -08:00 committed by Jack Zampolin
parent 3780b84290
commit 082295172e
21 changed files with 154 additions and 85 deletions

View File

@ -58,6 +58,8 @@ IMPROVEMENTS
* [\#3418](https://github.com/cosmos/cosmos-sdk/issues/3418) Add vesting account
genesis validation checks to `GaiaValidateGenesisState`.
* [\#3420](https://github.com/cosmos/cosmos-sdk/issues/3420) Added maximum length to governance proposal descriptions and titles
* [\#3256](https://github.com/cosmos/cosmos-sdk/issues/3256) Add gas consumption
for tx size in the ante handler.
* [\#3454](https://github.com/cosmos/cosmos-sdk/pull/3454) Add `--jail-whitelist` to `gaiad export` to enable testing of complex exports
* [\#3424](https://github.com/cosmos/cosmos-sdk/issues/3424) Allow generation of gentxs with empty memo field.

View File

@ -390,7 +390,7 @@ func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) (res abc
if err != nil {
result = err.Result()
} else {
result = app.Simulate(tx)
result = app.Simulate(txBytes, tx)
}
case "version":
return abci.ResponseQuery{
@ -718,7 +718,10 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
if r := recover(); r != nil {
switch rType := r.(type) {
case sdk.ErrorOutOfGas:
log := fmt.Sprintf("out of gas in location: %v", rType.Descriptor)
log := fmt.Sprintf(
"out of gas in location: %v; gasWanted: %d, gasUsed: %d",
rType.Descriptor, gasWanted, ctx.GasMeter().GasConsumed(),
)
result = sdk.ErrOutOfGas(log).Result()
default:
log := fmt.Sprintf("recovered: %v\nstack:\n%v", r, string(debug.Stack()))

View File

@ -655,20 +655,20 @@ func TestSimulateTx(t *testing.T) {
app.BeginBlock(abci.RequestBeginBlock{})
tx := newTxCounter(count, count)
txBytes, err := cdc.MarshalBinaryLengthPrefixed(tx)
require.Nil(t, err)
// simulate a message, check gas reported
result := app.Simulate(tx)
result := app.Simulate(txBytes, tx)
require.True(t, result.IsOK(), result.Log)
require.Equal(t, gasConsumed, result.GasUsed)
// simulate again, same result
result = app.Simulate(tx)
result = app.Simulate(txBytes, tx)
require.True(t, result.IsOK(), result.Log)
require.Equal(t, gasConsumed, result.GasUsed)
// simulate by calling Query with encoded tx
txBytes, err := cdc.MarshalBinaryLengthPrefixed(tx)
require.Nil(t, err)
query := abci.RequestQuery{
Path: "/app/simulate",
Data: txBytes,

View File

@ -14,8 +14,8 @@ func (app *BaseApp) Check(tx sdk.Tx) (result sdk.Result) {
}
// nolint - full tx execution
func (app *BaseApp) Simulate(tx sdk.Tx) (result sdk.Result) {
return app.runTx(runTxModeSimulate, nil, tx)
func (app *BaseApp) Simulate(txBytes []byte, tx sdk.Tx) (result sdk.Result) {
return app.runTx(runTxModeSimulate, txBytes, tx)
}
// nolint

View File

@ -11,9 +11,9 @@ import (
// nolint
const (
// DefaultGasAdjustment is applied to gas estimates to avoid tx
// execution failures due to state changes that might
// occur between the tx simulation and the actual run.
// DefaultGasAdjustment is applied to gas estimates to avoid tx execution
// failures due to state changes that might occur between the tx simulation
// and the actual run.
DefaultGasAdjustment = 1.0
DefaultGasLimit = 200000
GasFlagAuto = "auto"

View File

@ -209,7 +209,9 @@ func TestCoinSend(t *testing.T) {
require.Equal(t, http.StatusInternalServerError, res.StatusCode, body)
// run simulation and test success with estimated gas
res, body, _ = doTransferWithGas(t, port, seed, name1, memo, pw, addr, "10000", 1.0, true, false, fees)
res, body, _ = doTransferWithGas(
t, port, seed, name1, memo, pw, addr, "10000", 1.0, true, false, fees,
)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var gasEstResp rest.GasEstimateResponse
@ -285,7 +287,9 @@ func TestCoinSendGenerateSignAndBroadcast(t *testing.T) {
acc := getAccount(t, port, addr)
// simulate tx
res, body, _ := doTransferWithGas(t, port, seed, name1, memo, "", addr, client.GasFlagAuto, 1, true, false, fees)
res, body, _ := doTransferWithGas(
t, port, seed, name1, memo, "", addr, client.GasFlagAuto, 1.0, true, false, fees,
)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var gasEstResp rest.GasEstimateResponse

View File

@ -19,6 +19,15 @@ import (
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
)
// GasEstimateResponse defines a response definition for tx gas estimation.
type GasEstimateResponse struct {
GasEstimate uint64 `json:"gas_estimate"`
}
func (gr GasEstimateResponse) String() string {
return fmt.Sprintf("gas estimate: %d", gr.GasEstimate)
}
// CompleteAndBroadcastTxCLI implements a utility function that facilitates
// sending a series of messages in a signed transaction given a TxBuilder and a
// QueryContext. It ensures that the account exists, has a proper number and
@ -39,8 +48,11 @@ func CompleteAndBroadcastTxCLI(txBldr authtxb.TxBuilder, cliCtx context.CLIConte
if err != nil {
return err
}
fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBldr.GetGas())
gasEst := GasEstimateResponse{GasEstimate: txBldr.GetGas()}
fmt.Fprintf(os.Stderr, gasEst.String())
}
if cliCtx.Simulate {
return nil
}

View File

@ -79,7 +79,7 @@ func appStateFromGenesisFileFn(r *rand.Rand, accs []simulation.Account, genesisT
privKey := secp256k1.GenPrivKeySecp256k1(privkeySeed)
newAccs = append(newAccs, simulation.Account{privKey, privKey.PubKey(), acc.Address})
}
return json.RawMessage(genesis.AppState), newAccs, genesis.ChainID
return genesis.AppState, newAccs, genesis.ChainID
}
func appStateRandomizedFn(r *rand.Rand, accs []simulation.Account, genesisTimestamp time.Time) (json.RawMessage, []simulation.Account, string) {
@ -138,11 +138,11 @@ func appStateRandomizedFn(r *rand.Rand, accs []simulation.Account, genesisTimest
authGenesis := auth.GenesisState{
Params: auth.Params{
MemoCostPerByte: uint64(r.Intn(10) + 1),
MaxMemoCharacters: uint64(r.Intn(200-100) + 100),
MaxMemoCharacters: uint64(randIntBetween(r, 100, 200)),
TxSigLimit: uint64(r.Intn(7) + 1),
SigVerifyCostED25519: uint64(r.Intn(1000-500) + 500),
SigVerifyCostSecp256k1: uint64(r.Intn(1000-500) + 500),
TxSizeCostPerByte: uint64(randIntBetween(r, 5, 15)),
SigVerifyCostED25519: uint64(randIntBetween(r, 500, 1000)),
SigVerifyCostSecp256k1: uint64(randIntBetween(r, 500, 1000)),
},
}
fmt.Printf("Selected randomly generated auth parameters:\n\t%+v\n", authGenesis)

View File

@ -279,7 +279,7 @@ func TestGaiaCLIGasAuto(t *testing.T) {
}{}
err := cdc.UnmarshalJSON([]byte(stdout), &sendResp)
require.Nil(t, err)
require.Equal(t, sendResp.Response.GasWanted, sendResp.Response.GasUsed)
require.True(t, sendResp.Response.GasWanted >= sendResp.Response.GasUsed)
tests.WaitForNextNBlocksTM(1, f.Port)
// Check state has changed accordingly
@ -690,7 +690,7 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
// Unmarshal the response and ensure that gas was properly used
require.Nil(t, app.MakeCodec().UnmarshalJSON([]byte(stdout), &result))
require.Equal(t, msg.Fee.Gas, uint64(result.Response.GasUsed))
require.True(t, msg.Fee.Gas >= uint64(result.Response.GasUsed))
require.Equal(t, msg.Fee.Gas, uint64(result.Response.GasWanted))
tests.WaitForNextNBlocksTM(1, f.Port)

View File

@ -7,9 +7,11 @@ general purpose censorship of transactions of little economic value. Fees
are best suited as an anti-spam mechanism where validators are disinterested in
the use of the network and identities of users.
Fees are determined by the gas limits and gas prices transactions provide.
Operators should set minimum gas prices when starting their nodes. They must set
the unit costs of gas in each token denomination they wish to support:
Fees are determined by the gas limits and gas prices transactions provide, where
`fees = ceil(gasLimit * gasPrices)`. Txs incur gas costs for all state reads/writes,
signature verification, as well as costs proportional to the tx size. Operators
should set minimum gas prices when starting their nodes. They must set the unit
costs of gas in each token denomination they wish to support:
`gaiad start ... --minimum-gas-prices=0.00001steak,0.05photinos`

View File

@ -15,6 +15,17 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
var (
// simulation signature values used to estimate gas consumption
simSecp256k1Pubkey secp256k1.PubKeySecp256k1
simSecp256k1Sig [64]byte
)
func init() {
bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A")
copy(simSecp256k1Pubkey[:], bz)
}
// NewAnteHandler returns an AnteHandler that checks and increments sequence
// numbers, checks signatures & account numbers, and deducts fees from the first
// signer.
@ -54,8 +65,12 @@ func NewAnteHandler(ak AccountKeeper, fck FeeCollectionKeeper) sdk.AnteHandler {
if r := recover(); r != nil {
switch rType := r.(type) {
case sdk.ErrorOutOfGas:
log := fmt.Sprintf("out of gas in location: %v", rType.Descriptor)
log := fmt.Sprintf(
"out of gas in location: %v; gasWanted: %d, gasUsed: %d",
rType.Descriptor, stdTx.Fee.Gas, newCtx.GasMeter().GasConsumed(),
)
res = sdk.ErrOutOfGas(log).Result()
res.GasWanted = stdTx.Fee.Gas
res.GasUsed = newCtx.GasMeter().GasConsumed()
abort = true
@ -69,7 +84,9 @@ func NewAnteHandler(ak AccountKeeper, fck FeeCollectionKeeper) sdk.AnteHandler {
return newCtx, err.Result(), true
}
if res := ValidateMemo(newCtx.GasMeter(), stdTx, params); !res.IsOK() {
newCtx.GasMeter().ConsumeGas(params.TxSizeCostPerByte*sdk.Gas(len(newCtx.TxBytes())), "txSize")
if res := ValidateMemo(stdTx, params); !res.IsOK() {
return newCtx, res, true
}
@ -131,9 +148,8 @@ func GetSignerAcc(ctx sdk.Context, ak AccountKeeper, addr sdk.AccAddress) (Accou
return nil, sdk.ErrUnknownAddress(addr.String()).Result()
}
// ValidateMemo validates the memo and if successful consumes gas for
// verification.
func ValidateMemo(gasMeter sdk.GasMeter, stdTx StdTx, params Params) sdk.Result {
// ValidateMemo validates the memo size.
func ValidateMemo(stdTx StdTx, params Params) sdk.Result {
memoLength := len(stdTx.GetMemo())
if uint64(memoLength) > params.MaxMemoCharacters {
return sdk.ErrMemoTooLarge(
@ -144,7 +160,6 @@ func ValidateMemo(gasMeter sdk.GasMeter, stdTx StdTx, params Params) sdk.Result
).Result()
}
gasMeter.ConsumeGas(params.MemoCostPerByte*sdk.Gas(memoLength), "memo")
return sdk.Result{}
}
@ -164,7 +179,15 @@ func processSig(
return nil, sdk.ErrInternal("setting PubKey on signer's account").Result()
}
consumeSignatureVerificationGas(ctx.GasMeter(), sig.Signature, pubKey, params)
if simulate {
// Simulated txs should not contain a signature and are not required to
// contain a pubkey, so we must account for tx size of including a
// StdSignature (Amino encoding) and simulate gas consumption
// (assuming a SECP256k1 simulation key).
consumeSimSigGas(ctx.GasMeter(), pubKey, sig, params)
}
consumeSigVerificationGas(ctx.GasMeter(), sig.Signature, pubKey, params)
if !simulate && !pubKey.VerifyBytes(signBytes, sig.Signature) {
return nil, sdk.ErrUnauthorized("signature verification failed").Result()
}
@ -178,11 +201,22 @@ func processSig(
return acc, res
}
var dummySecp256k1Pubkey secp256k1.PubKeySecp256k1
func consumeSimSigGas(gasmeter sdk.GasMeter, pubkey crypto.PubKey, sig StdSignature, params Params) {
simSig := StdSignature{PubKey: pubkey}
if len(sig.Signature) == 0 {
simSig.Signature = simSecp256k1Sig[:]
}
func init() {
bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A")
copy(dummySecp256k1Pubkey[:], bz)
sigBz := msgCdc.MustMarshalBinaryLengthPrefixed(simSig)
cost := sdk.Gas(len(sigBz) + 6)
// If the pubkey is a multi-signature pubkey, then we estimate for the maximum
// number of signers.
if _, ok := pubkey.(multisig.PubKeyMultisigThreshold); ok {
cost *= params.TxSigLimit
}
gasmeter.ConsumeGas(params.TxSizeCostPerByte*cost, "txSize")
}
// ProcessPubKey verifies that the given account address matches that of the
@ -197,7 +231,7 @@ func ProcessPubKey(acc Account, sig StdSignature, simulate bool) (crypto.PubKey,
// shall consume the largest amount, i.e. it takes more gas to verify
// secp256k1 keys than ed25519 ones.
if pubKey == nil {
return dummySecp256k1Pubkey, sdk.Result{}
return simSecp256k1Pubkey, sdk.Result{}
}
return pubKey, sdk.Result{}
@ -218,25 +252,27 @@ func ProcessPubKey(acc Account, sig StdSignature, simulate bool) (crypto.PubKey,
return pubKey, sdk.Result{}
}
// consumeSignatureVerificationGas consumes gas for signature verification based
// upon the public key type. The cost is fetched from the given params and is
// matched by the concrete type.
// consumeSigVerificationGas consumes gas for signature verification based upon
// the public key type. The cost is fetched from the given params and is matched
// by the concrete type.
//
// TODO: Design a cleaner and flexible way to match concrete public key types.
func consumeSignatureVerificationGas(meter sdk.GasMeter, sig []byte, pubkey crypto.PubKey, params Params) {
func consumeSigVerificationGas(meter sdk.GasMeter, sig []byte, pubkey crypto.PubKey, params Params) {
pubkeyType := strings.ToLower(fmt.Sprintf("%T", pubkey))
switch {
case strings.Contains(pubkeyType, "ed25519"):
meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519")
case strings.Contains(pubkeyType, "secp256k1"):
meter.ConsumeGas(params.SigVerifyCostSecp256k1, "ante verify: secp256k1")
case strings.Contains(pubkeyType, "multisigthreshold"):
case strings.Contains(pubkeyType, "multisigthreshold"):
var multisignature multisig.Multisignature
codec.Cdc.MustUnmarshalBinaryBare(sig, &multisignature)
multisigPubKey := pubkey.(multisig.PubKeyMultisigThreshold)
multisigPubKey := pubkey.(multisig.PubKeyMultisigThreshold)
consumeMultisignatureVerificationGas(meter, multisignature, multisigPubKey, params)
default:
panic(fmt.Sprintf("unrecognized signature type: %s", pubkeyType))
}
@ -250,7 +286,7 @@ func consumeMultisignatureVerificationGas(meter sdk.GasMeter,
sigIndex := 0
for i := 0; i < size; i++ {
if sig.BitArray.GetIndex(i) {
consumeSignatureVerificationGas(meter, sig.Sigs[sigIndex], pubkey.PubKeys[i], params)
consumeSigVerificationGas(meter, sig.Sigs[sigIndex], pubkey.PubKeys[i], params)
sigIndex++
}
}
@ -294,8 +330,6 @@ func DeductFees(blockTime time.Time, acc Account, fee StdFee) (Account, sdk.Resu
// enough fees to cover a proposer's minimum fees. An result object is returned
// indicating success or failure.
//
// TODO: Account for transaction size.
//
// Contract: This should only be called during CheckTx as it cannot be part of
// consensus.
func EnsureSufficientMempoolFees(ctx sdk.Context, stdFee StdFee) sdk.Result {

View File

@ -595,9 +595,9 @@ func TestConsumeSignatureVerificationGas(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.wantPanic {
require.Panics(t, func() { consumeSignatureVerificationGas(tt.args.meter, tt.args.sig, tt.args.pubkey, tt.args.params) })
require.Panics(t, func() { consumeSigVerificationGas(tt.args.meter, tt.args.sig, tt.args.pubkey, tt.args.params) })
} else {
consumeSignatureVerificationGas(tt.args.meter, tt.args.sig, tt.args.pubkey, tt.args.params)
consumeSigVerificationGas(tt.args.meter, tt.args.sig, tt.args.pubkey, tt.args.params)
require.Equal(t, tt.gasConsumed, tt.args.meter.GasConsumed(), fmt.Sprintf("%d != %d", tt.gasConsumed, tt.args.meter.GasConsumed()))
}
})

View File

@ -54,8 +54,8 @@ func ValidateGenesis(data GenesisState) error {
if data.Params.MaxMemoCharacters == 0 {
return fmt.Errorf("invalid max memo characters: %d", data.Params.MaxMemoCharacters)
}
if data.Params.MemoCostPerByte == 0 {
return fmt.Errorf("invalid memo cost per byte: %d", data.Params.MemoCostPerByte)
if data.Params.TxSizeCostPerByte == 0 {
return fmt.Errorf("invalid tx size cost per byte: %d", data.Params.TxSizeCostPerByte)
}
return nil

View File

@ -6,7 +6,6 @@ import (
"strings"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/params"
)
@ -15,18 +14,18 @@ const DefaultParamspace = "auth"
// Default parameter values
const (
DefaultMemoCostPerByte sdk.Gas = 3
DefaultMaxMemoCharacters uint64 = 256
DefaultTxSigLimit uint64 = 7
DefaultSigVerifyCostED25519 uint64 = 590
DefaultSigVerifyCostSecp256k1 uint64 = 1000
DefaultMaxMemoCharacters uint64 = 256
DefaultTxSigLimit uint64 = 7
DefaultTxSizeCostPerByte uint64 = 10
DefaultSigVerifyCostED25519 uint64 = 590
DefaultSigVerifyCostSecp256k1 uint64 = 1000
)
// Parameter keys
var (
KeyMemoCostPerByte = []byte("MemoCostPerByte")
KeyMaxMemoCharacters = []byte("MaxMemoCharacters")
KeyTxSigLimit = []byte("TxSigLimit")
KeyTxSizeCostPerByte = []byte("TxSizeCostPerByte")
KeySigVerifyCostED25519 = []byte("SigVerifyCostED25519")
KeySigVerifyCostSecp256k1 = []byte("SigVerifyCostSecp256k1")
)
@ -35,9 +34,9 @@ var _ params.ParamSet = &Params{}
// Params defines the parameters for the auth module.
type Params struct {
MemoCostPerByte sdk.Gas
MaxMemoCharacters uint64
TxSigLimit uint64 // max total number of signatures per tx
TxSizeCostPerByte uint64
SigVerifyCostED25519 uint64
SigVerifyCostSecp256k1 uint64
}
@ -52,9 +51,9 @@ func ParamTypeTable() params.TypeTable {
// nolint
func (p *Params) KeyValuePairs() params.KeyValuePairs {
return params.KeyValuePairs{
{KeyMemoCostPerByte, &p.MemoCostPerByte},
{KeyMaxMemoCharacters, &p.MaxMemoCharacters},
{KeyTxSigLimit, &p.TxSigLimit},
{KeyTxSizeCostPerByte, &p.TxSizeCostPerByte},
{KeySigVerifyCostED25519, &p.SigVerifyCostED25519},
{KeySigVerifyCostSecp256k1, &p.SigVerifyCostSecp256k1},
}
@ -70,9 +69,9 @@ func (p Params) Equal(p2 Params) bool {
// DefaultParams returns a default set of parameters.
func DefaultParams() Params {
return Params{
MemoCostPerByte: DefaultMemoCostPerByte,
MaxMemoCharacters: DefaultMaxMemoCharacters,
TxSigLimit: DefaultTxSigLimit,
TxSizeCostPerByte: DefaultTxSizeCostPerByte,
SigVerifyCostED25519: DefaultSigVerifyCostED25519,
SigVerifyCostSecp256k1: DefaultSigVerifyCostSecp256k1,
}
@ -83,9 +82,9 @@ func (p Params) String() string {
var sb strings.Builder
sb.WriteString("Params: \n")
sb.WriteString(fmt.Sprintf("MemoCostPerByte: %v\n", p.MemoCostPerByte))
sb.WriteString(fmt.Sprintf("MaxMemoCharacters: %d\n", p.MaxMemoCharacters))
sb.WriteString(fmt.Sprintf("TxSigLimit: %d\n", p.TxSigLimit))
sb.WriteString(fmt.Sprintf("TxSizeCostPerByte: %d\n", p.TxSizeCostPerByte))
sb.WriteString(fmt.Sprintf("SigVerifyCostED25519: %d\n", p.SigVerifyCostED25519))
sb.WriteString(fmt.Sprintf("SigVerifyCostSecp256k1: %d\n", p.SigVerifyCostSecp256k1))

View File

@ -141,7 +141,7 @@ func TestMsgSendWithAccounts(t *testing.T) {
}
for _, tc := range testCases {
mock.SignCheckDeliver(t, mapp.BaseApp, tc.msgs, tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
mock.SignCheckDeliver(t, mapp.Cdc, mapp.BaseApp, tc.msgs, tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
for _, eb := range tc.expectedBalances {
mock.CheckBalance(t, mapp, eb.addr, eb.coins)
@ -180,7 +180,7 @@ func TestMsgSendMultipleOut(t *testing.T) {
}
for _, tc := range testCases {
mock.SignCheckDeliver(t, mapp.BaseApp, tc.msgs, tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
mock.SignCheckDeliver(t, mapp.Cdc, mapp.BaseApp, tc.msgs, tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
for _, eb := range tc.expectedBalances {
mock.CheckBalance(t, mapp, eb.addr, eb.coins)
@ -224,7 +224,7 @@ func TestSengMsgMultipleInOut(t *testing.T) {
}
for _, tc := range testCases {
mock.SignCheckDeliver(t, mapp.BaseApp, tc.msgs, tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
mock.SignCheckDeliver(t, mapp.Cdc, mapp.BaseApp, tc.msgs, tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
for _, eb := range tc.expectedBalances {
mock.CheckBalance(t, mapp, eb.addr, eb.coins)
@ -269,7 +269,7 @@ func TestMsgSendDependent(t *testing.T) {
}
for _, tc := range testCases {
mock.SignCheckDeliver(t, mapp.BaseApp, tc.msgs, tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
mock.SignCheckDeliver(t, mapp.Cdc, mapp.BaseApp, tc.msgs, tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
for _, eb := range tc.expectedBalances {
mock.CheckBalance(t, mapp, eb.addr, eb.coins)

View File

@ -72,10 +72,10 @@ func TestIBCMsgs(t *testing.T) {
Sequence: 0,
}
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{transferMsg}, []uint64{0}, []uint64{0}, true, true, priv1)
mock.SignCheckDeliver(t, mapp.Cdc, mapp.BaseApp, []sdk.Msg{transferMsg}, []uint64{0}, []uint64{0}, true, true, priv1)
mock.CheckBalance(t, mapp, addr1, emptyCoins)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{transferMsg}, []uint64{0}, []uint64{1}, false, false, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{receiveMsg}, []uint64{0}, []uint64{2}, true, true, priv1)
mock.SignCheckDeliver(t, mapp.Cdc, mapp.BaseApp, []sdk.Msg{transferMsg}, []uint64{0}, []uint64{1}, false, false, priv1)
mock.SignCheckDeliver(t, mapp.Cdc, mapp.BaseApp, []sdk.Msg{receiveMsg}, []uint64{0}, []uint64{2}, true, true, priv1)
mock.CheckBalance(t, mapp, addr1, coins)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{receiveMsg}, []uint64{0}, []uint64{2}, false, false, priv1)
mock.SignCheckDeliver(t, mapp.Cdc, mapp.BaseApp, []sdk.Msg{receiveMsg}, []uint64{0}, []uint64{2}, false, false, priv1)
}

View File

@ -51,10 +51,7 @@ func NewApp() *App {
db := dbm.NewMemDB()
// Create the cdc with some standard codecs
cdc := codec.New()
sdk.RegisterCodec(cdc)
codec.RegisterCrypto(cdc)
auth.RegisterCodec(cdc)
cdc := createCodec()
// Create your application object
app := &App{
@ -337,3 +334,11 @@ func incrementAllSequenceNumbers(initSeqNums []uint64) {
initSeqNums[i]++
}
}
func createCodec() *codec.Codec {
cdc := codec.New()
sdk.RegisterCodec(cdc)
codec.RegisterCrypto(cdc)
auth.RegisterCodec(cdc)
return cdc
}

View File

@ -61,14 +61,14 @@ func TestCheckAndDeliverGenTx(t *testing.T) {
require.Equal(t, accs[0], acct.(*auth.BaseAccount))
SignCheckDeliver(
t, mApp.BaseApp, []sdk.Msg{msg},
t, mApp.Cdc, mApp.BaseApp, []sdk.Msg{msg},
[]uint64{accs[0].GetAccountNumber()}, []uint64{accs[0].GetSequence()},
true, true, privKeys[0],
)
// Signing a tx with the wrong privKey should result in an auth error
res := SignCheckDeliver(
t, mApp.BaseApp, []sdk.Msg{msg},
t, mApp.Cdc, mApp.BaseApp, []sdk.Msg{msg},
[]uint64{accs[1].GetAccountNumber()}, []uint64{accs[1].GetSequence() + 1},
true, false, privKeys[1],
)
@ -78,7 +78,7 @@ func TestCheckAndDeliverGenTx(t *testing.T) {
// Resigning the tx with the correct privKey should result in an OK result
SignCheckDeliver(
t, mApp.BaseApp, []sdk.Msg{msg},
t, mApp.Cdc, mApp.BaseApp, []sdk.Msg{msg},
[]uint64{accs[0].GetAccountNumber()}, []uint64{accs[0].GetSequence() + 1},
true, true, privKeys[0],
)

View File

@ -5,6 +5,8 @@ import (
"math/rand"
"testing"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto"
@ -71,12 +73,16 @@ func CheckGenTx(
// the parameter 'expPass' against the result. A corresponding result is
// returned.
func SignCheckDeliver(
t *testing.T, app *baseapp.BaseApp, msgs []sdk.Msg, accNums []uint64,
seq []uint64, expSimPass, expPass bool, priv ...crypto.PrivKey,
t *testing.T, cdc *codec.Codec, app *baseapp.BaseApp, msgs []sdk.Msg,
accNums []uint64, seq []uint64, expSimPass, expPass bool, priv ...crypto.PrivKey,
) sdk.Result {
tx := GenTx(msgs, accNums, seq, priv...)
txBytes, err := cdc.MarshalBinaryLengthPrefixed(tx)
require.Nil(t, err)
// Must simulate now as CheckTx doesn't run Msgs anymore
res := app.Simulate(tx)
res := app.Simulate(txBytes, tx)
if expSimPass {
require.Equal(t, sdk.CodeOK, res.Code, res.Log)

View File

@ -26,6 +26,8 @@ func getMockApp(t *testing.T) (*mock.App, staking.Keeper, Keeper) {
mapp := mock.NewApp()
RegisterCodec(mapp.Cdc)
stakingTypes.RegisterCodec(mapp.Cdc)
keyStaking := sdk.NewKVStoreKey(staking.StoreKey)
tkeyStaking := sdk.NewTransientStoreKey(staking.TStoreKey)
keySlashing := sdk.NewKVStoreKey(StoreKey)
@ -107,7 +109,7 @@ func TestSlashingMsgs(t *testing.T) {
createValidatorMsg := staking.NewMsgCreateValidator(
sdk.ValAddress(addr1), priv1.PubKey(), bondCoin, description, commission,
)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{createValidatorMsg}, []uint64{0}, []uint64{0}, true, true, priv1)
mock.SignCheckDeliver(t, mapp.Cdc, mapp.BaseApp, []sdk.Msg{createValidatorMsg}, []uint64{0}, []uint64{0}, true, true, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{genCoin.Minus(bondCoin)})
mapp.BeginBlock(abci.RequestBeginBlock{})
@ -121,7 +123,7 @@ func TestSlashingMsgs(t *testing.T) {
checkValidatorSigningInfo(t, mapp, keeper, sdk.ConsAddress(addr1), false)
// unjail should fail with unknown validator
res := mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{unjailMsg}, []uint64{0}, []uint64{1}, false, false, priv1)
res := mock.SignCheckDeliver(t, mapp.Cdc, mapp.BaseApp, []sdk.Msg{unjailMsg}, []uint64{0}, []uint64{1}, false, false, priv1)
require.EqualValues(t, CodeValidatorNotJailed, res.Code)
require.EqualValues(t, DefaultCodespace, res.Codespace)
}

View File

@ -120,7 +120,7 @@ func TestStakingMsgs(t *testing.T) {
sdk.ValAddress(addr1), priv1.PubKey(), bondCoin, description, commissionMsg,
)
mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{createValidatorMsg}, []uint64{0}, []uint64{0}, true, true, priv1)
mock.SignCheckDeliver(t, mApp.Cdc, mApp.BaseApp, []sdk.Msg{createValidatorMsg}, []uint64{0}, []uint64{0}, true, true, priv1)
mock.CheckBalance(t, mApp, addr1, sdk.Coins{genCoin.Minus(bondCoin)})
mApp.BeginBlock(abci.RequestBeginBlock{})
@ -134,7 +134,7 @@ func TestStakingMsgs(t *testing.T) {
addr1, sdk.ValAddress(addr2), priv2.PubKey(), bondCoin, description, commissionMsg,
)
mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{createValidatorMsgOnBehalfOf}, []uint64{0, 0}, []uint64{1, 0}, true, true, priv1, priv2)
mock.SignCheckDeliver(t, mApp.Cdc, mApp.BaseApp, []sdk.Msg{createValidatorMsgOnBehalfOf}, []uint64{0, 0}, []uint64{1, 0}, true, true, priv1, priv2)
mock.CheckBalance(t, mApp, addr1, sdk.Coins{genCoin.Minus(bondCoin).Minus(bondCoin)})
mApp.BeginBlock(abci.RequestBeginBlock{})
@ -150,7 +150,7 @@ func TestStakingMsgs(t *testing.T) {
description = NewDescription("bar_moniker", "", "", "")
editValidatorMsg := NewMsgEditValidator(sdk.ValAddress(addr1), description, nil)
mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{editValidatorMsg}, []uint64{0}, []uint64{2}, true, true, priv1)
mock.SignCheckDeliver(t, mApp.Cdc, mApp.BaseApp, []sdk.Msg{editValidatorMsg}, []uint64{0}, []uint64{2}, true, true, priv1)
validator = checkValidator(t, mApp, keeper, sdk.ValAddress(addr1), true)
require.Equal(t, description, validator.Description)
@ -158,13 +158,13 @@ func TestStakingMsgs(t *testing.T) {
mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin})
delegateMsg := NewMsgDelegate(addr2, sdk.ValAddress(addr1), bondCoin)
mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{delegateMsg}, []uint64{0}, []uint64{1}, true, true, priv2)
mock.SignCheckDeliver(t, mApp.Cdc, mApp.BaseApp, []sdk.Msg{delegateMsg}, []uint64{0}, []uint64{1}, true, true, priv2)
mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)})
checkDelegation(t, mApp, keeper, addr2, sdk.ValAddress(addr1), true, sdk.NewDec(10))
// begin unbonding
beginUnbondingMsg := NewMsgUndelegate(addr2, sdk.ValAddress(addr1), sdk.NewDec(10))
mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{beginUnbondingMsg}, []uint64{0}, []uint64{2}, true, true, priv2)
mock.SignCheckDeliver(t, mApp.Cdc, mApp.BaseApp, []sdk.Msg{beginUnbondingMsg}, []uint64{0}, []uint64{2}, true, true, priv2)
// delegation should exist anymore
checkDelegation(t, mApp, keeper, addr2, sdk.ValAddress(addr1), false, sdk.Dec{})