Merge branch 'develop' into alessio/validate-addr-when-adding-genesis-account

This commit is contained in:
Christopher Goes 2018-11-16 11:44:41 +01:00 committed by GitHub
commit eb27c70292
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 187 additions and 75 deletions

View File

@ -9,11 +9,14 @@ BREAKING CHANGES
* [cli] [\#2727](https://github.com/cosmos/cosmos-sdk/pull/2727) Fix unbonding command flow
* [cli] [\#2786](https://github.com/cosmos/cosmos-sdk/pull/2786) Fix redelegation command flow
* [cli] [\#2829](https://github.com/cosmos/cosmos-sdk/pull/2829) add-genesis-account command now validates state when adding accounts
* [cli] [\#2804](https://github.com/cosmos/cosmos-sdk/issues/2804) Check whether key exists before passing it on to `tx create-validator`.
* Gaia
* SDK
* [\#2752](https://github.com/cosmos/cosmos-sdk/pull/2752) Don't hardcode bondable denom.
* [\#2019](https://github.com/cosmos/cosmos-sdk/issues/2019) Cap total number of signatures. Current per-transaction limit is 7, and if that is exceeded transaction is rejected.
* [\#2801](https://github.com/cosmos/cosmos-sdk/pull/2801) Remove AppInit structure.
* Tendermint
@ -33,6 +36,7 @@ FEATURES
* [app] \#2791 Support export at a specific height, with `gaiad export --height=HEIGHT`.
* [x/gov] [#2479](https://github.com/cosmos/cosmos-sdk/issues/2479) Implemented querier
for getting governance parameters.
* [app] \#2663 - Runtime-assertable invariants
* [app] \#2791 Support export at a specific height, with `gaiad export --height=HEIGHT`.
* SDK

View File

@ -12,7 +12,7 @@
[![riot.im](https://img.shields.io/badge/riot.im-JOIN%20CHAT-green.svg)](https://riot.im/app/#/room/#cosmos-sdk:matrix.org)
The Cosmos-SDK is a framework for building blockchain applications in Golang.
It is being used to build `Gaia`, the first implementation of the [Cosmos Hub](https://cosmos.network/docs/),
It is being used to build `Gaia`, the first implementation of the Cosmos Hub.
**WARNING**: The SDK has mostly stabilized, but we are still making some
breaking changes.

View File

@ -210,6 +210,8 @@ func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.R
tags := gov.EndBlocker(ctx, app.govKeeper)
validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper)
app.assertRuntimeInvariants()
return abci.ResponseEndBlock{
ValidatorUpdates: validatorUpdates,
Tags: tags,

View File

@ -11,7 +11,6 @@ import (
"strings"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
distr "github.com/cosmos/cosmos-sdk/x/distribution"
@ -92,13 +91,6 @@ func (ga *GenesisAccount) ToAccount() (acc *auth.BaseAccount) {
}
}
// get app init parameters for server init command
func GaiaAppInit() server.AppInit {
return server.AppInit{
AppGenState: GaiaAppGenStateJSON,
}
}
// Create the core parameters for genesis initialization for gaia
// note that the pubkey input is this machines pubkey

View File

@ -0,0 +1,34 @@
package app
import (
"fmt"
"time"
banksim "github.com/cosmos/cosmos-sdk/x/bank/simulation"
distrsim "github.com/cosmos/cosmos-sdk/x/distribution/simulation"
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
stakesim "github.com/cosmos/cosmos-sdk/x/stake/simulation"
)
func (app *GaiaApp) runtimeInvariants() []simulation.Invariant {
return []simulation.Invariant{
banksim.NonnegativeBalanceInvariant(app.accountKeeper),
distrsim.ValAccumInvariants(app.distrKeeper, app.stakeKeeper),
stakesim.SupplyInvariants(app.bankKeeper, app.stakeKeeper,
app.feeCollectionKeeper, app.distrKeeper, app.accountKeeper),
stakesim.PositivePowerInvariant(app.stakeKeeper),
}
}
func (app *GaiaApp) assertRuntimeInvariants() {
invariants := app.runtimeInvariants()
start := time.Now()
for _, inv := range invariants {
if err := inv(app.BaseApp); err != nil {
panic(fmt.Errorf("invariant broken: %s", err))
}
}
end := time.Now()
diff := end.Sub(start)
app.BaseApp.Logger.With("module", "invariants").Info("Asserted all invariants", "duration", diff)
}

View File

@ -37,15 +37,13 @@ func main() {
Short: "Gaia Daemon (server)",
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
}
appInit := app.GaiaAppInit()
rootCmd.AddCommand(gaiaInit.InitCmd(ctx, cdc, appInit))
rootCmd.AddCommand(gaiaInit.InitCmd(ctx, cdc))
rootCmd.AddCommand(gaiaInit.CollectGenTxsCmd(ctx, cdc))
rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, server.AppInit{}))
rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc))
rootCmd.AddCommand(gaiaInit.GenTxCmd(ctx, cdc))
rootCmd.AddCommand(gaiaInit.AddGenesisAccountCmd(ctx, cdc))
server.AddCommands(ctx, cdc, rootCmd, appInit,
newApp, exportAppStateAndTMValidators)
server.AddCommands(ctx, cdc, rootCmd, newApp, exportAppStateAndTMValidators)
// prepare and add flags
executor := cli.PrepareBaseCmd(rootCmd, "GA", app.DefaultNodeHome)

View File

@ -3,6 +3,7 @@ package init
import (
"fmt"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server"
@ -61,6 +62,14 @@ following delegation and commission default parameters:
return err
}
kb, err := keys.GetKeyBaseFromDir(viper.GetString(flagClientHome))
if err != nil {
return err
}
if _, err = kb.Get(viper.GetString(client.FlagName)); err != nil {
return err
}
// Read --pubkey, if empty take it from priv_validator.json
if valPubKeyString := viper.GetString(cli.FlagPubKey); valPubKeyString != "" {
valPubKey, err = sdk.GetConsPubKeyBech32(valPubKeyString)

View File

@ -42,7 +42,7 @@ func displayInfo(cdc *codec.Codec, info printInfo) error {
// get cmd to initialize all files for tendermint and application
// nolint
func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cobra.Command {
func InitCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "init",
Short: "Initialize private validator, p2p, genesis, and application configuration files",

View File

@ -32,10 +32,7 @@ func TestInitCmd(t *testing.T) {
ctx := server.NewContext(cfg, logger)
cdc := app.MakeCodec()
appInit := server.AppInit{
AppGenState: mock.AppGenState,
}
cmd := InitCmd(ctx, cdc, appInit)
cmd := InitCmd(ctx, cdc)
viper.Set(flagMoniker, "gaianode-test")
@ -65,13 +62,9 @@ func TestEmptyState(t *testing.T) {
ctx := server.NewContext(cfg, logger)
cdc := app.MakeCodec()
appInit := server.AppInit{
AppGenState: mock.AppGenStateEmpty,
}
viper.Set(flagMoniker, "gaianode-test")
cmd := InitCmd(ctx, cdc, appInit)
cmd := InitCmd(ctx, cdc)
err = cmd.RunE(nil, nil)
require.NoError(t, err)
@ -116,10 +109,7 @@ func TestStartStandAlone(t *testing.T) {
require.Nil(t, err)
ctx := server.NewContext(cfg, logger)
cdc := app.MakeCodec()
appInit := server.AppInit{
AppGenState: mock.AppGenState,
}
initCmd := InitCmd(ctx, cdc, appInit)
initCmd := InitCmd(ctx, cdc)
err = initCmd.RunE(nil, nil)
require.NoError(t, err)

View File

@ -38,8 +38,7 @@ var (
const nodeDirPerm = 0755
// get cmd to initialize all files for tendermint testnet and application
func TestnetFilesCmd(ctx *server.Context, cdc *codec.Codec,
appInit server.AppInit) *cobra.Command {
func TestnetFilesCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "testnet",

View File

@ -26,12 +26,13 @@ module.exports = {
children: [
"/gaia/installation",
"/gaia/join-testnet",
"/gaia/networks",
"/gaia/validators/validator-setup",
"/gaia/validators/overview",
"/gaia/validators/security",
"/gaia/validators/validator-faq",
"/gaia/validators/validator-setup",
"/gaia/ledger"
"/gaia/networks",
"/gaia/ledger",
"/gaia/gaiacli"
]
},
{

View File

@ -98,11 +98,6 @@ The `simplegovd` command will run the daemon server as a background process. Fir
```go
// cmd/simplegovd/main.go
// SimpleGovAppInit initial parameters
var SimpleGovAppInit = server.AppInit{
AppGenState: SimpleGovAppGenState,
AppGenTx: server.SimpleAppGenTx,
}
// SimpleGovAppGenState sets up the app_state and appends the simpleGov app state
func SimpleGovAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (appState json.RawMessage, err error) {
@ -137,7 +132,7 @@ func main() {
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
}
server.AddCommands(ctx, cdc, rootCmd, SimpleGovAppInit,
server.AddCommands(ctx, cdc, rootCmd,
server.ConstructAppCreator(newApp, "simplegov"),
server.ConstructAppExporter(exportAppState, "simplegov"))

View File

@ -39,11 +39,9 @@ func main() {
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
}
appInit := server.DefaultAppInit
rootCmd.AddCommand(InitCmd(ctx, cdc, appInit))
rootCmd.AddCommand(InitCmd(ctx, cdc))
server.AddCommands(ctx, cdc, rootCmd, appInit,
newApp, exportAppStateAndTMValidators)
server.AddCommands(ctx, cdc, rootCmd, newApp, exportAppStateAndTMValidators)
// prepare and add flags
rootDir := os.ExpandEnv("$HOME/.basecoind")
@ -58,7 +56,7 @@ func main() {
// get cmd to initialize all files for tendermint and application
// nolint: errcheck
func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cobra.Command {
func InitCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "init",
Short: "Initialize genesis config, priv-validator file, and p2p-node file",
@ -84,7 +82,7 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob
return err
}
appState, err := appInit.AppGenState(
appState, err := server.SimpleAppGenState(
cdc, tmtypes.GenesisDoc{}, []json.RawMessage{genTx})
if err != nil {
return err

View File

@ -30,10 +30,6 @@ const (
flagClientHome = "home-client"
)
// init parameters
var CoolAppInit = server.AppInit{
AppGenState: CoolAppGenState,
}
// coolGenAppParams sets up the app_state and appends the cool app state
func CoolAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) (
@ -65,7 +61,7 @@ func CoolAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []js
// get cmd to initialize all files for tendermint and application
// nolint: errcheck
func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cobra.Command {
func InitCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "init",
Short: "Initialize genesis config, priv-validator file, and p2p-node file",
@ -91,7 +87,7 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob
return err
}
appState, err := appInit.AppGenState(cdc, tmtypes.GenesisDoc{},
appState, err := CoolAppGenState(cdc, tmtypes.GenesisDoc{},
[]json.RawMessage{genTx})
if err != nil {
return err
@ -157,11 +153,10 @@ func main() {
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
}
rootCmd.AddCommand(InitCmd(ctx, cdc, CoolAppInit))
rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, CoolAppInit))
rootCmd.AddCommand(InitCmd(ctx, cdc))
rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc))
server.AddCommands(ctx, cdc, rootCmd, CoolAppInit,
newApp, exportAppStateAndTMValidators)
server.AddCommands(ctx, cdc, rootCmd, newApp, exportAppStateAndTMValidators)
// prepare and add flags
rootDir := os.ExpandEnv("$HOME/.democoind")

View File

@ -17,18 +17,18 @@ These instructions are for setting up a brand new full node from scratch.
First, initialize the node and create the necessary config files:
```bash
gaiad init
gaiad init --moniker <your_custom_moniker>
```
::: warning Note
Only ASCII characters are supported for the `--name`. Using Unicode characters will render your node unreachable.
Only ASCII characters are supported for the `--moniker`. Using Unicode characters will render your node unreachable.
:::
You can edit this `name` later, in the `~/.gaiad/config/config.toml` file:
You can edit this `moniker` later, in the `~/.gaiad/config/config.toml` file:
```toml
# A custom human readable name for this node
moniker = "<your_custom_name>"
moniker = "<your_custom_moniker>"
```
You can edit the `~/.gaiad/config/gaiad.toml` file in order to enable the anti spam mechanism and reject incoming transactions with less than a minimum fee:

View File

@ -8,11 +8,11 @@ It is based on two major principles:
- **Composability:** Anyone can create a module for the Cosmos-SDK, and integrating the already-built modules is as simple as importing them into your blockchain application.
- **Capabilities:** The SDK is inspired by capabilities-based security, and informed by years of wrestling with blockchain state-machines. Most developers will need to access other 3rd party modules when building their own modules. Given that the Cosmos-SDK is an open framework, some of the modules may be malicious, which means there is a need for security principles to reason about inter-module interactions. These principles are based on object-cababilities. In practice, this means that instead of having each module keep an access control list for other modules, each module implements special objects called keepers that can be passed to other modules to grant a pre-defined set of capabilities. For example, if an instance of module A's keepers is passed to module B, the latter will be able to call a restricted set of module A's functions. The capabilities of each keeper are defined by the module's developer, and it's the developer's job to understand and audit the safety of foreign code from 3rd party modules based on the capabilities they are passing into each third party module. For a deeper look at capabilities, jump to [this section](./capabilities.md).
- **Capabilities:** The SDK is inspired by capabilities-based security, and informed by years of wrestling with blockchain state-machines. Most developers will need to access other 3rd party modules when building their own modules. Given that the Cosmos-SDK is an open framework, some of the modules may be malicious, which means there is a need for security principles to reason about inter-module interactions. These principles are based on object-cababilities. In practice, this means that instead of having each module keep an access control list for other modules, each module implements special objects called keepers that can be passed to other modules to grant a pre-defined set of capabilities. For example, if an instance of module A's keepers is passed to module B, the latter will be able to call a restricted set of module A's functions. The capabilities of each keeper are defined by the module's developer, and it's the developer's job to understand and audit the safety of foreign code from 3rd party modules based on the capabilities they are passing into each third party module. For a deeper look at capabilities, jump to [this section](./ocap.md).
## Learn more about the SDK
- [SDK application architecture](./design.md)
- [SDK application architecture](./sdk-app-architecture.md)
- [SDK security paradigm: ocap](./ocap.md)
## Creating a new SDK project

View File

@ -2,8 +2,7 @@
`baseApp` requires stores to be mounted via capabilities keys - handlers can only access stores they're given the key to. The `baseApp` ensures all stores are properly loaded, cached, and committed. One mounted store is considered the "main" - it holds the latest block header, from which we can find and load the most recent state.
`baseApp` distinguishes between two handler types - the `AnteHandler` and the `MsgHandler`. The former is a global validity check (checking nonces, sigs and sufficient balances to pay fees,
e.g. things that apply to all transaction from all modules), the later is the full state transition function.
`baseApp` distinguishes between two handler types: `AnteHandler` and `MsgHandler`. Whilst the former is a global validity check that applies to all transactions from all modules, i.e. it checks nonces and whether balances are sufficient to pay fees, validates signatures and ensures that transactions don't carry too many signatures, the latter is the full state transition function.
During CheckTx the state transition function is only applied to the checkTxState and should return
before any expensive state transitions are run (this is up to each developer). It also needs to return the estimated
gas cost.

View File

@ -15,13 +15,6 @@ import (
tmtypes "github.com/tendermint/tendermint/types"
)
// Core functionality passed from the application to the server init command
type AppInit struct {
// AppGenState creates the core parameters initialization. It takes in a
// pubkey meant to represent the pubkey of the validator of this machine.
AppGenState func(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) (
appState json.RawMessage, err error)
}
// SimpleGenTx is a simple genesis tx
type SimpleGenTx struct {
@ -30,10 +23,6 @@ type SimpleGenTx struct {
//_____________________________________________________________________
// simple default application init
var DefaultAppInit = AppInit{
AppGenState: SimpleAppGenState,
}
// Generate a genesis transaction
func SimpleAppGenTx(cdc *codec.Codec, pk crypto.PubKey) (

View File

@ -129,7 +129,7 @@ func validateConfig(conf *cfg.Config) error {
// add server commands
func AddCommands(
ctx *Context, cdc *codec.Codec,
rootCmd *cobra.Command, appInit AppInit,
rootCmd *cobra.Command,
appCreator AppCreator, appExport AppExporter) {
rootCmd.PersistentFlags().String("log_level", ctx.Config.LogLevel, "Log level")

View File

@ -57,6 +57,7 @@ const (
CodeOutOfGas CodeType = 12
CodeMemoTooLarge CodeType = 13
CodeInsufficientFee CodeType = 14
CodeTooManySignatures CodeType = 15
// CodespaceRoot is a codespace for error codes in this file only.
// Notice that 0 is an "unset" codespace, which can be overridden with
@ -103,6 +104,8 @@ func CodeToDefaultMsg(code CodeType) string {
return "memo too large"
case CodeInsufficientFee:
return "insufficient fee"
case CodeTooManySignatures:
return "maximum numer of signatures exceeded"
default:
return unknownCodeMsg(code)
}
@ -155,6 +158,9 @@ func ErrMemoTooLarge(msg string) Error {
func ErrInsufficientFee(msg string) Error {
return newErrorWithRootCodespace(CodeInsufficientFee, msg)
}
func ErrTooManySignatures(msg string) Error {
return newErrorWithRootCodespace(CodeTooManySignatures, msg)
}
//----------------------------------------
// Error & sdkError

View File

@ -4,9 +4,11 @@ import (
"bytes"
"encoding/hex"
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/multisig"
"github.com/tendermint/tendermint/crypto/secp256k1"
)
@ -17,6 +19,8 @@ const (
maxMemoCharacters = 100
// how much gas = 1 atom
gasPerUnitCost = 1000
// max total number of sigs per tx
txSigLimit = 7
)
// NewAnteHandler returns an AnteHandler that checks
@ -74,6 +78,16 @@ func NewAnteHandler(am AccountKeeper, fck FeeCollectionKeeper) sdk.AnteHandler {
stdSigs := stdTx.GetSignatures() // When simulating, this would just be a 0-length slice.
signerAddrs := stdTx.GetSigners()
sigCount := 0
for i := 0; i < len(stdSigs); i++ {
sigCount += countSubKeys(stdSigs[i].PubKey)
if sigCount > txSigLimit {
return newCtx, sdk.ErrTooManySignatures(fmt.Sprintf(
"signatures: %d, limit: %d", sigCount, txSigLimit),
).Result(), true
}
}
// create the list of all sign bytes
signBytesList := getSignBytesList(newCtx.ChainID(), stdTx, stdSigs)
signerAccs, res := getSignerAccs(newCtx, am, signerAddrs)
@ -308,3 +322,15 @@ func getSignBytesList(chainID string, stdTx StdTx, stdSigs []StdSignature) (sign
}
return
}
func countSubKeys(pub crypto.PubKey) int {
v, ok := pub.(*multisig.PubKeyMultisigThreshold)
if !ok {
return 1
}
nkeys := 0
for _, subkey := range v.PubKeys {
nkeys += countSubKeys(subkey)
}
return nkeys
}

View File

@ -10,6 +10,7 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/multisig"
"github.com/tendermint/tendermint/crypto/secp256k1"
"github.com/tendermint/tendermint/libs/log"
)
@ -714,3 +715,77 @@ func TestAdjustFeesByGas(t *testing.T) {
})
}
}
func TestCountSubkeys(t *testing.T) {
genPubKeys := func(n int) []crypto.PubKey {
var ret []crypto.PubKey
for i := 0; i < n; i++ {
ret = append(ret, secp256k1.GenPrivKey().PubKey())
}
return ret
}
genMultiKey := func(n, k int, keysGen func(n int) []crypto.PubKey) crypto.PubKey {
return multisig.NewPubKeyMultisigThreshold(k, keysGen(n))
}
type args struct {
pub crypto.PubKey
}
mkey := genMultiKey(5, 4, genPubKeys)
mkeyType := mkey.(*multisig.PubKeyMultisigThreshold)
mkeyType.PubKeys = append(mkeyType.PubKeys, genMultiKey(6, 5, genPubKeys))
tests := []struct {
name string
args args
want int
}{
{"single key", args{secp256k1.GenPrivKey().PubKey()}, 1},
{"multi sig key", args{genMultiKey(5, 4, genPubKeys)}, 5},
{"multi multi sig", args{mkey}, 11},
}
for _, tt := range tests {
t.Run(tt.name, func(T *testing.T) {
require.Equal(t, tt.want, countSubKeys(tt.args.pub))
})
}
}
func TestAnteHandlerSigLimitExceeded(t *testing.T) {
// setup
ms, capKey, capKey2 := setupMultiStore()
cdc := codec.New()
RegisterBaseAccount(cdc)
mapper := NewAccountKeeper(cdc, capKey, ProtoBaseAccount)
feeCollector := NewFeeCollectionKeeper(cdc, capKey2)
anteHandler := NewAnteHandler(mapper, feeCollector)
ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, log.NewNopLogger())
ctx = ctx.WithBlockHeight(1)
// keys and addresses
priv1, addr1 := privAndAddr()
priv2, addr2 := privAndAddr()
priv3, addr3 := privAndAddr()
priv4, addr4 := privAndAddr()
priv5, addr5 := privAndAddr()
priv6, addr6 := privAndAddr()
priv7, addr7 := privAndAddr()
priv8, addr8 := privAndAddr()
// set the accounts
acc1 := mapper.NewAccountWithAddress(ctx, addr1)
acc1.SetCoins(newCoins())
mapper.SetAccount(ctx, acc1)
acc2 := mapper.NewAccountWithAddress(ctx, addr2)
acc2.SetCoins(newCoins())
mapper.SetAccount(ctx, acc2)
var tx sdk.Tx
msg := newTestMsg(addr1, addr2, addr3, addr4, addr5, addr6, addr7, addr8)
msgs := []sdk.Msg{msg}
fee := newStdFee()
// test rejection logic
privs, accnums, seqs := []crypto.PrivKey{priv1, priv2, priv3, priv4, priv5, priv6, priv7, priv8},
[]int64{0, 0, 0, 0, 0, 0, 0, 0}, []int64{0, 0, 0, 0, 0, 0, 0, 0}
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeTooManySignatures)
}