package app import ( "encoding/json" "math/rand" // #nosec G702 "time" "github.com/cerc-io/laconicd/crypto/ethsecp256k1" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/testutil/mock" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/cerc-io/laconicd/encoding" sdk "github.com/cosmos/cosmos-sdk/types" abci "github.com/tendermint/tendermint/abci/types" "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{ MaxBytes: 200000, MaxGas: -1, // no limit }, Evidence: &tmproto.EvidenceParams{ MaxAgeNumBlocks: 302400, MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration MaxBytes: 10000, }, Validator: &tmproto.ValidatorParams{ PubKeyTypes: []string{ tmtypes.ABCIPubKeyTypeEd25519, }, }, } // Setup initializes a new EthermintApp. A Nop logger is set in EthermintApp. func Setup(isCheckTx bool, patchGenesis func(*EthermintApp, simapp.GenesisState) simapp.GenesisState) *EthermintApp { return SetupWithDB(isCheckTx, patchGenesis, dbm.NewMemDB()) } // SetupWithDB initializes a new EthermintApp. A Nop logger is set in EthermintApp. func SetupWithDB(isCheckTx bool, patchGenesis func(*EthermintApp, simapp.GenesisState) simapp.GenesisState, db dbm.DB) *EthermintApp { 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 genesisState := NewTestGenesisState(app.AppCodec()) if patchGenesis != nil { genesisState = patchGenesis(app, genesisState) } stateBytes, err := json.MarshalIndent(genesisState, "", " ") if err != nil { panic(err) } // Initialize the chain app.InitChain( abci.RequestInitChain{ ChainId: "ethermint_9000-1", Validators: []abci.ValidatorUpdate{}, ConsensusParams: DefaultConsensusParams, AppStateBytes: stateBytes, }, ) } return app } // NewTestGenesisState generate genesis state with single validator func NewTestGenesisState(codec codec.Codec) simapp.GenesisState { privVal := mock.NewPV() pubKey, err := privVal.GetPubKey() if err != nil { panic(err) } // create validator set with single validator validator := tmtypes.NewValidator(pubKey, 1) valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) // generate genesis account senderPrivKey := secp256k1.GenPrivKey() acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0) balance := banktypes.Balance{ Address: acc.GetAddress().String(), Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))), } genesisState := NewDefaultGenesisState() return genesisStateWithValSet(codec, genesisState, valSet, []authtypes.GenesisAccount{acc}, balance) } // RandomAccounts creates random accounts with an ethsecp256k1 private key // TODO: replace secp256k1.GenPrivKeyFromSecret() with similar function in go-ethereum func RandomAccounts(r *rand.Rand, n int) []simtypes.Account { accs := make([]simtypes.Account, n) for i := 0; i < n; i++ { // don't need that much entropy for simulation privkeySeed := make([]byte, 15) _, _ = r.Read(privkeySeed) prv := secp256k1.GenPrivKeyFromSecret(privkeySeed) ethPrv := ðsecp256k1.PrivKey{} _ = ethPrv.UnmarshalAmino(prv.Bytes()) // UnmarshalAmino simply copies the bytes and assigns them to ethPrv.Key accs[i].PrivKey = ethPrv accs[i].PubKey = accs[i].PrivKey.PubKey() accs[i].Address = sdk.AccAddress(accs[i].PubKey.Address()) accs[i].ConsKey = ed25519.GenPrivKeyFromSecret(privkeySeed) } return accs } func genesisStateWithValSet(codec codec.Codec, genesisState simapp.GenesisState, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance, ) simapp.GenesisState { // set genesis accounts authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs) genesisState[authtypes.ModuleName] = codec.MustMarshalJSON(authGenesis) validators := make([]stakingtypes.Validator, 0, len(valSet.Validators)) delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators)) bondAmt := sdk.DefaultPowerReduction for _, val := range valSet.Validators { pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey) if err != nil { panic(err) } pkAny, err := codectypes.NewAnyWithValue(pk) if err != nil { panic(err) } validator := stakingtypes.Validator{ OperatorAddress: sdk.ValAddress(val.Address).String(), ConsensusPubkey: pkAny, Jailed: false, Status: stakingtypes.Bonded, Tokens: bondAmt, DelegatorShares: sdk.OneDec(), Description: stakingtypes.Description{}, UnbondingHeight: int64(0), UnbondingTime: time.Unix(0, 0).UTC(), Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), MinSelfDelegation: sdk.ZeroInt(), } validators = append(validators, validator) delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec())) } // set validators and delegations stakingGenesis := stakingtypes.NewGenesisState(stakingtypes.DefaultParams(), validators, delegations) genesisState[stakingtypes.ModuleName] = codec.MustMarshalJSON(stakingGenesis) totalSupply := sdk.NewCoins() for _, b := range balances { // add genesis acc tokens to total supply totalSupply = totalSupply.Add(b.Coins...) } for range delegations { // add delegated tokens to total supply totalSupply = totalSupply.Add(sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)) } // add bonded amount to bonded pool module account balances = append(balances, banktypes.Balance{ Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(), Coins: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)}, }) // update total supply bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{}) genesisState[banktypes.ModuleName] = codec.MustMarshalJSON(bankGenesis) return genesisState }