Compare commits

..
11 Commits
Author SHA1 Message Date
i-norden 21f42d27c7 update go modules 2022-03-01 08:27:52 -06:00
i-norden a031f9abca fixes 2022-03-01 08:20:49 -06:00
i-norden 47bafe4619 port auth module here for old version of ante module 2022-03-01 08:20:37 -06:00
i-norden fc0ade482d adjustments to work with smt/v0.44.6 2022-03-01 08:00:33 -06:00
Brian Ginsburg dbaaef07c7 bgins instruction tweaks 2021-11-09 11:17:18 -08:00
Boris Mann b9e7398220 Merge pull request #9 from gsk967/sai/testnet_docs
testnet docs
2021-11-08 11:40:02 -08:00
Sai Kumar 1aa98edb04 docs: update the genesis download instruction 2021-11-03 15:00:44 +05:30
Sai Kumar 9794007231 docs: update the testnet docs 2021-11-03 12:34:12 +05:30
Sai Kumar d41612b891 docs: updated testnet readme 2021-10-27 11:51:33 +05:30
Sai Kumar 3ef957206c docs: add golang install instructions 2021-10-27 11:50:32 +05:30
Sai Kumar 151747bc81 docs: add testnet docs 2021-10-25 18:35:59 +05:30
31 changed files with 4412 additions and 138 deletions
+1 -1
View File
@@ -11,9 +11,9 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
authante "github.com/tharsis/ethermint/x/auth/ante"
channelkeeper "github.com/cosmos/ibc-go/modules/core/04-channel/keeper"
ibcante "github.com/cosmos/ibc-go/modules/core/ante"
+3 -2
View File
@@ -4,9 +4,10 @@ import (
"errors"
"math/big"
authante "github.com/tharsis/ethermint/x/auth/ante"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/palantir/stacktrace"
ethermint "github.com/tharsis/ethermint/types"
@@ -28,7 +29,7 @@ type EVMKeeper interface {
GetParams(ctx sdk.Context) evmtypes.Params
WithContext(ctx sdk.Context)
ResetRefundTransient(ctx sdk.Context)
NewEVM(msg core.Message, config *params.ChainConfig, params evmtypes.Params, coinbase common.Address, tracer vm.Tracer) *vm.EVM
NewEVM(msg core.Message, config *params.ChainConfig, params evmtypes.Params, coinbase common.Address, tracer vm.EVMLogger) *vm.EVM
GetCodeHash(addr common.Address) common.Hash
}
+124 -62
View File
@@ -3,6 +3,15 @@ package app
import (
"encoding/json"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/db"
types2 "github.com/cosmos/cosmos-sdk/store/types"
types3 "github.com/cosmos/cosmos-sdk/store/v2"
"github.com/cosmos/cosmos-sdk/store/v2/multi"
"github.com/cosmos/cosmos-sdk/x/auth/middleware"
"errors"
"io"
"net/http"
"os"
@@ -14,13 +23,10 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmos "github.com/tendermint/tendermint/libs/os"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/server/api"
@@ -64,6 +70,8 @@ import (
"github.com/cosmos/cosmos-sdk/x/gov"
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
govv1beta2 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta2"
"github.com/cosmos/cosmos-sdk/x/mint"
mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
@@ -87,7 +95,6 @@ import (
ibctransferkeeper "github.com/cosmos/ibc-go/modules/apps/transfer/keeper"
ibctransfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types"
ibc "github.com/cosmos/ibc-go/modules/core"
ibcclient "github.com/cosmos/ibc-go/modules/core/02-client"
ibcclientclient "github.com/cosmos/ibc-go/modules/core/02-client/client"
porttypes "github.com/cosmos/ibc-go/modules/core/05-port/types"
ibchost "github.com/cosmos/ibc-go/modules/core/24-host"
@@ -96,7 +103,6 @@ import (
// unnamed import of statik for swagger UI support
_ "github.com/tharsis/ethermint/client/docs/statik"
"github.com/tharsis/ethermint/app/ante"
srvflags "github.com/tharsis/ethermint/server/flags"
ethermint "github.com/tharsis/ethermint/types"
@@ -208,13 +214,15 @@ type EthermintApp struct {
cdc *codec.LegacyAmino
appCodec codec.Codec
interfaceRegistry types.InterfaceRegistry
legacyRouter *middleware.LegacyRouter
msgSvcRouter *middleware.MsgServiceRouter
invCheckPeriod uint
// keys to access the substores
keys map[string]*sdk.KVStoreKey
tkeys map[string]*sdk.TransientStoreKey
memKeys map[string]*sdk.MemoryStoreKey
keys map[string]*types2.KVStoreKey
tkeys map[string]*types2.TransientStoreKey
memKeys map[string]*types2.MemoryStoreKey
// keepers
AccountKeeper authkeeper.AccountKeeper
@@ -261,32 +269,19 @@ type EthermintApp struct {
// NewEthermintApp returns a reference to a new initialized Ethermint application.
func NewEthermintApp(
logger log.Logger,
db dbm.DB,
db db.DBConnection,
traceStore io.Writer,
loadLatest bool,
skipUpgradeHeights map[int64]bool,
homePath string,
invCheckPeriod uint,
encodingConfig simappparams.EncodingConfig,
appOpts servertypes.AppOptions,
baseAppOptions ...func(*baseapp.BaseApp),
baseAppOptions ...baseapp.AppOption,
) *EthermintApp {
appCodec := encodingConfig.Marshaler
appCodec := encodingConfig.Codec
cdc := encodingConfig.Amino
interfaceRegistry := encodingConfig.InterfaceRegistry
// NOTE we use custom transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx
bApp := baseapp.NewBaseApp(
appName,
logger,
db,
encodingConfig.TxConfig.TxDecoder(),
baseAppOptions...,
)
bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetVersion(version.Version)
bApp.SetInterfaceRegistry(interfaceRegistry)
keys := sdk.NewKVStoreKeys(
// SDK keys
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
@@ -308,11 +303,57 @@ func NewEthermintApp(
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey)
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
// initialize stores
setNamespaces := func(config *multi.StoreParams, ver uint64) error {
for _, key := range keys {
typ, err := types3.StoreKeyToType(key)
if err != nil {
return err
}
if err = config.RegisterSubstore(key, typ); err != nil {
return err
}
}
for _, key := range memKeys {
typ, err := types3.StoreKeyToType(key)
if err != nil {
return err
}
if err = config.RegisterSubstore(key, typ); err != nil {
return err
}
}
for _, key := range tkeys {
typ, err := types3.StoreKeyToType(key)
if err != nil {
return err
}
if err = config.RegisterSubstore(key, typ); err != nil {
return err
}
}
return nil
}
baseAppOptions = append(baseAppOptions, baseapp.StoreOption(setNamespaces))
// NOTE we use custom transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx
bApp := baseapp.NewBaseApp(
appName,
logger,
db,
baseAppOptions...,
)
bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetVersion(version.Version)
bApp.SetInterfaceRegistry(interfaceRegistry)
app := &EthermintApp{
BaseApp: bApp,
cdc: cdc,
appCodec: appCodec,
interfaceRegistry: interfaceRegistry,
legacyRouter: middleware.NewLegacyRouter(),
msgSvcRouter: middleware.NewMsgServiceRouter(interfaceRegistry),
invCheckPeriod: invCheckPeriod,
keys: keys,
tkeys: tkeys,
@@ -322,7 +363,7 @@ func NewEthermintApp(
// init params keeper and subspaces
app.ParamsKeeper = initParamsKeeper(appCodec, cdc, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
// set the BaseApp's parameter store
bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramskeeper.ConsensusParamsKeyTable()))
bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramstypes.ConsensusParamsKeyTable()))
// add capability keeper and ScopeToModule for ibc module
app.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey])
@@ -337,6 +378,7 @@ func NewEthermintApp(
// use custom Ethermint account for contracts
app.AccountKeeper = authkeeper.NewAccountKeeper(
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), ethermint.ProtoAccount, maccPerms,
sdk.Bech32MainPrefix,
)
app.BankKeeper = bankkeeper.NewBaseKeeper(
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs(),
@@ -350,7 +392,7 @@ func NewEthermintApp(
)
app.DistrKeeper = distrkeeper.NewKeeper(
appCodec, keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
&stakingKeeper, authtypes.FeeCollectorName, app.ModuleAccountAddrs(),
&stakingKeeper, authtypes.FeeCollectorName,
)
app.SlashingKeeper = slashingkeeper.NewKeeper(
appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName),
@@ -367,7 +409,8 @@ func NewEthermintApp(
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
)
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.BaseApp.MsgServiceRouter())
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec,
app.msgSvcRouter, app.AccountKeeper)
tracer := cast.ToString(appOpts.Get(srvflags.EVMTracer))
@@ -410,16 +453,19 @@ func NewEthermintApp(
)
// register the proposal types
govRouter := govtypes.NewRouter()
govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler).
govRouter := govv1beta1.NewRouter()
govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler).
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)).
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)).
AddRoute(ibchost.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper))
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper))
govConfig := govtypes.DefaultConfig()
/*
Example of setting gov params:
govConfig.MaxMetadataLen = 10000
*/
govKeeper := govkeeper.NewKeeper(
appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
&stakingKeeper, govRouter,
&stakingKeeper, govRouter, app.msgSvcRouter, govConfig,
)
app.GovKeeper = *govKeeper.SetHooks(
@@ -468,7 +514,7 @@ func NewEthermintApp(
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants),
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper),
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil),
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
@@ -535,8 +581,8 @@ func NewEthermintApp(
)
app.mm.RegisterInvariants(&app.CrisisKeeper)
app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino)
app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
app.mm.RegisterRoutes(app.legacyRouter, app.QueryRouter(), encodingConfig.Amino)
app.configurator = module.NewConfigurator(app.appCodec, app.msgSvcRouter, app.GRPCQueryRouter())
app.mm.RegisterServices(app.configurator)
// add test gRPC service for testing gRPC queries in isolation
@@ -551,7 +597,7 @@ func NewEthermintApp(
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper),
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil),
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
@@ -565,37 +611,54 @@ func NewEthermintApp(
app.sm.RegisterStoreDecoders()
// initialize stores
app.MountKVStores(keys)
app.MountTransientStores(tkeys)
app.MountMemoryStores(memKeys)
// initialize BaseApp
app.SetInitChainer(app.InitChainer)
app.SetBeginBlocker(app.BeginBlocker)
// use Ethermint's custom AnteHandler
app.SetAnteHandler(
ante.NewAnteHandler(
app.AccountKeeper, app.BankKeeper, app.EvmKeeper, app.FeeGrantKeeper, app.IBCKeeper.ChannelKeeper,
encodingConfig.TxConfig.SignModeHandler(),
),
)
// TODO: use Ethermint's custom AnteHandler
app.setTxHandler(encodingConfig.TxConfig, cast.ToStringSlice(appOpts.Get(server.FlagIndexEvents)))
app.SetEndBlocker(app.EndBlocker)
if loadLatest {
if err := app.LoadLatestVersion(); err != nil {
tmos.Exit(err.Error())
}
}
app.ScopedIBCKeeper = scopedIBCKeeper
app.ScopedTransferKeeper = scopedTransferKeeper
return app
}
func (app *EthermintApp) setTxHandler(txConfig client.TxConfig, indexEventsStr []string) {
indexEvents := map[string]struct{}{}
for _, e := range indexEventsStr {
indexEvents[e] = struct{}{}
}
// need to sub in custom tx handler
/*
app.SetTxHandler(
ante.NewAnteHandler(
app.AccountKeeper, app.BankKeeper, app.EvmKeeper, app.FeeGrantKeeper, app.IBCKeeper.ChannelKeeper,
encodingConfig.TxConfig.SignModeHandler(),
),
)
*/
txHandler, err := middleware.NewDefaultTxHandler(middleware.TxHandlerOptions{
Debug: app.Trace(),
IndexEvents: indexEvents,
LegacyRouter: app.legacyRouter,
MsgServiceRouter: app.msgSvcRouter,
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
FeegrantKeeper: app.FeeGrantKeeper,
SignModeHandler: txConfig.SignModeHandler(),
SigGasConsumer: middleware.DefaultSigVerificationGasConsumer,
TxDecoder: txConfig.TxDecoder(),
})
if err != nil {
panic(err)
}
app.SetTxHandler(txHandler)
}
// Name returns the name of the App
func (app *EthermintApp) Name() string { return app.BaseApp.Name() }
@@ -621,7 +684,7 @@ func (app *EthermintApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain)
// LoadHeight loads state at a particular height
func (app *EthermintApp) LoadHeight(height int64) error {
return app.LoadVersion(height)
return errors.New("cannot load arbitrary height")
}
// ModuleAccountAddrs returns all the app's module account addresses.
@@ -669,21 +732,21 @@ func (app *EthermintApp) InterfaceRegistry() types.InterfaceRegistry {
// GetKey returns the KVStoreKey for the provided store key.
//
// NOTE: This is solely to be used for testing purposes.
func (app *EthermintApp) GetKey(storeKey string) *sdk.KVStoreKey {
func (app *EthermintApp) GetKey(storeKey string) *types3.KVStoreKey {
return app.keys[storeKey]
}
// GetTKey returns the TransientStoreKey for the provided store key.
//
// NOTE: This is solely to be used for testing purposes.
func (app *EthermintApp) GetTKey(storeKey string) *sdk.TransientStoreKey {
func (app *EthermintApp) GetTKey(storeKey string) *types3.TransientStoreKey {
return app.tkeys[storeKey]
}
// GetMemKey returns the MemStoreKey for the provided mem key.
//
// NOTE: This is solely used for testing purposes.
func (app *EthermintApp) GetMemKey(storeKey string) *sdk.MemoryStoreKey {
func (app *EthermintApp) GetMemKey(storeKey string) *types3.MemoryStoreKey {
return app.memKeys[storeKey]
}
@@ -704,7 +767,6 @@ func (app *EthermintApp) SimulationManager() *module.SimulationManager {
// API server.
func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
clientCtx := apiSvr.ClientCtx
rpc.RegisterRoutes(clientCtx, apiSvr.Router)
evmrest.RegisterTxRoutes(clientCtx, apiSvr.Router)
@@ -754,7 +816,7 @@ func GetMaccPerms() map[string][]string {
// initParamsKeeper init params keeper and its subspaces
func initParamsKeeper(
appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey sdk.StoreKey) paramskeeper.Keeper {
appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey types3.StoreKey) paramskeeper.Keeper {
paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey)
// SDK subspaces
@@ -764,7 +826,7 @@ func initParamsKeeper(
paramsKeeper.Subspace(minttypes.ModuleName)
paramsKeeper.Subspace(distrtypes.ModuleName)
paramsKeeper.Subspace(slashingtypes.ModuleName)
paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govtypes.ParamKeyTable())
paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govv1beta2.ParamKeyTable())
paramsKeeper.Subspace(crisistypes.ModuleName)
paramsKeeper.Subspace(ibctransfertypes.ModuleName)
paramsKeeper.Subspace(ibchost.ModuleName)
+13 -5
View File
@@ -2,23 +2,27 @@ package app
import (
"encoding/json"
"os"
"testing"
"github.com/cosmos/cosmos-sdk/db/memdb"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/simapp"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
"github.com/tharsis/ethermint/encoding"
)
func TestEthermintAppExport(t *testing.T) {
db := dbm.NewMemDB()
app := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
db := memdb.NewDB()
logger, err := log.NewDefaultLogger("plain", "info", false)
if err != nil {
t.Fatal(err)
}
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
genesisState := NewDefaultGenesisState()
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
@@ -35,7 +39,11 @@ func TestEthermintAppExport(t *testing.T) {
app.Commit()
// Making a new app object with the db, so that initchain hasn't been called
app2 := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
logger, err = log.NewDefaultLogger("plain", "info", false)
if err != nil {
t.Fatal(err)
}
app2 := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
_, err = app2.ExportAppStateAndValidators(false, []string{})
require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
}
+4 -5
View File
@@ -2,19 +2,18 @@ package app
import (
"encoding/json"
"io"
"testing"
"github.com/cosmos/cosmos-sdk/db/memdb"
"github.com/cosmos/cosmos-sdk/simapp"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
"github.com/tharsis/ethermint/encoding"
)
func BenchmarkEthermintApp_ExportAppStateAndValidators(b *testing.B) {
db := dbm.NewMemDB()
app := NewEthermintApp(log.NewTMLogger(io.Discard), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
db := memdb.NewDB()
app := NewEthermintApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
genesisState := NewDefaultGenesisState()
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
@@ -36,7 +35,7 @@ func BenchmarkEthermintApp_ExportAppStateAndValidators(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
// Making a new app object with the db, so that initchain hasn't been called
app2 := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(io.Discard)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
app2 := NewEthermintApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
if _, err := app2.ExportAppStateAndValidators(false, []string{}); err != nil {
b.Fatal(err)
}
+1 -1
View File
@@ -19,7 +19,7 @@ import (
// NewDefaultGenesisState generates the default state for the application.
func NewDefaultGenesisState() simapp.GenesisState {
encCfg := encoding.MakeConfig(ModuleBasics)
return ModuleBasics.DefaultGenesis(encCfg.Marshaler)
return ModuleBasics.DefaultGenesis(encCfg.Codec)
}
// ExportAppStateAndValidators exports the state of the application for a genesis
+7 -6
View File
@@ -2,10 +2,12 @@ package app
import (
"encoding/json"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
sdk "github.com/cosmos/cosmos-sdk/types"
"time"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/db/memdb"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/tharsis/ethermint/encoding"
@@ -13,13 +15,12 @@ import (
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmtypes "github.com/tendermint/tendermint/types"
dbm "github.com/tendermint/tm-db"
)
// DefaultConsensusParams defines the default Tendermint consensus params used in
// EthermintApp testing.
var DefaultConsensusParams = &abci.ConsensusParams{
Block: &abci.BlockParams{
var DefaultConsensusParams = &tmproto.ConsensusParams{
Block: &tmproto.BlockParams{
MaxBytes: 200000,
MaxGas: -1, // no limit
},
@@ -37,7 +38,7 @@ var DefaultConsensusParams = &abci.ConsensusParams{
// Setup initializes a new EthermintApp. A Nop logger is set in EthermintApp.
func Setup(isCheckTx bool) *EthermintApp {
db := dbm.NewMemDB()
db := memdb.NewDB()
app := NewEthermintApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 5, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
if !isCheckTx {
// init chain must be called to stop deliverState from being nil
+3 -11
View File
@@ -29,7 +29,6 @@ require (
github.com/rs/zerolog v1.25.0
github.com/spf13/cast v1.4.1
github.com/spf13/cobra v1.2.1
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.8.1
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969
github.com/stretchr/testify v1.7.0
@@ -53,14 +52,10 @@ require (
github.com/99designs/keyring v1.1.6 // indirect
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
github.com/DataDog/zstd v1.4.8 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
github.com/VictoriaMetrics/fastcache v1.5.7 // indirect
github.com/Workiva/go-datastructures v1.0.52 // indirect
github.com/agnivade/levenshtein v1.1.0 // indirect
github.com/aokoli/goutils v1.1.1 // indirect
github.com/armon/go-metrics v0.3.9 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
@@ -81,7 +76,6 @@ require (
github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect
github.com/edsrzf/mmap-go v1.0.0 // indirect
github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 // indirect
github.com/envoyproxy/protoc-gen-validate v0.6.1 // indirect
github.com/felixge/httpsnoop v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
@@ -106,9 +100,7 @@ require (
github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/holiman/uint256 v1.1.1 // indirect
github.com/huandu/xstrings v1.3.2 // indirect
github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/ipfs/go-block-format v0.0.2 // indirect
github.com/ipfs/go-cid v0.0.3 // indirect
@@ -127,13 +119,11 @@ require (
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
github.com/minio/highwayhash v1.0.1 // indirect
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/mr-tron/base58 v1.1.2 // indirect
github.com/mtibben/percent v0.2.1 // indirect
github.com/multiformats/go-base32 v0.0.3 // indirect
github.com/multiformats/go-multibase v0.0.1 // indirect
github.com/mwitkow/go-proto-validators v0.3.2 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pelletier/go-toml v1.9.3 // indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
@@ -144,7 +134,6 @@ require (
github.com/prometheus/common v0.29.0 // indirect
github.com/prometheus/procfs v0.6.0 // indirect
github.com/prometheus/tsdb v0.7.1 // indirect
github.com/pseudomuto/protoc-gen-doc v1.5.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rjeczalik/notify v0.9.1 // indirect
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect
@@ -152,6 +141,7 @@ require (
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.6.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 // indirect
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
@@ -177,3 +167,5 @@ replace google.golang.org/grpc => google.golang.org/grpc v1.33.2
replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
replace github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76
replace github.com/cosmos/cosmos-sdk => github.com/vulcanize/cosmos-sdk v0.45.0-smt-alpha
-44
View File
@@ -73,14 +73,6 @@ github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t
github.com/DataDog/zstd v1.4.8 h1:Rpmta4xZ/MgZnriKNd24iZMhGpP5dvUcs/uqfBapKZY=
github.com/DataDog/zstd v1.4.8/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU=
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
@@ -119,9 +111,6 @@ github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2uc
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
github.com/aokoli/goutils v1.1.1 h1:/hA+Ywo3AxoDZY5ZMnkiEkUvkK4BPp927ax110KCqqg=
github.com/aokoli/goutils v1.1.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
@@ -262,7 +251,6 @@ github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2
github.com/danieljoos/wincred v1.0.2 h1:zf4bhty2iLuwgjgpraD2E9UbvO+fe54XXGJbOwe23fU=
github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U=
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -312,9 +300,6 @@ github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 h1:2vLKys4RBU4
github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25/go.mod h1:hTr8+TLQmkUkgcuh3mcr5fjrT9c64ZzsBCdCEC6UppY=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.3.0-java/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.6.1 h1:4CF52PCseTFt4bE+Yk3dIpdVi7XWuPVMhPtm4FaIJPM=
github.com/envoyproxy/protoc-gen-validate v0.6.1/go.mod h1:txg5va2Qkip90uYoSKH+nkAAmXrb2j3iq4FLwdrCbXQ=
github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM=
github.com/ethereum/go-ethereum v1.10.1/go.mod h1:E5e/zvdfUVr91JZ0AwjyuJM3x+no51zZJRz61orLLSk=
github.com/ethereum/go-ethereum v1.10.3 h1:SEYOYARvbWnoDl1hOSks3ZJQpRiiRJe8ubaQGJQwq0s=
@@ -476,7 +461,6 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/protobuf v3.14.0+incompatible/go.mod h1:lUQ9D1ePzbH2PrIS7ob/bjm9HXyH5WHB0Akwh7URreM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -569,21 +553,14 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iU
github.com/holiman/uint256 v1.1.1 h1:4JywC80b+/hSfljFlEBLHrrh+CIONLDz9NuFl0af4Mw=
github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo=
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
github.com/huin/goupnp v1.0.1-0.20200620063722-49508fba0031/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo=
github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88 h1:bcAj8KroPf552TScjFPIakjH2/tdIrIH8F+cc4v4SRo=
github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo=
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/iancoleman/strcase v0.0.0-20180726023541-3605ed457bf7/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/improbable-eng/grpc-web v0.14.0/go.mod h1:6hRR09jOEG81ADP5wCQju1z71g6OL4eEvELdran/3cs=
github.com/improbable-eng/grpc-web v0.14.1 h1:NrN4PY71A6tAz2sKDvC5JCauENWp0ykG8Oq1H3cpFvw=
github.com/improbable-eng/grpc-web v0.14.1/go.mod h1:zEjGHa8DAlkoOXmswrNvhUGEYQA9UI7DhrGeHR1DMGU=
@@ -698,7 +675,6 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4=
github.com/lyft/protoc-gen-star v0.5.1/go.mod h1:9toiA3cC7z5uVbODF7kEQ91Xn7XNFkVUl+SrEe+ZORU=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
@@ -741,8 +717,6 @@ github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo=
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
@@ -754,8 +728,6 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
@@ -780,9 +752,6 @@ github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpK
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo=
github.com/mwitkow/go-proto-validators v0.3.2 h1:qRlmpTzm2pstMKKzTdvwPCF5QfBNURSlAgN/R+qbKos=
github.com/mwitkow/go-proto-validators v0.3.2/go.mod h1:ej0Qp0qMgHN/KtDyUt+Q1/tA7a5VarXUOUxD+oeD30w=
github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo=
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
@@ -879,7 +848,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992 h1:bzMe+2coZJYHnhGgVlcQKuRy4FSny4ds8dLQjw5P1XE=
@@ -930,10 +898,6 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/pseudomuto/protoc-gen-doc v1.5.0 h1:pHZp0MEiT68jrZV8js8BS7E9ZEnlSLegoQbbtXj5lfo=
github.com/pseudomuto/protoc-gen-doc v1.5.0/go.mod h1:exDTOVwqpp30eV/EDPFLZy3Pwr2sn6hBC1WIYH/UbIg=
github.com/pseudomuto/protokit v0.2.0 h1:hlnBDcy3YEDXH7kc9gV+NLaN0cDzhDvD1s7Y6FZ8RpM=
github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q=
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
@@ -1002,8 +966,6 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
github.com/spf13/afero v1.3.4/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
@@ -1043,7 +1005,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@@ -1166,7 +1127,6 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -1312,7 +1272,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1535,7 +1494,6 @@ google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181107211654-5fc9ac540362/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -1584,8 +1542,6 @@ google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e h1:Im71rbA1N3CbIag/PumYhQcNR8bLNmuOtRIyOnnLsT8=
google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211013025323-ce878158c4d4 h1:NBxB1XxiWpGqkPUiJ9PoBXkHV5A9+GohMOA+EmWoPbU=
google.golang.org/genproto v0.0.0-20211013025323-ce878158c4d4/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o=
+7
View File
@@ -0,0 +1,7 @@
# Testnet
## Setup local ethermint multi node testnet
```shell
$ bash multinode_testnet.sh
```
+201
View File
@@ -0,0 +1,201 @@
# Instructions to Run Full Node
Hardware
---
#### Supported
- **Operating System (OS):** Ubuntu 20.04
- **CPU:** 1 core
- **RAM:** 2GB
- **Storage:** 25GB SSD
#### Recommended
- **Operating System (OS):** Ubuntu 20.04
- **CPU:** 2 core
- **RAM:** 4GB
- **Storage:** 50GB SSD
# A) Setup
## 1) Install Golang (go)
1.1) Remove any existing installation of `go`
```
sudo rm -rf /usr/local/go
```
1.2) Install latest/required Go version (installing `go1.17.2`)
```
curl https://golang.org/dl/go1.17.2.linux-amd64.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.17.2.linux-amd64.tar.gz
```
1.3) Update env variables to include `go`
```
cat <<'EOF' >>$HOME/.profile
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export GO111MODULE=on
export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin
EOF
source $HOME/.profile
```
1.4) Check the version of go installed
```
go version
```
### 2) Install required software packages
```
sudo apt-get install git curl build-essential make jq -y
```
### 3) Install `ethermint`
```
git clone https://github.com/vulcanize/ethermint.git
cd ethermint
git fetch --all
git checkout v0.1.0-dev
make install
```
### 4) Verify your installation
```
ethermintd version --long
```
On running the above command, you should see a similar response like this. Make sure that the *version* and *commit
hash* are accurate
```
name: ethermint
server_name: ethermintd
```
### 5) Initialize Node
**Not required if you have already initialized before**
```
ethermintd init <your-node-moniker> --chain-id ethermint_81337-1
```
On running the above command, node will be initialized with default configuration. (config files will be saved in node's
default home directory (~/.ethermintd/config)
NOTE: Backup node and validator keys . You will need to use these keys at a later point in time.
---
# B) Starting Node
## 1) Download Final Genesis
Use `curl` to download the genesis file
**Replace your **genesis** file with published genesis file**
```shell
curl http://167.172.173.94:26657/genesis | jq .result.genesis > ~/.ethermintd/config/genesis.json
```
Verify sha256 hash of genesis file with the below command
```
jq -S -c -M '' ~/.ethermintd/config/genesis.json | shasum -a 256
```
genesis sha256 hash should be
```
4e5b68b5652a608c44c33e669c84ac179d9c0e301f958b5448f037a53c5cbb4e
```
## 2) Update Peers & Seeds in config.toml
```
peers="5ad2e6c35f2c84ff3ee31d89a95b34d92cb6afb1@157.230.101.237:26656,defc95b08547b6ef254723ad9621967a7e819020@161.35.223.44:26656"
sed -i.bak -e "s/^persistent_peers *=.*/persistent_peers = \"$peers\"/" ~/.ethermintd/config/config.toml
```
## 3) Start the Full Node
#### 3.1) Start node as `systemctl` service
3.1.1) Create the service file
```
sudo tee /etc/systemd/system/ethermintd.service > /dev/null <<EOF
[Unit]
Description=EthermintD Daemon
After=network-online.target
[Service]
User=$USER
ExecStart=$(which ethermintd) start --gql-playground --gql-server
Restart=always
RestartSec=3
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
```
3.1.2) Load service and start
```
sudo systemctl daemon-reload
sudo systemctl enable ethermintd
sudo systemctl start ethermintd
```
3.1.3) Check status of service
```
sudo systemctl status ethermintd
```
`NOTE:`
A helpful command here is `journalctl` that can be used to:
a) check logs
```
journalctl -u ethermintd
```
b) most recent logs
```
journalctl -xeu ethermintd
```
c) logs from previous day
```
journalctl --since "1 day ago" -u ethermintd
```
d) Check logs with follow flag
```
journalctl -f -u ethermintd
```
+231
View File
@@ -0,0 +1,231 @@
# Setting up a Genesis Validator for Vulcanize Ethermint Testnet (ethermint_9000-1)
Hardware
---
#### Supported
- **Operating System (OS):** Ubuntu 20.04
- **CPU:** 1 core
- **RAM:** 2GB
- **Storage:** 25GB SSD
#### Recommended
- **Operating System (OS):** Ubuntu 20.04
- **CPU:** 2 core
- **RAM:** 4GB
- **Storage:** 50GB SSD
# A) Setup
## 1) Install Golang (go)
1.1) Remove any existing installation of `go`
```
sudo rm -rf /usr/local/go
```
1.2) Install latest/required Go version (installing `go1.17.2`)
```
curl -O https://golang.org/dl/go1.17.2.linux-amd64.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.17.2.linux-amd64.tar.gz
```
1.3) Update env variables to include `go`
```
cat <<'EOF' >>$HOME/.profile
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export GO111MODULE=on
export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin
EOF
source $HOME/.profile
```
1.4) Check the version of go installed
```
go version
```
### 2) Install required software packages
```
sudo apt-get update && sudo apt-get install git curl build-essential make jq -y
```
### 3) Install `ethermint`
```
git clone https://github.com/vulcanize/ethermint.git
cd ethermint
git fetch --all
git checkout v0.1.0-dev
make install
```
### 4) Verify your installation
```
ethermintd version --long
```
On running the above command, you should see a similar response like this. Make sure that the *version* and *commit
hash* are accurate
```
name: ethermint
server_name: ethermintd
```
### 5) Initialize Node
**Not required if you have already initialized before**
```
ethermintd init <your-node-moniker> --chain-id ethermint_81337-1
```
On running the above command, node will be initialized with default configuration. (config files will be saved in node's
default home directory (~/.ethermintd/config)
NOTE: Backup node and validator keys. You will need to use these keys at a later point in time.
---
## 6) Create Account keys
if you have participated in previous testnet and have mnemonic phrase, use below command to recover your account
```
ethermintd keys add <key-name> --recover
```
to create new account
```
ethermintd keys add <key-name>
```
NOTE: Save `mnemonic` and related account details (public key). You will need to use the need mnemonic/private key to
recover accounts at a later point in time.
## 7) Add Genesis Account
```
ethermintd add-genesis-account <key-name> 4500000000000000agnt --keyring-backend os
```
## 8) Create Your `gentx`
```
ethermintd gentx <key-name> 4500000000000000agnt \
--pubkey=$(ethermintd tendermint show-validator) \
--chain-id="ethermint_81337-1" \
--moniker="my-moniker" \
--website="https://yourweb.site" \
--details="description of my validator" \
--commission-rate="0.10" \
--commission-max-rate="0.20" \
--commission-max-change-rate="0.01" \
--min-self-delegation="1"
```
Note:
- `<key-name>` and `chain-id` are required. other flags are optional
- Don't change amount value while creating your gentx
- Genesis transaction file will be saved in `~/.ethermintd/config/gentx` folder
## 9) Submit Your gentx
Submit your `gentx` file to the [testnets]() in the format of
`<validator-moniker>-gentx.json`
NOTE: (Do NOT use space in the file name)
To submit the gentx file, follow the below process:
- Fork the [testnets]() repository
- Upload your gentx file in `ethermint_81337-1/config/gentxs` folder
- Submit Pull Request to [testnets]() with name `ADD <your-moniker> gentx`
---
**Execute below instructions only after publishing of final genesis file**
genesis file will be published to [testnets/ethermint_9000-1]()
# B) Starting the validator
TBU
## 3) Start the Node
#### 3.1) Start node as `systemctl` service
3.1.1) Create the service file Note: this step is not required if you did setup before
```
sudo tee /etc/systemd/system/ethermintd.service > /dev/null <<EOF
[Unit]
Description=ethermintd Daemon
After=network-online.target
[Service]
User=$USER
ExecStart=$(which ethermintd) start
Restart=always
RestartSec=3
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
```
3.1.2) Load service and start
```
sudo systemctl daemon-reload
sudo systemctl enable ethermintd
sudo systemctl start ethermintd
```
3.1.3) Check status of service
```
sudo systemctl status ethermintd
```
`NOTE:`
A helpful command here is `journalctl` that can be used to:
a) check logs
```
journalctl -u ethermintd
```
b) most recent logs
```
journalctl -xeu ethermintd
```
c) logs from previous day
```
journalctl --since "1 day ago" -u ethermintd
```
d) Check logs with follow flag
```
journalctl -f -u ethermintd
```
+232
View File
@@ -0,0 +1,232 @@
#/bin/sh
# clean the existed chain
rm -rf ~/.testethermint*
echo "Installing the require tools "
sudo apt-get install git curl build-essential make nohup jq -y
echo "Done Installing the tools"
command_exists() {
type "$1" &>/dev/null
}
if command_exists go; then
echo "Golang is already installed"
else
echo "Installing golang dependencies"
wget https://golang.org/dl/go1.17.2.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.17.2.linux-amd64.tar.gz
echo "Updating the profile"
export GOPATH=$HOME/go
export GOROOT=/usr/local/go
export GOBIN=$GOPATH/bin
export PATH=$PATH:/usr/local/go/bin:$GOBIN
echo "" >>~/.profile
echo 'export GOPATH=$HOME/go' >>~/.profile
echo 'export GOROOT=/usr/local/go' >>~/.profile
echo 'export GOBIN=$GOPATH/bin' >>~/.profile
echo 'export PATH=$PATH:/usr/local/go/bin:$GOBIN' >>~/.profile
source ~/.profile
mkdir -p "$GOBIN"
mkdir -p $GOPATH/src/github.com
go version
fi
# chain env variables
export DAEMON_HOME=~/.testethermint
export CHAINID=ethermint_9000-1
export DENOM=uether
export GH_URL=https://github.com/vulcanize/ethermint.git
export CHAIN_VERSION=dev
export DAEMON=ethermintd
display_usage() {
printf "** Please check the exported values:: **\n Daemon : $DAEMON\n Denom : $DENOM\n ChainID : $CHAINID\n DaemonHome : $DAEMON_HOME\n \n Github URL : $GH_URL\n Chain Version : $CHAIN_VERSION\n"
exit 1
}
if [ -z $DAEMON ] || [ -z $DENOM ] || [ -z $CHAINID ] || [ -z $DAEMON_HOME ] || [ -z $GH_URL ] || [ -z $CHAIN_VERSION ]; then
display_usage
fi
echo "--------- Install $DAEMON ---------"
git clone -b $CHAIN_VERSION --single-branch $GH_URL && cd $(basename $_ .git)
git fetch && git checkout $CHAIN_VERSION
make install
cd $HOME
# check version
$DAEMON version --long
#echo "----------Create test keys-----------"
export DAEMON_HOME_1=$DAEMON_HOME-1
export DAEMON_HOME_2=$DAEMON_HOME-2
export DAEMON_HOME_3=$DAEMON_HOME-3
export DAEMON_HOME_4=$DAEMON_HOME-4
printf "DAEMON_HOME_1=$DAEMON_HOME_1\nDAEMON_HOME_2=$DAEMON_HOME_2\nDAEMON_HOME_3=$DAEMON_HOME_3\nDAEMON_HOME_4=$DAEMON_HOME_4\n"
rm -rf $DAEMON_HOME*
echo "-----Create daemon home directories if not exist------"
mkdir -p "$DAEMON_HOME_1"
mkdir -p "$DAEMON_HOME_2"
mkdir -p "$DAEMON_HOME_3"
mkdir -p "$DAEMON_HOME_4"
echo "--------Start initializing the chain ($CHAINID)---------"
$DAEMON init --chain-id $CHAINID $DAEMON_HOME_1 --home $DAEMON_HOME_1 --keyring-backend test
$DAEMON init --chain-id $CHAINID $DAEMON_HOME_2 --home $DAEMON_HOME_2 --keyring-backend test
$DAEMON init --chain-id $CHAINID $DAEMON_HOME_3 --home $DAEMON_HOME_3 --keyring-backend test
$DAEMON init --chain-id $CHAINID $DAEMON_HOME_4 --home $DAEMON_HOME_4 --keyring-backend test
echo "---------Creating four keys-------------"
$DAEMON keys add validator1 --home $DAEMON_HOME_1 --keyring-backend test
$DAEMON keys add validator2 --home $DAEMON_HOME_2 --keyring-backend test
$DAEMON keys add validator3 --home $DAEMON_HOME_3 --keyring-backend test
$DAEMON keys add validator4 --home $DAEMON_HOME_4 --keyring-backend test
echo "----------Genesis creation---------"
$DAEMON --home $DAEMON_HOME_1 add-genesis-account validator1 1000000000000$DENOM --keyring-backend test
$DAEMON --home $DAEMON_HOME_2 add-genesis-account validator2 1000000000000$DENOM --keyring-backend test
$DAEMON --home $DAEMON_HOME_3 add-genesis-account validator3 1000000000000$DENOM --keyring-backend test
$DAEMON --home $DAEMON_HOME_4 add-genesis-account validator4 1000000000000$DENOM --keyring-backend test
$DAEMON --home $DAEMON_HOME_1 add-genesis-account $($DAEMON keys show validator2 -a --home $DAEMON_HOME_2 --keyring-backend test) 1000000000000$DENOM
$DAEMON --home $DAEMON_HOME_1 add-genesis-account $($DAEMON keys show validator3 -a --home $DAEMON_HOME_3 --keyring-backend test) 1000000000000$DENOM
$DAEMON --home $DAEMON_HOME_1 add-genesis-account $($DAEMON keys show validator4 -a --home $DAEMON_HOME_4 --keyring-backend test) 1000000000000$DENOM
echo "--------Gentx--------"
$DAEMON gentx validator1 90000000000$DENOM --chain-id $CHAINID --keyring-backend test --home $DAEMON_HOME_1
$DAEMON gentx validator2 90000000000$DENOM --chain-id $CHAINID --keyring-backend test --home $DAEMON_HOME_2
$DAEMON gentx validator3 90000000000$DENOM --chain-id $CHAINID --keyring-backend test --home $DAEMON_HOME_3
$DAEMON gentx validator4 90000000000$DENOM --chain-id $CHAINID --keyring-backend test --home $DAEMON_HOME_4
echo "---------Copy all the genesis to $DAEMON_HOME_1----------"
cp $DAEMON_HOME_2/config/gentx/*.json $DAEMON_HOME_1/config/gentx/
cp $DAEMON_HOME_3/config/gentx/*.json $DAEMON_HOME_1/config/gentx/
cp $DAEMON_HOME_4/config/gentx/*.json $DAEMON_HOME_1/config/gentx/
echo "----------collect-gentxs------------"
$DAEMON collect-gentxs --home $DAEMON_HOME_1
echo "---------Updating $DAEMON_HOME_1 genesis.json ------------"
sed -i "s/172800000000000/600000000000/g" $DAEMON_HOME_1/config/genesis.json
sed -i "s/172800s/600s/g" $DAEMON_HOME_1/config/genesis.json
sed -i "s/stake/$DENOM/g" $DAEMON_HOME_1/config/genesis.json
echo "---------Distribute genesis.json of $DAEMON_HOME_1 to remaining nodes-------"
cp $DAEMON_HOME_1/config/genesis.json $DAEMON_HOME_2/config/
cp $DAEMON_HOME_1/config/genesis.json $DAEMON_HOME_3/config/
cp $DAEMON_HOME_1/config/genesis.json $DAEMON_HOME_4/config/
echo "---------Getting public IP address-----------"
IP="127.0.0.1"
echo "Public IP address: ${IP}"
echo "----------Update node-id of $DAEMON_HOME_1 in remaining nodes---------"
nodeID=$("${DAEMON}" tendermint show-node-id --home $DAEMON_HOME_1)
echo $nodeID
PERSISTENT_PEERS="$nodeID@$IP:16656"
echo "PERSISTENT_PEERS : $PERSISTENT_PEERS"
echo "----------Updating $DAEMON_HOME_1 chain config-----------"
sed -i 's#tcp://127.0.0.1:26657#tcp://0.0.0.0:16657#g' $DAEMON_HOME_1/config/config.toml
sed -i 's#tcp://0.0.0.0:26656#tcp://0.0.0.0:16656#g' $DAEMON_HOME_1/config/config.toml
sed -i '/persistent_peers =/c\persistent_peers = "'""'"' $DAEMON_HOME_1/config/config.toml
sed -i '/max_num_inbound_peers =/c\max_num_inbound_peers = 140' $DAEMON_HOME_1/config/config.toml
sed -i '/max_num_outbound_peers =/c\max_num_outbound_peers = 110' $DAEMON_HOME_1/config/config.toml
sed -i '/pprof_laddr =/c\# pprof_laddr = "localhost:6060"' $DAEMON_HOME_1/config/config.toml
sed -i '/allow_duplicate_ip =/c\allow_duplicate_ip = true' $DAEMON_HOME_1/config/config.toml
sed -i 's#0.0.0.0:9090#0.0.0.0:1090#g' $DAEMON_HOME_1/config/app.toml
sed -i 's#0.0.0.0:9091#0.0.0.0:1091#g' $DAEMON_HOME_1/config/app.toml
sed -i 's#0.0.0.0:8545#0.0.0.0:1545#g' $DAEMON_HOME_1/config/app.toml
sed -i 's#0.0.0.0:8546#0.0.0.0:1546#g' $DAEMON_HOME_1/config/app.toml
echo "----------Updating $DAEMON_HOME_2 chain config-----------"
sed -i 's#tcp://127.0.0.1:26657#tcp://0.0.0.0:26657#g' $DAEMON_HOME_2/config/config.toml
sed -i 's#tcp://0.0.0.0:26656#tcp://0.0.0.0:26656#g' $DAEMON_HOME_2/config/config.toml
sed -i '/persistent_peers =/c\persistent_peers = "'"$PERSISTENT_PEERS"'"' $DAEMON_HOME_2/config/config.toml
sed -i '/max_num_inbound_peers =/c\max_num_inbound_peers = 140' $DAEMON_HOME_2/config/config.toml
sed -i '/max_num_outbound_peers =/c\max_num_outbound_peers = 110' $DAEMON_HOME_2/config/config.toml
sed -i '/pprof_laddr =/c\# pprof_laddr = "localhost:6060"' $DAEMON_HOME_2/config/config.toml
sed -i '/allow_duplicate_ip =/c\allow_duplicate_ip = true' $DAEMON_HOME_2/config/config.toml
sed -i 's#0.0.0.0:9090#0.0.0.0:2090#g' $DAEMON_HOME_2/config/app.toml
sed -i 's#0.0.0.0:9091#0.0.0.0:2091#g' $DAEMON_HOME_2/config/app.toml
sed -i 's#0.0.0.0:8545#0.0.0.0:2545#g' $DAEMON_HOME_2/config/app.toml
sed -i 's#0.0.0.0:8546#0.0.0.0:2546#g' $DAEMON_HOME_2/config/app.toml
echo "----------Updating $DAEMON_HOME_3 chain config------------"
sed -i 's#tcp://127.0.0.1:26657#tcp://0.0.0.0:36657#g' $DAEMON_HOME_3/config/config.toml
sed -i 's#tcp://0.0.0.0:26656#tcp://0.0.0.0:36656#g' $DAEMON_HOME_3/config/config.toml
sed -i '/persistent_peers =/c\persistent_peers = "'"$PERSISTENT_PEERS"'"' $DAEMON_HOME_3/config/config.toml
sed -i '/max_num_inbound_peers =/c\max_num_inbound_peers = 140' $DAEMON_HOME_3/config/config.toml
sed -i '/max_num_outbound_peers =/c\max_num_outbound_peers = 110' $DAEMON_HOME_3/config/config.toml
sed -i '/pprof_laddr =/c\# pprof_laddr = "localhost:6060"' $DAEMON_HOME_3/config/config.toml
sed -i '/allow_duplicate_ip =/c\allow_duplicate_ip = true' $DAEMON_HOME_3/config/config.toml
sed -i 's#0.0.0.0:9090#0.0.0.0:3090#g' $DAEMON_HOME_3/config/app.toml
sed -i 's#0.0.0.0:9091#0.0.0.0:3091#g' $DAEMON_HOME_3/config/app.toml
sed -i 's#0.0.0.0:8545#0.0.0.0:3545#g' $DAEMON_HOME_3/config/app.toml
sed -i 's#0.0.0.0:8546#0.0.0.0:3546#g' $DAEMON_HOME_3/config/app.toml
echo "----------Updating $DAEMON_HOME_4 chain config------------"
sed -i 's#tcp://127.0.0.1:26657#tcp://0.0.0.0:46657#g' $DAEMON_HOME_4/config/config.toml
sed -i 's#tcp://0.0.0.0:26656#tcp://0.0.0.0:46656#g' $DAEMON_HOME_4/config/config.toml
sed -i '/persistent_peers =/c\persistent_peers = "'"$PERSISTENT_PEERS"'"' $DAEMON_HOME_4/config/config.toml
sed -i '/max_num_inbound_peers =/c\max_num_inbound_peers = 140' $DAEMON_HOME_4/config/config.toml
sed -i '/max_num_outbound_peers =/c\max_num_outbound_peers = 110' $DAEMON_HOME_4/config/config.toml
sed -i '/pprof_laddr =/c\# pprof_laddr = "localhost:6060"' $DAEMON_HOME_4/config/config.toml
sed -i '/allow_duplicate_ip =/c\allow_duplicate_ip = true' $DAEMON_HOME_4/config/config.toml
sed -i 's#0.0.0.0:9090#0.0.0.0:4090#g' $DAEMON_HOME_4/config/app.toml
sed -i 's#0.0.0.0:9091#0.0.0.0:4091#g' $DAEMON_HOME_4/config/app.toml
sed -i 's#0.0.0.0:8545#0.0.0.0:4545#g' $DAEMON_HOME_4/config/app.toml
sed -i 's#0.0.0.0:8546#0.0.0.0:4546#g' $DAEMON_HOME_4/config/app.toml
echo "starting the chains"
nohup $(which $DAEMON) start --gql-playground --gql-server --home $DAEMON_HOME_1 >$DAEMON_HOME_1.log &
sleep 5s
echo "Checking $DAEMON_HOME_1 chain status"
$DAEMON status --node tcp://localhost:16657
nohup $(which $DAEMON) start --gql-playground --gql-server --home $DAEMON_HOME_2 >$DAEMON_HOME_2.log &
sleep 5s
echo "Checking $DAEMON_HOME_2 chain status"
$DAEMON status --node tcp://localhost:26657
nohup $(which $DAEMON) start --gql-playground --gql-server --home $DAEMON_HOME_3 >$DAEMON_HOME_3.log &
sleep 5s
echo "Checking $DAEMON_HOME_3 chain status"
$DAEMON status --node tcp://localhost:36657
nohup $(which $DAEMON) start --gql-playground --gql-server --home $DAEMON_HOME_4 >$DAEMON_HOME_4.log &
sleep 5s
echo "Checking $DAEMON_HOME_4 chain status"
$DAEMON status --node tcp://localhost:46657
+56
View File
@@ -0,0 +1,56 @@
### Create Validator Post Genesis
1. Run Full Node
2. Create Account and Get test tokens
3. Create Validator
### 1.Run Full Node
- Check "[Run Full Node](full-node.md)" section to Run a Full Node
### 2. Create Account & Get test tokens
```
ethermintd keys add <key-name> --keyring-backend test
```
NOTE: Save `mnemonic` and related account details (public key). You will need to use the need mnemonic/private key to
recover accounts at a later point in time.
##### Get Test tokens from faucet
- Open this link : http://167.172.173.94:1314/ and paste your account
- 1 gnt = 10^18 agnt
- Each Transaction you will get 500gnt
- Total Tokens 5000gnt for account
### 3.Create Validator
- ##### Check full node sync status
`ethermintd status 2>&1 | jq -r ".SyncInfo"`
`catching_up: false` means node is completely synced
- ##### Create validator
`Note:` Only execute below transaction after complete sync of your full node
Please replace `key_name` with your key name and `moniker` also
```
ethermintd tx staking create-validator \
--amount=4500000000000000000000agnt \
--pubkey=$(ethermintd tendermint show-validator) \
--moniker="my-moniker" \
--website="https://myweb.site" \
--details="description of your validator" \
--chain-id="ethermint_81337-1" \
--commission-rate="0.10" \
--commission-max-rate="0.20" \
--commission-max-change-rate="0.01" \
--min-self-delegation="1" \
--gas="auto" \
--gas-adjustment="1.2" \
--gas-prices="0.025agnt" \
--from=<key_name>
```
+58
View File
@@ -0,0 +1,58 @@
package ante
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
// HandlerOptions are the options required for constructing a default SDK AnteHandler.
type HandlerOptions struct {
AccountKeeper AccountKeeper
BankKeeper types.BankKeeper
FeegrantKeeper FeegrantKeeper
SignModeHandler authsigning.SignModeHandler
SigGasConsumer func(meter sdk.GasMeter, sig signing.SignatureV2, params types.Params) error
}
// NewAnteHandler returns an AnteHandler that checks and increments sequence
// numbers, checks signatures & account numbers, and deducts fees from the first
// signer.
func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
if options.AccountKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for ante builder")
}
if options.BankKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for ante builder")
}
if options.SignModeHandler == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder")
}
var sigGasConsumer = options.SigGasConsumer
if sigGasConsumer == nil {
sigGasConsumer = DefaultSigVerificationGasConsumer
}
anteDecorators := []sdk.AnteDecorator{
NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
NewRejectExtensionOptionsDecorator(),
NewMempoolFeeDecorator(),
NewValidateBasicDecorator(),
NewTxTimeoutHeightDecorator(),
NewValidateMemoDecorator(options.AccountKeeper),
NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper),
NewSetPubKeyDecorator(options.AccountKeeper), // SetPubKeyDecorator must be called before all signature verification decorators
NewValidateSigCountDecorator(options.AccountKeeper),
NewSigGasConsumeDecorator(options.AccountKeeper, sigGasConsumer),
NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
NewIncrementSequenceDecorator(options.AccountKeeper),
}
return sdk.ChainAnteDecorators(anteDecorators...), nil
}
File diff suppressed because it is too large Load Diff
+206
View File
@@ -0,0 +1,206 @@
package ante
import (
"github.com/cosmos/cosmos-sdk/codec/legacy"
"github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
)
// ValidateBasicDecorator will call tx.ValidateBasic and return any non-nil error.
// If ValidateBasic passes, decorator calls next AnteHandler in chain. Note,
// ValidateBasicDecorator decorator will not get executed on ReCheckTx since it
// is not dependent on application state.
type ValidateBasicDecorator struct{}
func NewValidateBasicDecorator() ValidateBasicDecorator {
return ValidateBasicDecorator{}
}
func (vbd ValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
// no need to validate basic on recheck tx, call next antehandler
if ctx.IsReCheckTx() {
return next(ctx, tx, simulate)
}
if err := tx.ValidateBasic(); err != nil {
return ctx, err
}
return next(ctx, tx, simulate)
}
// ValidateMemoDecorator will validate memo given the parameters passed in
// If memo is too large decorator returns with error, otherwise call next AnteHandler
// CONTRACT: Tx must implement TxWithMemo interface
type ValidateMemoDecorator struct {
ak AccountKeeper
}
func NewValidateMemoDecorator(ak AccountKeeper) ValidateMemoDecorator {
return ValidateMemoDecorator{
ak: ak,
}
}
func (vmd ValidateMemoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
memoTx, ok := tx.(sdk.TxWithMemo)
if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
}
params := vmd.ak.GetParams(ctx)
memoLength := len(memoTx.GetMemo())
if uint64(memoLength) > params.MaxMemoCharacters {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrMemoTooLarge,
"maximum number of characters is %d but received %d characters",
params.MaxMemoCharacters, memoLength,
)
}
return next(ctx, tx, simulate)
}
// ConsumeTxSizeGasDecorator will take in parameters and consume gas proportional
// to the size of tx before calling next AnteHandler. Note, the gas costs will be
// slightly over estimated due to the fact that any given signing account may need
// to be retrieved from state.
//
// CONTRACT: If simulate=true, then signatures must either be completely filled
// in or empty.
// CONTRACT: To use this decorator, signatures of transaction must be represented
// as legacytx.StdSignature otherwise simulate mode will incorrectly estimate gas cost.
type ConsumeTxSizeGasDecorator struct {
ak AccountKeeper
}
func NewConsumeGasForTxSizeDecorator(ak AccountKeeper) ConsumeTxSizeGasDecorator {
return ConsumeTxSizeGasDecorator{
ak: ak,
}
}
func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
sigTx, ok := tx.(authsigning.SigVerifiableTx)
if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid tx type")
}
params := cgts.ak.GetParams(ctx)
ctx.GasMeter().ConsumeGas(params.TxSizeCostPerByte*sdk.Gas(len(ctx.TxBytes())), "txSize")
// simulate gas cost for signatures in simulate mode
if simulate {
// in simulate mode, each element should be a nil signature
sigs, err := sigTx.GetSignaturesV2()
if err != nil {
return ctx, err
}
n := len(sigs)
for i, signer := range sigTx.GetSigners() {
// if signature is already filled in, no need to simulate gas cost
if i < n && !isIncompleteSignature(sigs[i].Data) {
continue
}
var pubkey cryptotypes.PubKey
acc := cgts.ak.GetAccount(ctx, signer)
// use placeholder simSecp256k1Pubkey if sig is nil
if acc == nil || acc.GetPubKey() == nil {
pubkey = simSecp256k1Pubkey
} else {
pubkey = acc.GetPubKey()
}
// use stdsignature to mock the size of a full signature
simSig := legacytx.StdSignature{ //nolint:staticcheck // this will be removed when proto is ready
Signature: simSecp256k1Sig[:],
PubKey: pubkey,
}
sigBz := legacy.Cdc.MustMarshal(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.LegacyAminoPubKey); ok {
cost *= params.TxSigLimit
}
ctx.GasMeter().ConsumeGas(params.TxSizeCostPerByte*cost, "txSize")
}
}
return next(ctx, tx, simulate)
}
// isIncompleteSignature tests whether SignatureData is fully filled in for simulation purposes
func isIncompleteSignature(data signing.SignatureData) bool {
if data == nil {
return true
}
switch data := data.(type) {
case *signing.SingleSignatureData:
return len(data.Signature) == 0
case *signing.MultiSignatureData:
if len(data.Signatures) == 0 {
return true
}
for _, s := range data.Signatures {
if isIncompleteSignature(s) {
return true
}
}
}
return false
}
type (
// TxTimeoutHeightDecorator defines an AnteHandler decorator that checks for a
// tx height timeout.
TxTimeoutHeightDecorator struct{}
// TxWithTimeoutHeight defines the interface a tx must implement in order for
// TxHeightTimeoutDecorator to process the tx.
TxWithTimeoutHeight interface {
sdk.Tx
GetTimeoutHeight() uint64
}
)
// TxTimeoutHeightDecorator defines an AnteHandler decorator that checks for a
// tx height timeout.
func NewTxTimeoutHeightDecorator() TxTimeoutHeightDecorator {
return TxTimeoutHeightDecorator{}
}
// AnteHandle implements an AnteHandler decorator for the TxHeightTimeoutDecorator
// type where the current block height is checked against the tx's height timeout.
// If a height timeout is provided (non-zero) and is less than the current block
// height, then an error is returned.
func (txh TxTimeoutHeightDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
timeoutTx, ok := tx.(TxWithTimeoutHeight)
if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "expected tx to implement TxWithTimeoutHeight")
}
timeoutHeight := timeoutTx.GetTimeoutHeight()
if timeoutHeight > 0 && uint64(ctx.BlockHeight()) > timeoutHeight {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrTxTimeoutHeight, "block height: %d, timeout height: %d", ctx.BlockHeight(), timeoutHeight,
)
}
return next(ctx, tx, simulate)
}
+224
View File
@@ -0,0 +1,224 @@
package ante_test
import (
"strings"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
)
func (suite *AnteTestSuite) TestValidateBasic() {
suite.SetupTest(true) // setup
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
// keys and addresses
priv1, _, addr1 := testdata.KeyTestPubAddr()
// msg and signatures
msg := testdata.NewTestMsg(addr1)
feeAmount := testdata.NewTestFeeAmount()
gasLimit := testdata.NewTestGasLimit()
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
suite.txBuilder.SetFeeAmount(feeAmount)
suite.txBuilder.SetGasLimit(gasLimit)
privs, accNums, accSeqs := []cryptotypes.PrivKey{}, []uint64{}, []uint64{}
invalidTx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
vbd := ante.NewValidateBasicDecorator()
antehandler := sdk.ChainAnteDecorators(vbd)
_, err = antehandler(suite.ctx, invalidTx, false)
suite.Require().NotNil(err, "Did not error on invalid tx")
privs, accNums, accSeqs = []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
validTx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
_, err = antehandler(suite.ctx, validTx, false)
suite.Require().Nil(err, "ValidateBasicDecorator returned error on valid tx. err: %v", err)
// test decorator skips on recheck
suite.ctx = suite.ctx.WithIsReCheckTx(true)
// decorator should skip processing invalidTx on recheck and thus return nil-error
_, err = antehandler(suite.ctx, invalidTx, false)
suite.Require().Nil(err, "ValidateBasicDecorator ran on ReCheck")
}
func (suite *AnteTestSuite) TestValidateMemo() {
suite.SetupTest(true) // setup
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
// keys and addresses
priv1, _, addr1 := testdata.KeyTestPubAddr()
// msg and signatures
msg := testdata.NewTestMsg(addr1)
feeAmount := testdata.NewTestFeeAmount()
gasLimit := testdata.NewTestGasLimit()
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
suite.txBuilder.SetFeeAmount(feeAmount)
suite.txBuilder.SetGasLimit(gasLimit)
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
suite.txBuilder.SetMemo(strings.Repeat("01234567890", 500))
invalidTx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
// require that long memos get rejected
vmd := ante.NewValidateMemoDecorator(suite.app.AccountKeeper)
antehandler := sdk.ChainAnteDecorators(vmd)
_, err = antehandler(suite.ctx, invalidTx, false)
suite.Require().NotNil(err, "Did not error on tx with high memo")
suite.txBuilder.SetMemo(strings.Repeat("01234567890", 10))
validTx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
// require small memos pass ValidateMemo Decorator
_, err = antehandler(suite.ctx, validTx, false)
suite.Require().Nil(err, "ValidateBasicDecorator returned error on valid tx. err: %v", err)
}
func (suite *AnteTestSuite) TestConsumeGasForTxSize() {
suite.SetupTest(true) // setup
// keys and addresses
priv1, _, addr1 := testdata.KeyTestPubAddr()
// msg and signatures
msg := testdata.NewTestMsg(addr1)
feeAmount := testdata.NewTestFeeAmount()
gasLimit := testdata.NewTestGasLimit()
cgtsd := ante.NewConsumeGasForTxSizeDecorator(suite.app.AccountKeeper)
antehandler := sdk.ChainAnteDecorators(cgtsd)
testCases := []struct {
name string
sigV2 signing.SignatureV2
}{
{"SingleSignatureData", signing.SignatureV2{PubKey: priv1.PubKey()}},
{"MultiSignatureData", signing.SignatureV2{PubKey: priv1.PubKey(), Data: multisig.NewMultisig(2)}},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
suite.txBuilder.SetFeeAmount(feeAmount)
suite.txBuilder.SetGasLimit(gasLimit)
suite.txBuilder.SetMemo(strings.Repeat("01234567890", 10))
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
txBytes, err := suite.clientCtx.TxConfig.TxJSONEncoder()(tx)
suite.Require().Nil(err, "Cannot marshal tx: %v", err)
params := suite.app.AccountKeeper.GetParams(suite.ctx)
expectedGas := sdk.Gas(len(txBytes)) * params.TxSizeCostPerByte
// Set suite.ctx with TxBytes manually
suite.ctx = suite.ctx.WithTxBytes(txBytes)
// track how much gas is necessary to retrieve parameters
beforeGas := suite.ctx.GasMeter().GasConsumed()
suite.app.AccountKeeper.GetParams(suite.ctx)
afterGas := suite.ctx.GasMeter().GasConsumed()
expectedGas += afterGas - beforeGas
beforeGas = suite.ctx.GasMeter().GasConsumed()
suite.ctx, err = antehandler(suite.ctx, tx, false)
suite.Require().Nil(err, "ConsumeTxSizeGasDecorator returned error: %v", err)
// require that decorator consumes expected amount of gas
consumedGas := suite.ctx.GasMeter().GasConsumed() - beforeGas
suite.Require().Equal(expectedGas, consumedGas, "Decorator did not consume the correct amount of gas")
// simulation must not underestimate gas of this decorator even with nil signatures
txBuilder, err := suite.clientCtx.TxConfig.WrapTxBuilder(tx)
suite.Require().NoError(err)
suite.Require().NoError(txBuilder.SetSignatures(tc.sigV2))
tx = txBuilder.GetTx()
simTxBytes, err := suite.clientCtx.TxConfig.TxJSONEncoder()(tx)
suite.Require().Nil(err, "Cannot marshal tx: %v", err)
// require that simulated tx is smaller than tx with signatures
suite.Require().True(len(simTxBytes) < len(txBytes), "simulated tx still has signatures")
// Set suite.ctx with smaller simulated TxBytes manually
suite.ctx = suite.ctx.WithTxBytes(simTxBytes)
beforeSimGas := suite.ctx.GasMeter().GasConsumed()
// run antehandler with simulate=true
suite.ctx, err = antehandler(suite.ctx, tx, true)
consumedSimGas := suite.ctx.GasMeter().GasConsumed() - beforeSimGas
// require that antehandler passes and does not underestimate decorator cost
suite.Require().Nil(err, "ConsumeTxSizeGasDecorator returned error: %v", err)
suite.Require().True(consumedSimGas >= expectedGas, "Simulate mode underestimates gas on AnteDecorator. Simulated cost: %d, expected cost: %d", consumedSimGas, expectedGas)
})
}
}
func (suite *AnteTestSuite) TestTxHeightTimeoutDecorator() {
suite.SetupTest(true)
antehandler := sdk.ChainAnteDecorators(ante.NewTxTimeoutHeightDecorator())
// keys and addresses
priv1, _, addr1 := testdata.KeyTestPubAddr()
// msg and signatures
msg := testdata.NewTestMsg(addr1)
feeAmount := testdata.NewTestFeeAmount()
gasLimit := testdata.NewTestGasLimit()
testCases := []struct {
name string
timeout uint64
height int64
expectErr bool
}{
{"default value", 0, 10, false},
{"no timeout (greater height)", 15, 10, false},
{"no timeout (same height)", 10, 10, false},
{"timeout (smaller height)", 9, 10, true},
}
for _, tc := range testCases {
tc := tc
suite.Run(tc.name, func() {
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
suite.txBuilder.SetFeeAmount(feeAmount)
suite.txBuilder.SetGasLimit(gasLimit)
suite.txBuilder.SetMemo(strings.Repeat("01234567890", 10))
suite.txBuilder.SetTimeoutHeight(tc.timeout)
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
ctx := suite.ctx.WithBlockHeight(tc.height)
_, err = antehandler(ctx, tx, true)
suite.Require().Equal(tc.expectErr, err != nil, err)
})
}
}
+20
View File
@@ -0,0 +1,20 @@
package ante
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
// AccountKeeper defines the contract needed for AccountKeeper related APIs.
// Interface provides support to use non-sdk AccountKeeper for AnteHandler's decorators.
type AccountKeeper interface {
GetParams(ctx sdk.Context) (params types.Params)
GetAccount(ctx sdk.Context, addr sdk.AccAddress) types.AccountI
SetAccount(ctx sdk.Context, acc types.AccountI)
GetModuleAddress(moduleName string) sdk.AccAddress
}
// FeegrantKeeper defines the expected feegrant keeper.
type FeegrantKeeper interface {
UseGrantedFees(ctx sdk.Context, granter, grantee sdk.AccAddress, fee sdk.Coins, msgs []sdk.Msg) error
}
+36
View File
@@ -0,0 +1,36 @@
package ante
import (
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
type HasExtensionOptionsTx interface {
GetExtensionOptions() []*codectypes.Any
GetNonCriticalExtensionOptions() []*codectypes.Any
}
// RejectExtensionOptionsDecorator is an AnteDecorator that rejects all extension
// options which can optionally be included in protobuf transactions. Users that
// need extension options should create a custom AnteHandler chain that handles
// needed extension options properly and rejects unknown ones.
type RejectExtensionOptionsDecorator struct{}
// NewRejectExtensionOptionsDecorator creates a new RejectExtensionOptionsDecorator
func NewRejectExtensionOptionsDecorator() RejectExtensionOptionsDecorator {
return RejectExtensionOptionsDecorator{}
}
var _ types.AnteDecorator = RejectExtensionOptionsDecorator{}
// AnteHandle implements the AnteDecorator.AnteHandle method
func (r RejectExtensionOptionsDecorator) AnteHandle(ctx types.Context, tx types.Tx, simulate bool, next types.AnteHandler) (newCtx types.Context, err error) {
if hasExtOptsTx, ok := tx.(HasExtensionOptionsTx); ok {
if len(hasExtOptsTx.GetExtensionOptions()) != 0 {
return ctx, sdkerrors.ErrUnknownExtensionOptions
}
}
return next(ctx, tx, simulate)
}
+36
View File
@@ -0,0 +1,36 @@
package ante_test
import (
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/cosmos/cosmos-sdk/x/auth/tx"
)
func (suite *AnteTestSuite) TestRejectExtensionOptionsDecorator() {
suite.SetupTest(true) // setup
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
reod := ante.NewRejectExtensionOptionsDecorator()
antehandler := sdk.ChainAnteDecorators(reod)
// no extension options should not trigger an error
theTx := suite.txBuilder.GetTx()
_, err := antehandler(suite.ctx, theTx, false)
suite.Require().NoError(err)
extOptsTxBldr, ok := suite.txBuilder.(tx.ExtensionOptionsTxBuilder)
if !ok {
// if we can't set extension options, this decorator doesn't apply and we're done
return
}
// setting any extension option should cause an error
any, err := types.NewAnyWithValue(testdata.NewTestMsg())
suite.Require().NoError(err)
extOptsTxBldr.SetExtensionOptions(any)
theTx = suite.txBuilder.GetTx()
_, err = antehandler(suite.ctx, theTx, false)
suite.Require().EqualError(err, "unknown extension options")
}
+141
View File
@@ -0,0 +1,141 @@
package ante
import (
"fmt"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
// MempoolFeeDecorator will check if the transaction's fee is at least as large
// as the local validator's minimum gasFee (defined in validator config).
// If fee is too low, decorator returns error and tx is rejected from mempool.
// Note this only applies when ctx.CheckTx = true
// If fee is high enough or not CheckTx, then call next AnteHandler
// CONTRACT: Tx must implement FeeTx to use MempoolFeeDecorator
type MempoolFeeDecorator struct{}
func NewMempoolFeeDecorator() MempoolFeeDecorator {
return MempoolFeeDecorator{}
}
func (mfd MempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
feeTx, ok := tx.(sdk.FeeTx)
if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
}
feeCoins := feeTx.GetFee()
gas := feeTx.GetGas()
// Ensure that the provided fees meet a minimum threshold for the validator,
// if this is a CheckTx. This is only for local mempool purposes, and thus
// is only ran on check tx.
if ctx.IsCheckTx() && !simulate {
minGasPrices := ctx.MinGasPrices()
if !minGasPrices.IsZero() {
requiredFees := make(sdk.Coins, len(minGasPrices))
// Determine the required fees by multiplying each required minimum gas
// price by the gas limit, where fee = ceil(minGasPrice * gasLimit).
glDec := sdk.NewDec(int64(gas))
for i, gp := range minGasPrices {
fee := gp.Amount.Mul(glDec)
requiredFees[i] = sdk.NewCoin(gp.Denom, fee.Ceil().RoundInt())
}
if !feeCoins.IsAnyGTE(requiredFees) {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees)
}
}
}
return next(ctx, tx, simulate)
}
// DeductFeeDecorator deducts fees from the first signer of the tx
// If the first signer does not have the funds to pay for the fees, return with InsufficientFunds error
// Call next AnteHandler if fees successfully deducted
// CONTRACT: Tx must implement FeeTx interface to use DeductFeeDecorator
type DeductFeeDecorator struct {
ak AccountKeeper
bankKeeper evmtypes.BankKeeper
feegrantKeeper FeegrantKeeper
}
func NewDeductFeeDecorator(ak AccountKeeper, bk evmtypes.BankKeeper, fk FeegrantKeeper) DeductFeeDecorator {
return DeductFeeDecorator{
ak: ak,
bankKeeper: bk,
feegrantKeeper: fk,
}
}
func (dfd DeductFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
feeTx, ok := tx.(sdk.FeeTx)
if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
}
if addr := dfd.ak.GetModuleAddress(types.FeeCollectorName); addr == nil {
panic(fmt.Sprintf("%s module account has not been set", types.FeeCollectorName))
}
fee := feeTx.GetFee()
feePayer := feeTx.FeePayer()
feeGranter := feeTx.FeeGranter()
deductFeesFrom := feePayer
// if feegranter set deduct fee from feegranter account.
// this works with only when feegrant enabled.
if feeGranter != nil {
if dfd.feegrantKeeper == nil {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "fee grants are not enabled")
} else if !feeGranter.Equals(feePayer) {
err := dfd.feegrantKeeper.UseGrantedFees(ctx, feeGranter, feePayer, fee, tx.GetMsgs())
if err != nil {
return ctx, sdkerrors.Wrapf(err, "%s not allowed to pay fees from %s", feeGranter, feePayer)
}
}
deductFeesFrom = feeGranter
}
deductFeesFromAcc := dfd.ak.GetAccount(ctx, deductFeesFrom)
if deductFeesFromAcc == nil {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "fee payer address: %s does not exist", deductFeesFrom)
}
// deduct the fees
if !feeTx.GetFee().IsZero() {
err = DeductFees(dfd.bankKeeper, ctx, deductFeesFromAcc, feeTx.GetFee())
if err != nil {
return ctx, err
}
}
events := sdk.Events{sdk.NewEvent(sdk.EventTypeTx,
sdk.NewAttribute(sdk.AttributeKeyFee, feeTx.GetFee().String()),
)}
ctx.EventManager().EmitEvents(events)
return next(ctx, tx, simulate)
}
// DeductFees deducts fees from the given account.
func DeductFees(bankKeeper evmtypes.BankKeeper, ctx sdk.Context, acc types.AccountI, fees sdk.Coins) error {
if !fees.IsValid() {
return sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "invalid fee amount: %s", fees)
}
err := bankKeeper.SendCoinsFromAccountToModule(ctx, acc.GetAddress(), types.FeeCollectorName, fees)
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error())
}
return nil
}
+104
View File
@@ -0,0 +1,104 @@
package ante_test
import (
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
)
func (suite *AnteTestSuite) TestEnsureMempoolFees() {
suite.SetupTest(true) // setup
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
mfd := ante.NewMempoolFeeDecorator()
antehandler := sdk.ChainAnteDecorators(mfd)
// keys and addresses
priv1, _, addr1 := testdata.KeyTestPubAddr()
// msg and signatures
msg := testdata.NewTestMsg(addr1)
feeAmount := testdata.NewTestFeeAmount()
gasLimit := testdata.NewTestGasLimit()
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
suite.txBuilder.SetFeeAmount(feeAmount)
suite.txBuilder.SetGasLimit(gasLimit)
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
// Set high gas price so standard test fee fails
atomPrice := sdk.NewDecCoinFromDec("atom", sdk.NewDec(200).Quo(sdk.NewDec(100000)))
highGasPrice := []sdk.DecCoin{atomPrice}
suite.ctx = suite.ctx.WithMinGasPrices(highGasPrice)
// Set IsCheckTx to true
suite.ctx = suite.ctx.WithIsCheckTx(true)
// antehandler errors with insufficient fees
_, err = antehandler(suite.ctx, tx, false)
suite.Require().NotNil(err, "Decorator should have errored on too low fee for local gasPrice")
// Set IsCheckTx to false
suite.ctx = suite.ctx.WithIsCheckTx(false)
// antehandler should not error since we do not check minGasPrice in DeliverTx
_, err = antehandler(suite.ctx, tx, false)
suite.Require().Nil(err, "MempoolFeeDecorator returned error in DeliverTx")
// Set IsCheckTx back to true for testing sufficient mempool fee
suite.ctx = suite.ctx.WithIsCheckTx(true)
atomPrice = sdk.NewDecCoinFromDec("atom", sdk.NewDec(0).Quo(sdk.NewDec(100000)))
lowGasPrice := []sdk.DecCoin{atomPrice}
suite.ctx = suite.ctx.WithMinGasPrices(lowGasPrice)
_, err = antehandler(suite.ctx, tx, false)
suite.Require().Nil(err, "Decorator should not have errored on fee higher than local gasPrice")
}
func (suite *AnteTestSuite) TestDeductFees() {
suite.SetupTest(false) // setup
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
// keys and addresses
priv1, _, addr1 := testdata.KeyTestPubAddr()
// msg and signatures
msg := testdata.NewTestMsg(addr1)
feeAmount := testdata.NewTestFeeAmount()
gasLimit := testdata.NewTestGasLimit()
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
suite.txBuilder.SetFeeAmount(feeAmount)
suite.txBuilder.SetGasLimit(gasLimit)
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
// Set account with insufficient funds
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
coins := sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(10)))
err = simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr1, coins)
suite.Require().NoError(err)
dfd := ante.NewDeductFeeDecorator(suite.app.AccountKeeper, suite.app.BankKeeper, nil)
antehandler := sdk.ChainAnteDecorators(dfd)
_, err = antehandler(suite.ctx, tx, false)
suite.Require().NotNil(err, "Tx did not error when fee payer had insufficient funds")
// Set account with sufficient funds
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
err = simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr1, sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(200))))
suite.Require().NoError(err)
_, err = antehandler(suite.ctx, tx, false)
suite.Require().Nil(err, "Tx errored after account has been set with sufficient funds")
}
+233
View File
@@ -0,0 +1,233 @@
package ante_test
/* TODO: fix these tests
import (
"math/rand"
"testing"
"time"
"github.com/tendermint/tendermint/crypto"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/simapp/helpers"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
ante "github.com/tharsis/ethermint/x/auth/ante"
authsign "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/auth/tx"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/feegrant"
)
func (suite *AnteTestSuite) TestDeductFeesNoDelegation() {
suite.SetupTest(false)
// setup
app, ctx := suite.app, suite.ctx
protoTxCfg := tx.NewTxConfig(codec.NewProtoCodec(app.InterfaceRegistry()), tx.DefaultSignModes)
// this just tests our handler
dfd := ante.NewDeductFeeDecorator(app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper)
feeAnteHandler := sdk.ChainAnteDecorators(dfd)
// this tests the whole stack
anteHandlerStack := suite.anteHandler
// keys and addresses
priv1, _, addr1 := testdata.KeyTestPubAddr()
priv2, _, addr2 := testdata.KeyTestPubAddr()
priv3, _, addr3 := testdata.KeyTestPubAddr()
priv4, _, addr4 := testdata.KeyTestPubAddr()
priv5, _, addr5 := testdata.KeyTestPubAddr()
// Set addr1 with insufficient funds
err := simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr1, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(10))})
suite.Require().NoError(err)
// Set addr2 with more funds
err = simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr2, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(99999))})
suite.Require().NoError(err)
// grant fee allowance from `addr2` to `addr3` (plenty to pay)
err = app.FeeGrantKeeper.GrantAllowance(ctx, addr2, addr3, &feegrant.BasicAllowance{
SpendLimit: sdk.NewCoins(sdk.NewInt64Coin("atom", 500)),
})
suite.Require().NoError(err)
// grant low fee allowance (20atom), to check the tx requesting more than allowed.
err = app.FeeGrantKeeper.GrantAllowance(ctx, addr2, addr4, &feegrant.BasicAllowance{
SpendLimit: sdk.NewCoins(sdk.NewInt64Coin("atom", 20)),
})
suite.Require().NoError(err)
cases := map[string]struct {
signerKey cryptotypes.PrivKey
signer sdk.AccAddress
feeAccount sdk.AccAddress
fee int64
valid bool
}{
"paying with low funds": {
signerKey: priv1,
signer: addr1,
fee: 50,
valid: false,
},
"paying with good funds": {
signerKey: priv2,
signer: addr2,
fee: 50,
valid: true,
},
"paying with no account": {
signerKey: priv3,
signer: addr3,
fee: 1,
valid: false,
},
"no fee with real account": {
signerKey: priv1,
signer: addr1,
fee: 0,
valid: true,
},
"no fee with no account": {
signerKey: priv5,
signer: addr5,
fee: 0,
valid: false,
},
"valid fee grant without account": {
signerKey: priv3,
signer: addr3,
feeAccount: addr2,
fee: 50,
valid: true,
},
"no fee grant": {
signerKey: priv3,
signer: addr3,
feeAccount: addr1,
fee: 2,
valid: false,
},
"allowance smaller than requested fee": {
signerKey: priv4,
signer: addr4,
feeAccount: addr2,
fee: 50,
valid: false,
},
"granter cannot cover allowed fee grant": {
signerKey: priv4,
signer: addr4,
feeAccount: addr1,
fee: 50,
valid: false,
},
}
for name, stc := range cases {
tc := stc // to make scopelint happy
suite.T().Run(name, func(t *testing.T) {
fee := sdk.NewCoins(sdk.NewInt64Coin("atom", tc.fee))
msgs := []sdk.Msg{testdata.NewTestMsg(tc.signer)}
acc := app.AccountKeeper.GetAccount(ctx, tc.signer)
privs, accNums, seqs := []cryptotypes.PrivKey{tc.signerKey}, []uint64{0}, []uint64{0}
if acc != nil {
accNums, seqs = []uint64{acc.GetAccountNumber()}, []uint64{acc.GetSequence()}
}
tx, err := genTxWithFeeGranter(protoTxCfg, msgs, fee, helpers.DefaultGenTxGas, ctx.ChainID(), accNums, seqs, tc.feeAccount, privs...)
suite.Require().NoError(err)
_, err = feeAnteHandler(ctx, tx, false) // tests only feegrant ante
if tc.valid {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
_, err = anteHandlerStack(ctx, tx, false) // tests while stack
if tc.valid {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
// don't consume any gas
func SigGasNoConsumer(meter sdk.GasMeter, sig []byte, pubkey crypto.PubKey, params authtypes.Params) error {
return nil
}
func genTxWithFeeGranter(gen client.TxConfig, msgs []sdk.Msg, feeAmt sdk.Coins, gas uint64, chainID string, accNums,
accSeqs []uint64, feeGranter sdk.AccAddress, priv ...cryptotypes.PrivKey) (sdk.Tx, error) {
sigs := make([]signing.SignatureV2, len(priv))
// create a random length memo
r := rand.New(rand.NewSource(time.Now().UnixNano()))
memo := simulation.RandStringOfLength(r, simulation.RandIntBetween(r, 0, 100))
signMode := gen.SignModeHandler().DefaultMode()
// 1st round: set SignatureV2 with empty signatures, to set correct
// signer infos.
for i, p := range priv {
sigs[i] = signing.SignatureV2{
PubKey: p.PubKey(),
Data: &signing.SingleSignatureData{
SignMode: signMode,
},
Sequence: accSeqs[i],
}
}
tx := gen.NewTxBuilder()
err := tx.SetMsgs(msgs...)
if err != nil {
return nil, err
}
err = tx.SetSignatures(sigs...)
if err != nil {
return nil, err
}
tx.SetMemo(memo)
tx.SetFeeAmount(feeAmt)
tx.SetGasLimit(gas)
tx.SetFeeGranter(feeGranter)
// 2nd round: once all signer infos are set, every signer can sign.
for i, p := range priv {
signerData := authsign.SignerData{
ChainID: chainID,
AccountNumber: accNums[i],
Sequence: accSeqs[i],
}
signBytes, err := gen.SignModeHandler().GetSignBytes(signMode, signerData, tx.GetTx())
if err != nil {
panic(err)
}
sig, err := p.Sign(signBytes)
if err != nil {
panic(err)
}
sigs[i].Data.(*signing.SingleSignatureData).Signature = sig
err = tx.SetSignatures(sigs...)
if err != nil {
panic(err)
}
}
return tx.GetTx(), nil
}
*/
+76
View File
@@ -0,0 +1,76 @@
package ante
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
)
var (
_ GasTx = (*legacytx.StdTx)(nil) // assert StdTx implements GasTx
)
// GasTx defines a Tx with a GetGas() method which is needed to use SetUpContextDecorator
type GasTx interface {
sdk.Tx
GetGas() uint64
}
// SetUpContextDecorator sets the GasMeter in the Context and wraps the next AnteHandler with a defer clause
// to recover from any downstream OutOfGas panics in the AnteHandler chain to return an error with information
// on gas provided and gas used.
// CONTRACT: Must be first decorator in the chain
// CONTRACT: Tx must implement GasTx interface
type SetUpContextDecorator struct{}
func NewSetUpContextDecorator() SetUpContextDecorator {
return SetUpContextDecorator{}
}
func (sud SetUpContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
// all transactions must implement GasTx
gasTx, ok := tx.(GasTx)
if !ok {
// Set a gas meter with limit 0 as to prevent an infinite gas meter attack
// during runTx.
newCtx = SetGasMeter(simulate, ctx, 0)
return newCtx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be GasTx")
}
newCtx = SetGasMeter(simulate, ctx, gasTx.GetGas())
// Decorator will catch an OutOfGasPanic caused in the next antehandler
// AnteHandlers must have their own defer/recover in order for the BaseApp
// to know how much gas was used! This is because the GasMeter is created in
// the AnteHandler, but if it panics the context won't be set properly in
// runTx's recover call.
defer func() {
if r := recover(); r != nil {
switch rType := r.(type) {
case sdk.ErrorOutOfGas:
log := fmt.Sprintf(
"out of gas in location: %v; gasWanted: %d, gasUsed: %d",
rType.Descriptor, gasTx.GetGas(), newCtx.GasMeter().GasConsumed())
err = sdkerrors.Wrap(sdkerrors.ErrOutOfGas, log)
default:
panic(r)
}
}
}()
return next(newCtx, tx, simulate)
}
// SetGasMeter returns a new context with a gas meter set from a given context.
func SetGasMeter(simulate bool, ctx sdk.Context, gasLimit uint64) sdk.Context {
// In various cases such as simulation and during the genesis block, we do not
// meter any gas utilization.
if simulate || ctx.BlockHeight() == 0 {
return ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
}
return ctx.WithGasMeter(sdk.NewGasMeter(gasLimit))
}
+99
View File
@@ -0,0 +1,99 @@
package ante_test
import (
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
)
func (suite *AnteTestSuite) TestSetup() {
suite.SetupTest(true) // setup
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
// keys and addresses
priv1, _, addr1 := testdata.KeyTestPubAddr()
// msg and signatures
msg := testdata.NewTestMsg(addr1)
feeAmount := testdata.NewTestFeeAmount()
gasLimit := testdata.NewTestGasLimit()
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
suite.txBuilder.SetFeeAmount(feeAmount)
suite.txBuilder.SetGasLimit(gasLimit)
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
sud := ante.NewSetUpContextDecorator()
antehandler := sdk.ChainAnteDecorators(sud)
// Set height to non-zero value for GasMeter to be set
suite.ctx = suite.ctx.WithBlockHeight(1)
// Context GasMeter Limit not set
suite.Require().Equal(uint64(0), suite.ctx.GasMeter().Limit(), "GasMeter set with limit before setup")
newCtx, err := antehandler(suite.ctx, tx, false)
suite.Require().Nil(err, "SetUpContextDecorator returned error")
// Context GasMeter Limit should be set after SetUpContextDecorator runs
suite.Require().Equal(gasLimit, newCtx.GasMeter().Limit(), "GasMeter not set correctly")
}
func (suite *AnteTestSuite) TestRecoverPanic() {
suite.SetupTest(true) // setup
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
// keys and addresses
priv1, _, addr1 := testdata.KeyTestPubAddr()
// msg and signatures
msg := testdata.NewTestMsg(addr1)
feeAmount := testdata.NewTestFeeAmount()
gasLimit := testdata.NewTestGasLimit()
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
suite.txBuilder.SetFeeAmount(feeAmount)
suite.txBuilder.SetGasLimit(gasLimit)
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
sud := ante.NewSetUpContextDecorator()
antehandler := sdk.ChainAnteDecorators(sud, OutOfGasDecorator{})
// Set height to non-zero value for GasMeter to be set
suite.ctx = suite.ctx.WithBlockHeight(1)
newCtx, err := antehandler(suite.ctx, tx, false)
suite.Require().NotNil(err, "Did not return error on OutOfGas panic")
suite.Require().True(sdkerrors.ErrOutOfGas.Is(err), "Returned error is not an out of gas error")
suite.Require().Equal(gasLimit, newCtx.GasMeter().Limit())
antehandler = sdk.ChainAnteDecorators(sud, PanicDecorator{})
suite.Require().Panics(func() { antehandler(suite.ctx, tx, false) }, "Recovered from non-Out-of-Gas panic") // nolint:errcheck
}
type OutOfGasDecorator struct{}
// AnteDecorator that will throw OutOfGas panic
func (ogd OutOfGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
overLimit := ctx.GasMeter().Limit() + 1
// Should panic with outofgas error
ctx.GasMeter().ConsumeGas(overLimit, "test panic")
// not reached
return next(ctx, tx, simulate)
}
type PanicDecorator struct{}
func (pd PanicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
panic("random error")
}
+510
View File
@@ -0,0 +1,510 @@
package ante
import (
"bytes"
"encoding/base64"
"encoding/hex"
"fmt"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
var (
// simulation signature values used to estimate gas consumption
key = make([]byte, secp256k1.PubKeySize)
simSecp256k1Pubkey = &secp256k1.PubKey{Key: key}
simSecp256k1Sig [64]byte
_ authsigning.SigVerifiableTx = (*legacytx.StdTx)(nil) // assert StdTx implements SigVerifiableTx
)
func init() {
// This decodes a valid hex string into a sepc256k1Pubkey for use in transaction simulation
bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A")
copy(key, bz)
simSecp256k1Pubkey.Key = key
}
// SignatureVerificationGasConsumer is the type of function that is used to both
// consume gas when verifying signatures and also to accept or reject different types of pubkeys
// This is where apps can define their own PubKey
type SignatureVerificationGasConsumer = func(meter sdk.GasMeter, sig signing.SignatureV2, params types.Params) error
// SetPubKeyDecorator sets PubKeys in context for any signer which does not already have pubkey set
// PubKeys must be set in context for all signers before any other sigverify decorators run
// CONTRACT: Tx must implement SigVerifiableTx interface
type SetPubKeyDecorator struct {
ak AccountKeeper
}
func NewSetPubKeyDecorator(ak AccountKeeper) SetPubKeyDecorator {
return SetPubKeyDecorator{
ak: ak,
}
}
func (spkd SetPubKeyDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
sigTx, ok := tx.(authsigning.SigVerifiableTx)
if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid tx type")
}
pubkeys, err := sigTx.GetPubKeys()
if err != nil {
return ctx, err
}
signers := sigTx.GetSigners()
for i, pk := range pubkeys {
// PublicKey was omitted from slice since it has already been set in context
if pk == nil {
if !simulate {
continue
}
pk = simSecp256k1Pubkey
}
// Only make check if simulate=false
if !simulate && !bytes.Equal(pk.Address(), signers[i]) {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey,
"pubKey does not match signer address %s with signer index: %d", signers[i], i)
}
acc, err := GetSignerAcc(ctx, spkd.ak, signers[i])
if err != nil {
return ctx, err
}
// account already has pubkey set,no need to reset
if acc.GetPubKey() != nil {
continue
}
err = acc.SetPubKey(pk)
if err != nil {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, err.Error())
}
spkd.ak.SetAccount(ctx, acc)
}
// Also emit the following events, so that txs can be indexed by these
// indices:
// - signature (via `tx.signature='<sig_as_base64>'`),
// - concat(address,"/",sequence) (via `tx.acc_seq='cosmos1abc...def/42'`).
sigs, err := sigTx.GetSignaturesV2()
if err != nil {
return ctx, err
}
var events sdk.Events
for i, sig := range sigs {
events = append(events, sdk.NewEvent(sdk.EventTypeTx,
sdk.NewAttribute(sdk.AttributeKeyAccountSequence, fmt.Sprintf("%s/%d", signers[i], sig.Sequence)),
))
sigBzs, err := signatureDataToBz(sig.Data)
if err != nil {
return ctx, err
}
for _, sigBz := range sigBzs {
events = append(events, sdk.NewEvent(sdk.EventTypeTx,
sdk.NewAttribute(sdk.AttributeKeySignature, base64.StdEncoding.EncodeToString(sigBz)),
))
}
}
ctx.EventManager().EmitEvents(events)
return next(ctx, tx, simulate)
}
// Consume parameter-defined amount of gas for each signature according to the passed-in SignatureVerificationGasConsumer function
// before calling the next AnteHandler
// CONTRACT: Pubkeys are set in context for all signers before this decorator runs
// CONTRACT: Tx must implement SigVerifiableTx interface
type SigGasConsumeDecorator struct {
ak AccountKeeper
sigGasConsumer SignatureVerificationGasConsumer
}
func NewSigGasConsumeDecorator(ak AccountKeeper, sigGasConsumer SignatureVerificationGasConsumer) SigGasConsumeDecorator {
return SigGasConsumeDecorator{
ak: ak,
sigGasConsumer: sigGasConsumer,
}
}
func (sgcd SigGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
sigTx, ok := tx.(authsigning.SigVerifiableTx)
if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
}
params := sgcd.ak.GetParams(ctx)
sigs, err := sigTx.GetSignaturesV2()
if err != nil {
return ctx, err
}
// stdSigs contains the sequence number, account number, and signatures.
// When simulating, this would just be a 0-length slice.
signerAddrs := sigTx.GetSigners()
for i, sig := range sigs {
signerAcc, err := GetSignerAcc(ctx, sgcd.ak, signerAddrs[i])
if err != nil {
return ctx, err
}
pubKey := signerAcc.GetPubKey()
// In simulate mode the transaction comes with no signatures, thus if the
// account's pubkey is nil, both signature verification and gasKVStore.Set()
// shall consume the largest amount, i.e. it takes more gas to verify
// secp256k1 keys than ed25519 ones.
if simulate && pubKey == nil {
pubKey = simSecp256k1Pubkey
}
// make a SignatureV2 with PubKey filled in from above
sig = signing.SignatureV2{
PubKey: pubKey,
Data: sig.Data,
Sequence: sig.Sequence,
}
err = sgcd.sigGasConsumer(ctx.GasMeter(), sig, params)
if err != nil {
return ctx, err
}
}
return next(ctx, tx, simulate)
}
// Verify all signatures for a tx and return an error if any are invalid. Note,
// the SigVerificationDecorator decorator will not get executed on ReCheck.
//
// CONTRACT: Pubkeys are set in context for all signers before this decorator runs
// CONTRACT: Tx must implement SigVerifiableTx interface
type SigVerificationDecorator struct {
ak AccountKeeper
signModeHandler authsigning.SignModeHandler
}
func NewSigVerificationDecorator(ak AccountKeeper, signModeHandler authsigning.SignModeHandler) SigVerificationDecorator {
return SigVerificationDecorator{
ak: ak,
signModeHandler: signModeHandler,
}
}
// OnlyLegacyAminoSigners checks SignatureData to see if all
// signers are using SIGN_MODE_LEGACY_AMINO_JSON. If this is the case
// then the corresponding SignatureV2 struct will not have account sequence
// explicitly set, and we should skip the explicit verification of sig.Sequence
// in the SigVerificationDecorator's AnteHandler function.
func OnlyLegacyAminoSigners(sigData signing.SignatureData) bool {
switch v := sigData.(type) {
case *signing.SingleSignatureData:
return v.SignMode == signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON
case *signing.MultiSignatureData:
for _, s := range v.Signatures {
if !OnlyLegacyAminoSigners(s) {
return false
}
}
return true
default:
return false
}
}
func (svd SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
// no need to verify signatures on recheck tx
if ctx.IsReCheckTx() {
return next(ctx, tx, simulate)
}
sigTx, ok := tx.(authsigning.SigVerifiableTx)
if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
}
// stdSigs contains the sequence number, account number, and signatures.
// When simulating, this would just be a 0-length slice.
sigs, err := sigTx.GetSignaturesV2()
if err != nil {
return ctx, err
}
signerAddrs := sigTx.GetSigners()
// check that signer length and signature length are the same
if len(sigs) != len(signerAddrs) {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signerAddrs), len(sigs))
}
for i, sig := range sigs {
acc, err := GetSignerAcc(ctx, svd.ak, signerAddrs[i])
if err != nil {
return ctx, err
}
// retrieve pubkey
pubKey := acc.GetPubKey()
if !simulate && pubKey == nil {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "pubkey on account is not set")
}
// Check account sequence number.
if sig.Sequence != acc.GetSequence() {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrWrongSequence,
"account sequence mismatch, expected %d, got %d", acc.GetSequence(), sig.Sequence,
)
}
// retrieve signer data
genesis := ctx.BlockHeight() == 0
chainID := ctx.ChainID()
var accNum uint64
if !genesis {
accNum = acc.GetAccountNumber()
}
signerData := authsigning.SignerData{
ChainID: chainID,
AccountNumber: accNum,
Sequence: acc.GetSequence(),
}
if !simulate {
err := authsigning.VerifySignature(pubKey, signerData, sig.Data, svd.signModeHandler, tx)
if err != nil {
var errMsg string
if OnlyLegacyAminoSigners(sig.Data) {
// If all signers are using SIGN_MODE_LEGACY_AMINO, we rely on VerifySignature to check account sequence number,
// and therefore communicate sequence number as a potential cause of error.
errMsg = fmt.Sprintf("signature verification failed; please verify account number (%d), sequence (%d) and chain-id (%s)", accNum, acc.GetSequence(), chainID)
} else {
errMsg = fmt.Sprintf("signature verification failed; please verify account number (%d) and chain-id (%s)", accNum, chainID)
}
return ctx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, errMsg)
}
}
}
return next(ctx, tx, simulate)
}
// IncrementSequenceDecorator handles incrementing sequences of all signers.
// Use the IncrementSequenceDecorator decorator to prevent replay attacks. Note,
// there is no need to execute IncrementSequenceDecorator on RecheckTX since
// CheckTx would already bump the sequence number.
//
// NOTE: Since CheckTx and DeliverTx state are managed separately, subsequent and
// sequential txs orginating from the same account cannot be handled correctly in
// a reliable way unless sequence numbers are managed and tracked manually by a
// client. It is recommended to instead use multiple messages in a tx.
type IncrementSequenceDecorator struct {
ak AccountKeeper
}
func NewIncrementSequenceDecorator(ak AccountKeeper) IncrementSequenceDecorator {
return IncrementSequenceDecorator{
ak: ak,
}
}
func (isd IncrementSequenceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
sigTx, ok := tx.(authsigning.SigVerifiableTx)
if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
}
// increment sequence of all signers
for _, addr := range sigTx.GetSigners() {
acc := isd.ak.GetAccount(ctx, addr)
if err := acc.SetSequence(acc.GetSequence() + 1); err != nil {
panic(err)
}
isd.ak.SetAccount(ctx, acc)
}
return next(ctx, tx, simulate)
}
// ValidateSigCountDecorator takes in Params and returns errors if there are too many signatures in the tx for the given params
// otherwise it calls next AnteHandler
// Use this decorator to set parameterized limit on number of signatures in tx
// CONTRACT: Tx must implement SigVerifiableTx interface
type ValidateSigCountDecorator struct {
ak AccountKeeper
}
func NewValidateSigCountDecorator(ak AccountKeeper) ValidateSigCountDecorator {
return ValidateSigCountDecorator{
ak: ak,
}
}
func (vscd ValidateSigCountDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
sigTx, ok := tx.(authsigning.SigVerifiableTx)
if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a sigTx")
}
params := vscd.ak.GetParams(ctx)
pubKeys, err := sigTx.GetPubKeys()
if err != nil {
return ctx, err
}
sigCount := 0
for _, pk := range pubKeys {
sigCount += CountSubKeys(pk)
if uint64(sigCount) > params.TxSigLimit {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrTooManySignatures,
"signatures: %d, limit: %d", sigCount, params.TxSigLimit)
}
}
return next(ctx, tx, simulate)
}
// DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It 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.
func DefaultSigVerificationGasConsumer(
meter sdk.GasMeter, sig signing.SignatureV2, params types.Params,
) error {
pubkey := sig.PubKey
switch pubkey := pubkey.(type) {
case *ed25519.PubKey:
meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519")
return sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "ED25519 public keys are unsupported")
case *secp256k1.PubKey:
meter.ConsumeGas(params.SigVerifyCostSecp256k1, "ante verify: secp256k1")
return nil
case *secp256r1.PubKey:
meter.ConsumeGas(params.SigVerifyCostSecp256r1(), "ante verify: secp256r1")
return nil
case multisig.PubKey:
multisignature, ok := sig.Data.(*signing.MultiSignatureData)
if !ok {
return fmt.Errorf("expected %T, got, %T", &signing.MultiSignatureData{}, sig.Data)
}
err := ConsumeMultisignatureVerificationGas(meter, multisignature, pubkey, params, sig.Sequence)
if err != nil {
return err
}
return nil
default:
return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "unrecognized public key type: %T", pubkey)
}
}
// ConsumeMultisignatureVerificationGas consumes gas from a GasMeter for verifying a multisig pubkey signature
func ConsumeMultisignatureVerificationGas(
meter sdk.GasMeter, sig *signing.MultiSignatureData, pubkey multisig.PubKey,
params types.Params, accSeq uint64,
) error {
size := sig.BitArray.Count()
sigIndex := 0
for i := 0; i < size; i++ {
if !sig.BitArray.GetIndex(i) {
continue
}
sigV2 := signing.SignatureV2{
PubKey: pubkey.GetPubKeys()[i],
Data: sig.Signatures[sigIndex],
Sequence: accSeq,
}
err := DefaultSigVerificationGasConsumer(meter, sigV2, params)
if err != nil {
return err
}
sigIndex++
}
return nil
}
// GetSignerAcc returns an account for a given address that is expected to sign
// a transaction.
func GetSignerAcc(ctx sdk.Context, ak AccountKeeper, addr sdk.AccAddress) (types.AccountI, error) {
if acc := ak.GetAccount(ctx, addr); acc != nil {
return acc, nil
}
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", addr)
}
// CountSubKeys counts the total number of keys for a multi-sig public key.
func CountSubKeys(pub cryptotypes.PubKey) int {
v, ok := pub.(*kmultisig.LegacyAminoPubKey)
if !ok {
return 1
}
numKeys := 0
for _, subkey := range v.GetPubKeys() {
numKeys += CountSubKeys(subkey)
}
return numKeys
}
// signatureDataToBz converts a SignatureData into raw bytes signature.
// For SingleSignatureData, it returns the signature raw bytes.
// For MultiSignatureData, it returns an array of all individual signatures,
// as well as the aggregated signature.
func signatureDataToBz(data signing.SignatureData) ([][]byte, error) {
if data == nil {
return nil, fmt.Errorf("got empty SignatureData")
}
switch data := data.(type) {
case *signing.SingleSignatureData:
return [][]byte{data.Signature}, nil
case *signing.MultiSignatureData:
sigs := [][]byte{}
var err error
for _, d := range data.Signatures {
nestedSigs, err := signatureDataToBz(d)
if err != nil {
return nil, err
}
sigs = append(sigs, nestedSigs...)
}
multisig := cryptotypes.MultiSignature{
Signatures: sigs,
}
aggregatedSig, err := multisig.Marshal()
if err != nil {
return nil, err
}
sigs = append(sigs, aggregatedSig)
return sigs, nil
default:
return nil, sdkerrors.ErrInvalidType.Wrapf("unexpected signature data type %T", data)
}
}
+44
View File
@@ -0,0 +1,44 @@
package ante_test
import (
"testing"
"github.com/stretchr/testify/require"
tmcrypto "github.com/tendermint/tendermint/crypto"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
)
// This benchmark is used to asses the ante.Secp256k1ToR1GasFactor value
func BenchmarkSig(b *testing.B) {
require := require.New(b)
msg := tmcrypto.CRandBytes(1000)
skK := secp256k1.GenPrivKey()
pkK := skK.PubKey()
skR, _ := secp256r1.GenPrivKey()
pkR := skR.PubKey()
sigK, err := skK.Sign(msg)
require.NoError(err)
sigR, err := skR.Sign(msg)
require.NoError(err)
b.ResetTimer()
b.Run("secp256k1", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
ok := pkK.VerifySignature(msg, sigK)
require.True(ok)
}
})
b.Run("secp256r1", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
ok := pkR.VerifySignature(msg, sigR)
require.True(ok)
}
})
}
+390
View File
@@ -0,0 +1,390 @@
package ante_test
import (
"fmt"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
func (suite *AnteTestSuite) TestSetPubKey() {
suite.SetupTest(true) // setup
require := suite.Require()
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
// keys and addresses
priv1, pub1, addr1 := testdata.KeyTestPubAddr()
priv2, pub2, addr2 := testdata.KeyTestPubAddr()
priv3, pub3, addr3 := testdata.KeyTestPubAddrSecp256R1(require)
addrs := []sdk.AccAddress{addr1, addr2, addr3}
pubs := []cryptotypes.PubKey{pub1, pub2, pub3}
msgs := make([]sdk.Msg, len(addrs))
// set accounts and create msg for each address
for i, addr := range addrs {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr)
require.NoError(acc.SetAccountNumber(uint64(i)))
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
msgs[i] = testdata.NewTestMsg(addr)
}
require.NoError(suite.txBuilder.SetMsgs(msgs...))
suite.txBuilder.SetFeeAmount(testdata.NewTestFeeAmount())
suite.txBuilder.SetGasLimit(testdata.NewTestGasLimit())
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0}
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
require.NoError(err)
spkd := ante.NewSetPubKeyDecorator(suite.app.AccountKeeper)
antehandler := sdk.ChainAnteDecorators(spkd)
ctx, err := antehandler(suite.ctx, tx, false)
require.NoError(err)
// Require that all accounts have pubkey set after Decorator runs
for i, addr := range addrs {
pk, err := suite.app.AccountKeeper.GetPubKey(ctx, addr)
require.NoError(err, "Error on retrieving pubkey from account")
require.True(pubs[i].Equals(pk),
"Wrong Pubkey retrieved from AccountKeeper, idx=%d\nexpected=%s\n got=%s", i, pubs[i], pk)
}
}
func (suite *AnteTestSuite) TestConsumeSignatureVerificationGas() {
params := types.DefaultParams()
msg := []byte{1, 2, 3, 4}
cdc := simapp.MakeTestEncodingConfig().Amino
p := types.DefaultParams()
skR1, _ := secp256r1.GenPrivKey()
pkSet1, sigSet1 := generatePubKeysAndSignatures(5, msg, false)
multisigKey1 := kmultisig.NewLegacyAminoPubKey(2, pkSet1)
multisignature1 := multisig.NewMultisig(len(pkSet1))
expectedCost1 := expectedGasCostByKeys(pkSet1)
for i := 0; i < len(pkSet1); i++ {
stdSig := legacytx.StdSignature{PubKey: pkSet1[i], Signature: sigSet1[i]}
sigV2, err := legacytx.StdSignatureToSignatureV2(cdc, stdSig)
suite.Require().NoError(err)
err = multisig.AddSignatureV2(multisignature1, sigV2, pkSet1)
suite.Require().NoError(err)
}
type args struct {
meter sdk.GasMeter
sig signing.SignatureData
pubkey cryptotypes.PubKey
params types.Params
}
tests := []struct {
name string
args args
gasConsumed uint64
shouldErr bool
}{
{"PubKeyEd25519", args{sdk.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, p.SigVerifyCostED25519, true},
{"PubKeySecp256k1", args{sdk.NewInfiniteGasMeter(), nil, secp256k1.GenPrivKey().PubKey(), params}, p.SigVerifyCostSecp256k1, false},
{"PubKeySecp256r1", args{sdk.NewInfiniteGasMeter(), nil, skR1.PubKey(), params}, p.SigVerifyCostSecp256r1(), false},
{"Multisig", args{sdk.NewInfiniteGasMeter(), multisignature1, multisigKey1, params}, expectedCost1, false},
{"unknown key", args{sdk.NewInfiniteGasMeter(), nil, nil, params}, 0, true},
}
for _, tt := range tests {
sigV2 := signing.SignatureV2{
PubKey: tt.args.pubkey,
Data: tt.args.sig,
Sequence: 0, // Arbitrary account sequence
}
err := ante.DefaultSigVerificationGasConsumer(tt.args.meter, sigV2, tt.args.params)
if tt.shouldErr {
suite.Require().NotNil(err)
} else {
suite.Require().Nil(err)
suite.Require().Equal(tt.gasConsumed, tt.args.meter.GasConsumed(), fmt.Sprintf("%d != %d", tt.gasConsumed, tt.args.meter.GasConsumed()))
}
}
}
func (suite *AnteTestSuite) TestSigVerification() {
suite.SetupTest(true) // setup
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
// make block height non-zero to ensure account numbers part of signBytes
suite.ctx = suite.ctx.WithBlockHeight(1)
// keys and addresses
priv1, _, addr1 := testdata.KeyTestPubAddr()
priv2, _, addr2 := testdata.KeyTestPubAddr()
priv3, _, addr3 := testdata.KeyTestPubAddr()
addrs := []sdk.AccAddress{addr1, addr2, addr3}
msgs := make([]sdk.Msg, len(addrs))
// set accounts and create msg for each address
for i, addr := range addrs {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr)
suite.Require().NoError(acc.SetAccountNumber(uint64(i)))
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
msgs[i] = testdata.NewTestMsg(addr)
}
feeAmount := testdata.NewTestFeeAmount()
gasLimit := testdata.NewTestGasLimit()
spkd := ante.NewSetPubKeyDecorator(suite.app.AccountKeeper)
svd := ante.NewSigVerificationDecorator(suite.app.AccountKeeper, suite.clientCtx.TxConfig.SignModeHandler())
antehandler := sdk.ChainAnteDecorators(spkd, svd)
type testCase struct {
name string
privs []cryptotypes.PrivKey
accNums []uint64
accSeqs []uint64
recheck bool
shouldErr bool
}
testCases := []testCase{
{"no signers", []cryptotypes.PrivKey{}, []uint64{}, []uint64{}, false, true},
{"not enough signers", []cryptotypes.PrivKey{priv1, priv2}, []uint64{0, 1}, []uint64{0, 0}, false, true},
{"wrong order signers", []cryptotypes.PrivKey{priv3, priv2, priv1}, []uint64{2, 1, 0}, []uint64{0, 0, 0}, false, true},
{"wrong accnums", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{7, 8, 9}, []uint64{0, 0, 0}, false, true},
{"wrong sequences", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{3, 4, 5}, false, true},
{"valid tx", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0}, false, false},
{"no err on recheck", []cryptotypes.PrivKey{}, []uint64{}, []uint64{}, true, false},
}
for i, tc := range testCases {
suite.ctx = suite.ctx.WithIsReCheckTx(tc.recheck)
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() // Create new txBuilder for each test
suite.Require().NoError(suite.txBuilder.SetMsgs(msgs...))
suite.txBuilder.SetFeeAmount(feeAmount)
suite.txBuilder.SetGasLimit(gasLimit)
tx, err := suite.CreateTestTx(tc.privs, tc.accNums, tc.accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
_, err = antehandler(suite.ctx, tx, false)
if tc.shouldErr {
suite.Require().NotNil(err, "TestCase %d: %s did not error as expected", i, tc.name)
} else {
suite.Require().Nil(err, "TestCase %d: %s errored unexpectedly. Err: %v", i, tc.name, err)
}
}
}
// This test is exactly like the one above, but we set the codec explicitly to
// Amino.
// Once https://github.com/cosmos/cosmos-sdk/issues/6190 is in, we can remove
// this, since it'll be handled by the test matrix.
// In the meantime, we want to make double-sure amino compatibility works.
// ref: https://github.com/cosmos/cosmos-sdk/issues/7229
func (suite *AnteTestSuite) TestSigVerification_ExplicitAmino() {
suite.app, suite.ctx = createTestApp(true)
suite.ctx = suite.ctx.WithBlockHeight(1)
// Set up TxConfig.
aminoCdc := codec.NewLegacyAmino()
// We're using TestMsg amino encoding in some tests, so register it here.
txConfig := legacytx.StdTxConfig{Cdc: aminoCdc}
suite.clientCtx = client.Context{}.
WithTxConfig(txConfig)
anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: suite.app.AccountKeeper,
BankKeeper: suite.app.BankKeeper,
FeegrantKeeper: suite.app.FeeGrantKeeper,
SignModeHandler: txConfig.SignModeHandler(),
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
)
suite.Require().NoError(err)
suite.anteHandler = anteHandler
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
// make block height non-zero to ensure account numbers part of signBytes
suite.ctx = suite.ctx.WithBlockHeight(1)
// keys and addresses
priv1, _, addr1 := testdata.KeyTestPubAddr()
priv2, _, addr2 := testdata.KeyTestPubAddr()
priv3, _, addr3 := testdata.KeyTestPubAddr()
addrs := []sdk.AccAddress{addr1, addr2, addr3}
msgs := make([]sdk.Msg, len(addrs))
// set accounts and create msg for each address
for i, addr := range addrs {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr)
suite.Require().NoError(acc.SetAccountNumber(uint64(i)))
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
msgs[i] = testdata.NewTestMsg(addr)
}
feeAmount := testdata.NewTestFeeAmount()
gasLimit := testdata.NewTestGasLimit()
spkd := ante.NewSetPubKeyDecorator(suite.app.AccountKeeper)
svd := ante.NewSigVerificationDecorator(suite.app.AccountKeeper, suite.clientCtx.TxConfig.SignModeHandler())
antehandler := sdk.ChainAnteDecorators(spkd, svd)
type testCase struct {
name string
privs []cryptotypes.PrivKey
accNums []uint64
accSeqs []uint64
recheck bool
shouldErr bool
}
testCases := []testCase{
{"no signers", []cryptotypes.PrivKey{}, []uint64{}, []uint64{}, false, true},
{"not enough signers", []cryptotypes.PrivKey{priv1, priv2}, []uint64{0, 1}, []uint64{0, 0}, false, true},
{"wrong order signers", []cryptotypes.PrivKey{priv3, priv2, priv1}, []uint64{2, 1, 0}, []uint64{0, 0, 0}, false, true},
{"wrong accnums", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{7, 8, 9}, []uint64{0, 0, 0}, false, true},
{"wrong sequences", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{3, 4, 5}, false, true},
{"valid tx", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0}, false, false},
{"no err on recheck", []cryptotypes.PrivKey{}, []uint64{}, []uint64{}, true, false},
}
for i, tc := range testCases {
suite.ctx = suite.ctx.WithIsReCheckTx(tc.recheck)
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() // Create new txBuilder for each test
suite.Require().NoError(suite.txBuilder.SetMsgs(msgs...))
suite.txBuilder.SetFeeAmount(feeAmount)
suite.txBuilder.SetGasLimit(gasLimit)
tx, err := suite.CreateTestTx(tc.privs, tc.accNums, tc.accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
_, err = antehandler(suite.ctx, tx, false)
if tc.shouldErr {
suite.Require().NotNil(err, "TestCase %d: %s did not error as expected", i, tc.name)
} else {
suite.Require().Nil(err, "TestCase %d: %s errored unexpectedly. Err: %v", i, tc.name, err)
}
}
}
func (suite *AnteTestSuite) TestSigIntegration() {
// generate private keys
privs := []cryptotypes.PrivKey{
secp256k1.GenPrivKey(),
secp256k1.GenPrivKey(),
secp256k1.GenPrivKey(),
}
params := types.DefaultParams()
initialSigCost := params.SigVerifyCostSecp256k1
initialCost, err := suite.runSigDecorators(params, false, privs...)
suite.Require().Nil(err)
params.SigVerifyCostSecp256k1 *= 2
doubleCost, err := suite.runSigDecorators(params, false, privs...)
suite.Require().Nil(err)
suite.Require().Equal(initialSigCost*uint64(len(privs)), doubleCost-initialCost)
}
func (suite *AnteTestSuite) runSigDecorators(params types.Params, _ bool, privs ...cryptotypes.PrivKey) (sdk.Gas, error) {
suite.SetupTest(true) // setup
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
// Make block-height non-zero to include accNum in SignBytes
suite.ctx = suite.ctx.WithBlockHeight(1)
suite.app.AccountKeeper.SetParams(suite.ctx, params)
msgs := make([]sdk.Msg, len(privs))
accNums := make([]uint64, len(privs))
accSeqs := make([]uint64, len(privs))
// set accounts and create msg for each address
for i, priv := range privs {
addr := sdk.AccAddress(priv.PubKey().Address())
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr)
suite.Require().NoError(acc.SetAccountNumber(uint64(i)))
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
msgs[i] = testdata.NewTestMsg(addr)
accNums[i] = uint64(i)
accSeqs[i] = uint64(0)
}
suite.Require().NoError(suite.txBuilder.SetMsgs(msgs...))
feeAmount := testdata.NewTestFeeAmount()
gasLimit := testdata.NewTestGasLimit()
suite.txBuilder.SetFeeAmount(feeAmount)
suite.txBuilder.SetGasLimit(gasLimit)
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
spkd := ante.NewSetPubKeyDecorator(suite.app.AccountKeeper)
svgc := ante.NewSigGasConsumeDecorator(suite.app.AccountKeeper, ante.DefaultSigVerificationGasConsumer)
svd := ante.NewSigVerificationDecorator(suite.app.AccountKeeper, suite.clientCtx.TxConfig.SignModeHandler())
antehandler := sdk.ChainAnteDecorators(spkd, svgc, svd)
// Determine gas consumption of antehandler with default params
before := suite.ctx.GasMeter().GasConsumed()
ctx, err := antehandler(suite.ctx, tx, false)
after := ctx.GasMeter().GasConsumed()
return after - before, err
}
func (suite *AnteTestSuite) TestIncrementSequenceDecorator() {
suite.SetupTest(true) // setup
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
priv, _, addr := testdata.KeyTestPubAddr()
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr)
suite.Require().NoError(acc.SetAccountNumber(uint64(50)))
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
msgs := []sdk.Msg{testdata.NewTestMsg(addr)}
suite.Require().NoError(suite.txBuilder.SetMsgs(msgs...))
privs := []cryptotypes.PrivKey{priv}
accNums := []uint64{suite.app.AccountKeeper.GetAccount(suite.ctx, addr).GetAccountNumber()}
accSeqs := []uint64{suite.app.AccountKeeper.GetAccount(suite.ctx, addr).GetSequence()}
feeAmount := testdata.NewTestFeeAmount()
gasLimit := testdata.NewTestGasLimit()
suite.txBuilder.SetFeeAmount(feeAmount)
suite.txBuilder.SetGasLimit(gasLimit)
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
isd := ante.NewIncrementSequenceDecorator(suite.app.AccountKeeper)
antehandler := sdk.ChainAnteDecorators(isd)
testCases := []struct {
ctx sdk.Context
simulate bool
expectedSeq uint64
}{
{suite.ctx.WithIsReCheckTx(true), false, 1},
{suite.ctx.WithIsCheckTx(true).WithIsReCheckTx(false), false, 2},
{suite.ctx.WithIsReCheckTx(true), false, 3},
{suite.ctx.WithIsReCheckTx(true), false, 4},
{suite.ctx.WithIsReCheckTx(true), true, 5},
}
for i, tc := range testCases {
_, err := antehandler(tc.ctx, tx, tc.simulate)
suite.Require().NoError(err, "unexpected error; tc #%d, %v", i, tc)
suite.Require().Equal(tc.expectedSeq, suite.app.AccountKeeper.GetAccount(suite.ctx, addr).GetSequence())
}
}
+200
View File
@@ -0,0 +1,200 @@
package ante_test
import (
"errors"
"fmt"
"testing"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
"github.com/stretchr/testify/suite"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
xauthsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/auth/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
)
// TestAccount represents an account used in the tests in x/auth/ante.
type TestAccount struct {
acc types.AccountI
priv cryptotypes.PrivKey
}
// AnteTestSuite is a test suite to be used with ante handler tests.
type AnteTestSuite struct {
suite.Suite
app *simapp.SimApp
anteHandler sdk.AnteHandler
ctx sdk.Context
clientCtx client.Context
txBuilder client.TxBuilder
}
// returns context and app with params set on account keeper
func createTestApp(isCheckTx bool) (*simapp.SimApp, sdk.Context) {
app := simapp.Setup(isCheckTx)
ctx := app.BaseApp.NewContext(isCheckTx, tmproto.Header{})
app.AccountKeeper.SetParams(ctx, authtypes.DefaultParams())
return app, ctx
}
// SetupTest setups a new test, with new app, context, and anteHandler.
func (suite *AnteTestSuite) SetupTest(isCheckTx bool) {
suite.app, suite.ctx = createTestApp(isCheckTx)
suite.ctx = suite.ctx.WithBlockHeight(1)
// Set up TxConfig.
encodingConfig := simapp.MakeTestEncodingConfig()
// We're using TestMsg encoding in some tests, so register it here.
encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
testdata.RegisterInterfaces(encodingConfig.InterfaceRegistry)
suite.clientCtx = client.Context{}.
WithTxConfig(encodingConfig.TxConfig)
anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: suite.app.AccountKeeper,
BankKeeper: suite.app.BankKeeper,
FeegrantKeeper: suite.app.FeeGrantKeeper,
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
)
suite.Require().NoError(err)
suite.anteHandler = anteHandler
}
// CreateTestAccounts creates `numAccs` accounts, and return all relevant
// information about them including their private keys.
func (suite *AnteTestSuite) CreateTestAccounts(numAccs int) []TestAccount {
var accounts []TestAccount
for i := 0; i < numAccs; i++ {
priv, _, addr := testdata.KeyTestPubAddr()
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr)
err := acc.SetAccountNumber(uint64(i))
suite.Require().NoError(err)
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
someCoins := sdk.Coins{
sdk.NewInt64Coin("atom", 10000000),
}
err = suite.app.BankKeeper.MintCoins(suite.ctx, minttypes.ModuleName, someCoins)
suite.Require().NoError(err)
err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, minttypes.ModuleName, addr, someCoins)
suite.Require().NoError(err)
accounts = append(accounts, TestAccount{acc, priv})
}
return accounts
}
// CreateTestTx is a helper function to create a tx given multiple inputs.
func (suite *AnteTestSuite) CreateTestTx(privs []cryptotypes.PrivKey, accNums []uint64, accSeqs []uint64, chainID string) (xauthsigning.Tx, error) {
// First round: we gather all the signer infos. We use the "set empty
// signature" hack to do that.
var sigsV2 []signing.SignatureV2
for i, priv := range privs {
sigV2 := signing.SignatureV2{
PubKey: priv.PubKey(),
Data: &signing.SingleSignatureData{
SignMode: suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(),
Signature: nil,
},
Sequence: accSeqs[i],
}
sigsV2 = append(sigsV2, sigV2)
}
err := suite.txBuilder.SetSignatures(sigsV2...)
if err != nil {
return nil, err
}
// Second round: all signer infos are set, so each signer can sign.
sigsV2 = []signing.SignatureV2{}
for i, priv := range privs {
signerData := xauthsigning.SignerData{
ChainID: chainID,
AccountNumber: accNums[i],
Sequence: accSeqs[i],
}
sigV2, err := tx.SignWithPrivKey(
suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), signerData,
suite.txBuilder, priv, suite.clientCtx.TxConfig, accSeqs[i])
if err != nil {
return nil, err
}
sigsV2 = append(sigsV2, sigV2)
}
err = suite.txBuilder.SetSignatures(sigsV2...)
if err != nil {
return nil, err
}
return suite.txBuilder.GetTx(), nil
}
// TestCase represents a test case used in test tables.
type TestCase struct {
desc string
malleate func()
simulate bool
expPass bool
expErr error
}
// CreateTestTx is a helper function to create a tx given multiple inputs.
func (suite *AnteTestSuite) RunTestCase(privs []cryptotypes.PrivKey, msgs []sdk.Msg, feeAmount sdk.Coins, gasLimit uint64, accNums, accSeqs []uint64, chainID string, tc TestCase) {
suite.Run(fmt.Sprintf("Case %s", tc.desc), func() {
suite.Require().NoError(suite.txBuilder.SetMsgs(msgs...))
suite.txBuilder.SetFeeAmount(feeAmount)
suite.txBuilder.SetGasLimit(gasLimit)
// Theoretically speaking, ante handler unit tests should only test
// ante handlers, but here we sometimes also test the tx creation
// process.
tx, txErr := suite.CreateTestTx(privs, accNums, accSeqs, chainID)
newCtx, anteErr := suite.anteHandler(suite.ctx, tx, tc.simulate)
if tc.expPass {
suite.Require().NoError(txErr)
suite.Require().NoError(anteErr)
suite.Require().NotNil(newCtx)
suite.ctx = newCtx
} else {
switch {
case txErr != nil:
suite.Require().Error(txErr)
suite.Require().True(errors.Is(txErr, tc.expErr))
case anteErr != nil:
suite.Require().Error(anteErr)
suite.Require().True(errors.Is(anteErr, tc.expErr))
default:
suite.Fail("expected one of txErr,anteErr to be an error")
}
}
})
}
func TestAnteTestSuite(t *testing.T) {
suite.Run(t, new(AnteTestSuite))
}
+1 -1
View File
@@ -3,8 +3,8 @@ package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/palantir/stacktrace"
authante "github.com/tharsis/ethermint/x/auth/ante"
evmtypes "github.com/tharsis/ethermint/x/evm/types"