2020-08-04 18:52:32 +00:00
package client
2020-07-31 21:42:04 +00:00
// DONTCOVER
import (
"bufio"
"encoding/json"
"fmt"
"net"
"os"
"path/filepath"
2021-06-29 17:02:21 +00:00
"github.com/ethereum/go-ethereum/common"
2021-04-18 15:54:18 +00:00
2020-07-31 21:42:04 +00:00
"github.com/spf13/cobra"
tmconfig "github.com/tendermint/tendermint/config"
tmrand "github.com/tendermint/tendermint/libs/rand"
2021-04-17 10:00:07 +00:00
"github.com/tendermint/tendermint/types"
2020-07-31 21:42:04 +00:00
tmtime "github.com/tendermint/tendermint/types/time"
2021-04-17 10:00:07 +00:00
"github.com/cosmos/cosmos-sdk/client"
2020-07-31 21:42:04 +00:00
"github.com/cosmos/cosmos-sdk/client/flags"
2021-04-17 10:00:07 +00:00
"github.com/cosmos/cosmos-sdk/client/tx"
2021-06-29 17:02:21 +00:00
"github.com/cosmos/cosmos-sdk/crypto/keyring"
2021-11-14 13:34:10 +00:00
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdkserver "github.com/cosmos/cosmos-sdk/server"
2021-06-29 17:02:21 +00:00
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
2022-01-18 21:02:10 +00:00
"github.com/cosmos/cosmos-sdk/testutil"
2020-07-31 21:42:04 +00:00
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
2021-04-17 10:00:07 +00:00
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types"
2020-07-31 21:42:04 +00:00
"github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
2021-04-17 10:00:07 +00:00
mintypes "github.com/cosmos/cosmos-sdk/x/mint/types"
2020-07-31 21:42:04 +00:00
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
2021-06-22 10:49:18 +00:00
"github.com/tharsis/ethermint/crypto/hd"
2021-07-28 09:47:29 +00:00
"github.com/tharsis/ethermint/server/config"
2021-11-14 13:34:10 +00:00
srvflags "github.com/tharsis/ethermint/server/flags"
2021-06-29 17:02:21 +00:00
ethermint "github.com/tharsis/ethermint/types"
2021-06-22 10:49:18 +00:00
evmtypes "github.com/tharsis/ethermint/x/evm/types"
2021-11-14 13:34:10 +00:00
"github.com/tharsis/ethermint/testutil/network"
2020-07-31 21:42:04 +00:00
)
var (
2021-11-14 13:34:10 +00:00
flagNodeDirPrefix = "node-dir-prefix"
flagNumValidators = "v"
flagOutputDir = "output-dir"
flagNodeDaemonHome = "node-daemon-home"
flagStartingIPAddress = "starting-ip-address"
flagEnableLogging = "enable-logging"
flagRPCAddress = "rpc.address"
flagAPIAddress = "api.address"
flagPrintMnemonic = "print-mnemonic"
2020-07-31 21:42:04 +00:00
)
2021-11-14 13:34:10 +00:00
type initArgs struct {
algo string
chainID string
keyringBackend string
minGasPrices string
nodeDaemonHome string
nodeDirPrefix string
numValidators int
outputDir string
startingIPAddress string
}
2020-07-31 21:42:04 +00:00
2021-11-14 13:34:10 +00:00
type startArgs struct {
algo string
apiAddress string
chainID string
grpcAddress string
minGasPrices string
outputDir string
rpcAddress string
jsonrpcAddress string
numValidators int
enableLogging bool
printMnemonic bool
}
func addTestnetFlagsToCmd ( cmd * cobra . Command ) {
cmd . Flags ( ) . Int ( flagNumValidators , 4 , "Number of validators to initialize the testnet with" )
cmd . Flags ( ) . StringP ( flagOutputDir , "o" , "./.testnets" , "Directory to store initialization data for the testnet" )
cmd . Flags ( ) . String ( flags . FlagChainID , "" , "genesis file chain-id, if left blank will be randomly created" )
cmd . Flags ( ) . String ( sdkserver . FlagMinGasPrices , fmt . Sprintf ( "0.000006%s" , ethermint . AttoPhoton ) , "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01photino,0.001stake)" )
cmd . Flags ( ) . String ( flags . FlagKeyAlgorithm , string ( hd . EthSecp256k1Type ) , "Key signing algorithm to generate keys for" )
}
// NewTestnetCmd creates a root testnet command with subcommands to run an in-process testnet or initialize
// validator configuration files for running a multi-validator testnet in a separate process
func NewTestnetCmd ( mbm module . BasicManager , genBalIterator banktypes . GenesisBalancesIterator ) * cobra . Command {
testnetCmd := & cobra . Command {
Use : "testnet" ,
Short : "subcommands for starting or configuring local testnets" ,
DisableFlagParsing : true ,
SuggestionsMinimumDistance : 2 ,
RunE : client . ValidateCmd ,
}
testnetCmd . AddCommand ( testnetStartCmd ( ) )
testnetCmd . AddCommand ( testnetInitFilesCmd ( mbm , genBalIterator ) )
return testnetCmd
}
// get cmd to initialize all files for tendermint testnet and application
func testnetInitFilesCmd ( mbm module . BasicManager , genBalIterator banktypes . GenesisBalancesIterator ) * cobra . Command {
2020-07-31 21:42:04 +00:00
cmd := & cobra . Command {
2021-11-14 13:34:10 +00:00
Use : "init-files" ,
Short : "Initialize config directories & files for a multi-validator testnet running locally via separate processes (e.g. Docker Compose or similar)" ,
Long : ` init - files will setup "v" number of directories and populate each with
necessary files ( private validator , genesis , config , etc . ) for running "v" validator nodes .
Booting up a network with these validator folders is intended to be used with Docker Compose ,
or a similar setup where each node has a manually configurable IP address .
2020-07-31 21:42:04 +00:00
2021-11-14 13:34:10 +00:00
Note , strict routability for addresses is turned off in the config file .
2020-07-31 21:42:04 +00:00
2021-11-14 13:34:10 +00:00
Example :
evmosd testnet init - files -- v 4 -- output - dir . / . testnets -- starting - ip - address 192.168 .10 .2
` ,
2020-07-31 21:42:04 +00:00
RunE : func ( cmd * cobra . Command , _ [ ] string ) error {
2021-11-14 13:34:10 +00:00
clientCtx , err := client . GetClientQueryContext ( cmd )
if err != nil {
return err
2021-04-17 10:00:07 +00:00
}
2020-07-31 21:42:04 +00:00
2021-11-14 13:34:10 +00:00
serverCtx := sdkserver . GetServerContextFromCmd ( cmd )
args := initArgs { }
args . outputDir , _ = cmd . Flags ( ) . GetString ( flagOutputDir )
args . keyringBackend , _ = cmd . Flags ( ) . GetString ( flags . FlagKeyringBackend )
args . chainID , _ = cmd . Flags ( ) . GetString ( flags . FlagChainID )
args . minGasPrices , _ = cmd . Flags ( ) . GetString ( sdkserver . FlagMinGasPrices )
args . nodeDirPrefix , _ = cmd . Flags ( ) . GetString ( flagNodeDirPrefix )
args . nodeDaemonHome , _ = cmd . Flags ( ) . GetString ( flagNodeDaemonHome )
args . startingIPAddress , _ = cmd . Flags ( ) . GetString ( flagStartingIPAddress )
args . numValidators , _ = cmd . Flags ( ) . GetInt ( flagNumValidators )
args . algo , _ = cmd . Flags ( ) . GetString ( flags . FlagKeyAlgorithm )
return initTestnetFiles ( clientCtx , cmd , serverCtx . Config , mbm , genBalIterator , args )
2020-07-31 21:42:04 +00:00
} ,
}
2021-11-14 13:34:10 +00:00
addTestnetFlagsToCmd ( cmd )
2020-07-31 21:42:04 +00:00
cmd . Flags ( ) . String ( flagNodeDirPrefix , "node" , "Prefix the directory name for each node with (node results in node0, node1, ...)" )
2021-11-14 13:34:10 +00:00
cmd . Flags ( ) . String ( flagNodeDaemonHome , "evmosd" , "Home directory of the node's daemon configuration" )
cmd . Flags ( ) . String ( flagStartingIPAddress , "192.168.0.1" , "Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)" )
2020-07-31 21:42:04 +00:00
cmd . Flags ( ) . String ( flags . FlagKeyringBackend , flags . DefaultKeyringBackend , "Select keyring's backend (os|file|test)" )
2021-11-14 13:34:10 +00:00
2020-07-31 21:42:04 +00:00
return cmd
}
2021-11-14 13:34:10 +00:00
// get cmd to start multi validator in-process testnet
func testnetStartCmd ( ) * cobra . Command {
cmd := & cobra . Command {
Use : "start" ,
Short : "Launch an in-process multi-validator testnet" ,
Long : ` testnet will launch an in - process multi - validator testnet ,
and generate "v" directories , populated with necessary validator configuration files
( private validator , genesis , config , etc . ) .
Example :
evmosd testnet -- v 4 -- output - dir . / . testnets
` ,
RunE : func ( cmd * cobra . Command , _ [ ] string ) error {
args := startArgs { }
args . outputDir , _ = cmd . Flags ( ) . GetString ( flagOutputDir )
args . chainID , _ = cmd . Flags ( ) . GetString ( flags . FlagChainID )
args . minGasPrices , _ = cmd . Flags ( ) . GetString ( sdkserver . FlagMinGasPrices )
args . numValidators , _ = cmd . Flags ( ) . GetInt ( flagNumValidators )
args . algo , _ = cmd . Flags ( ) . GetString ( flags . FlagKeyAlgorithm )
args . enableLogging , _ = cmd . Flags ( ) . GetBool ( flagEnableLogging )
args . rpcAddress , _ = cmd . Flags ( ) . GetString ( flagRPCAddress )
args . apiAddress , _ = cmd . Flags ( ) . GetString ( flagAPIAddress )
args . grpcAddress , _ = cmd . Flags ( ) . GetString ( srvflags . GRPCAddress )
args . jsonrpcAddress , _ = cmd . Flags ( ) . GetString ( srvflags . JSONRPCAddress )
args . printMnemonic , _ = cmd . Flags ( ) . GetBool ( flagPrintMnemonic )
return startTestnet ( cmd , args )
} ,
}
addTestnetFlagsToCmd ( cmd )
cmd . Flags ( ) . Bool ( flagEnableLogging , false , "Enable INFO logging of tendermint validator nodes" )
cmd . Flags ( ) . String ( flagRPCAddress , "tcp://0.0.0.0:26657" , "the RPC address to listen on" )
cmd . Flags ( ) . String ( flagAPIAddress , "tcp://0.0.0.0:1317" , "the address to listen on for REST API" )
cmd . Flags ( ) . String ( srvflags . GRPCAddress , config . DefaultGRPCAddress , "the gRPC server address to listen on" )
cmd . Flags ( ) . String ( srvflags . JSONRPCAddress , config . DefaultJSONRPCAddress , "the JSON-RPC server address to listen on" )
cmd . Flags ( ) . Bool ( flagPrintMnemonic , true , "print mnemonic of first validator to stdout for manual testing" )
return cmd
}
const nodeDirPerm = 0 o755
// initTestnetFiles initializes testnet files for a testnet to be run in a separate process
func initTestnetFiles (
2021-04-17 10:00:07 +00:00
clientCtx client . Context ,
2020-08-12 14:25:57 +00:00
cmd * cobra . Command ,
2021-04-17 10:00:07 +00:00
nodeConfig * tmconfig . Config ,
2020-08-12 14:25:57 +00:00
mbm module . BasicManager ,
2021-04-17 10:00:07 +00:00
genBalIterator banktypes . GenesisBalancesIterator ,
2021-11-14 13:34:10 +00:00
args initArgs ,
2020-07-31 21:42:04 +00:00
) error {
2020-09-24 17:50:47 +00:00
2021-11-14 13:34:10 +00:00
if args . chainID == "" {
args . chainID = fmt . Sprintf ( "ethermint_%d-1" , tmrand . Int63n ( 9999999999999 ) + 1 )
2020-07-31 21:42:04 +00:00
}
2021-11-14 13:34:10 +00:00
nodeIDs := make ( [ ] string , args . numValidators )
valPubKeys := make ( [ ] cryptotypes . PubKey , args . numValidators )
2020-07-31 21:42:04 +00:00
2021-04-18 15:54:18 +00:00
appConfig := config . DefaultConfig ( )
2021-11-14 13:34:10 +00:00
appConfig . MinGasPrices = args . minGasPrices
2021-04-17 10:00:07 +00:00
appConfig . API . Enable = true
appConfig . Telemetry . Enabled = true
appConfig . Telemetry . PrometheusRetentionTime = 60
appConfig . Telemetry . EnableHostnameLabel = false
2021-11-14 13:34:10 +00:00
appConfig . Telemetry . GlobalLabels = [ ] [ ] string { { "chain_id" , args . chainID } }
2020-07-31 21:42:04 +00:00
var (
2021-04-17 10:00:07 +00:00
genAccounts [ ] authtypes . GenesisAccount
genBalances [ ] banktypes . Balance
2020-07-31 21:42:04 +00:00
genFiles [ ] string
)
inBuf := bufio . NewReader ( cmd . InOrStdin ( ) )
// generate private keys, node IDs, and initial transactions
2021-11-14 13:34:10 +00:00
for i := 0 ; i < args . numValidators ; i ++ {
nodeDirName := fmt . Sprintf ( "%s%d" , args . nodeDirPrefix , i )
nodeDir := filepath . Join ( args . outputDir , nodeDirName , args . nodeDaemonHome )
gentxsDir := filepath . Join ( args . outputDir , "gentxs" )
2020-07-31 21:42:04 +00:00
2021-04-17 10:00:07 +00:00
nodeConfig . SetRoot ( nodeDir )
nodeConfig . RPC . ListenAddress = "tcp://0.0.0.0:26657"
2020-07-31 21:42:04 +00:00
if err := os . MkdirAll ( filepath . Join ( nodeDir , "config" ) , nodeDirPerm ) ; err != nil {
2021-11-14 13:34:10 +00:00
_ = os . RemoveAll ( args . outputDir )
2020-07-31 21:42:04 +00:00
return err
}
2021-04-17 10:00:07 +00:00
nodeConfig . Moniker = nodeDirName
2020-07-31 21:42:04 +00:00
2021-11-14 13:34:10 +00:00
ip , err := getIP ( i , args . startingIPAddress )
if err != nil {
_ = os . RemoveAll ( args . outputDir )
return err
2020-07-31 21:42:04 +00:00
}
2021-04-17 10:00:07 +00:00
nodeIDs [ i ] , valPubKeys [ i ] , err = genutil . InitializeNodeValidatorFiles ( nodeConfig )
2020-07-31 21:42:04 +00:00
if err != nil {
2021-11-14 13:34:10 +00:00
_ = os . RemoveAll ( args . outputDir )
2020-07-31 21:42:04 +00:00
return err
}
memo := fmt . Sprintf ( "%s@%s:26656" , nodeIDs [ i ] , ip )
2021-04-17 10:00:07 +00:00
genFiles = append ( genFiles , nodeConfig . GenesisFile ( ) )
2020-07-31 21:42:04 +00:00
2021-11-14 13:34:10 +00:00
kb , err := keyring . New ( sdk . KeyringServiceName ( ) , args . keyringBackend , nodeDir , inBuf , hd . EthSecp256k1Option ( ) )
2020-07-31 21:42:04 +00:00
if err != nil {
return err
}
2021-04-17 10:00:07 +00:00
keyringAlgos , _ := kb . SupportedAlgorithms ( )
2021-11-14 13:34:10 +00:00
algo , err := keyring . NewSigningAlgoFromString ( args . algo , keyringAlgos )
2021-04-17 10:00:07 +00:00
if err != nil {
return err
}
2020-07-31 21:42:04 +00:00
2022-01-18 21:02:10 +00:00
addr , secret , err := testutil . GenerateSaveCoinKey ( kb , nodeDirName , "" , true , algo )
2020-07-31 21:42:04 +00:00
if err != nil {
2021-11-14 13:34:10 +00:00
_ = os . RemoveAll ( args . outputDir )
2020-07-31 21:42:04 +00:00
return err
}
info := map [ string ] string { "secret" : secret }
cliPrint , err := json . Marshal ( info )
if err != nil {
return err
}
// save private key seed words
2021-11-14 13:34:10 +00:00
if err := network . WriteFile ( fmt . Sprintf ( "%v.json" , "key_seed" ) , nodeDir , cliPrint ) ; err != nil {
2020-07-31 21:42:04 +00:00
return err
}
2021-06-29 17:02:21 +00:00
accStakingTokens := sdk . TokensFromConsensusPower ( 5000 , ethermint . PowerReduction )
2021-11-14 13:34:10 +00:00
coins := sdk . Coins {
sdk . NewCoin ( ethermint . AttoPhoton , accStakingTokens ) ,
}
2020-07-31 21:42:04 +00:00
2021-11-14 13:34:10 +00:00
genBalances = append ( genBalances , banktypes . Balance { Address : addr . String ( ) , Coins : coins . Sort ( ) } )
2021-06-29 17:02:21 +00:00
genAccounts = append ( genAccounts , & ethermint . EthAccount {
2021-04-17 10:00:07 +00:00
BaseAccount : authtypes . NewBaseAccount ( addr , nil , 0 , 0 ) ,
2021-06-29 17:02:21 +00:00
CodeHash : common . BytesToHash ( evmtypes . EmptyCodeHash ) . Hex ( ) ,
2020-07-31 21:42:04 +00:00
} )
2021-06-29 17:02:21 +00:00
valTokens := sdk . TokensFromConsensusPower ( 100 , ethermint . PowerReduction )
2021-04-17 10:00:07 +00:00
createValMsg , err := stakingtypes . NewMsgCreateValidator (
2020-07-31 21:42:04 +00:00
sdk . ValAddress ( addr ) ,
valPubKeys [ i ] ,
2021-11-14 13:34:10 +00:00
sdk . NewCoin ( ethermint . AttoPhoton , valTokens ) ,
2020-07-31 21:42:04 +00:00
stakingtypes . NewDescription ( nodeDirName , "" , "" , "" , "" ) ,
stakingtypes . NewCommissionRates ( sdk . OneDec ( ) , sdk . OneDec ( ) , sdk . OneDec ( ) ) ,
sdk . OneInt ( ) ,
)
if err != nil {
return err
}
2021-04-17 10:00:07 +00:00
txBuilder := clientCtx . TxConfig . NewTxBuilder ( )
if err := txBuilder . SetMsgs ( createValMsg ) ; err != nil {
return err
}
txBuilder . SetMemo ( memo )
txFactory := tx . Factory { }
txFactory = txFactory .
2021-11-14 13:34:10 +00:00
WithChainID ( args . chainID ) .
2021-04-17 10:00:07 +00:00
WithMemo ( memo ) .
WithKeybase ( kb ) .
WithTxConfig ( clientCtx . TxConfig )
2021-11-14 13:34:10 +00:00
if err := tx . Sign ( txFactory , nodeDirName , txBuilder , true ) ; err != nil {
2021-04-17 10:00:07 +00:00
return err
}
txBz , err := clientCtx . TxConfig . TxJSONEncoder ( ) ( txBuilder . GetTx ( ) )
2020-07-31 21:42:04 +00:00
if err != nil {
return err
}
2021-11-14 13:34:10 +00:00
if err := network . WriteFile ( fmt . Sprintf ( "%v.json" , nodeDirName ) , gentxsDir , txBz ) ; err != nil {
return err
}
customAppTemplate , customAppConfig := config . AppConfig ( ethermint . AttoPhoton )
srvconfig . SetConfigTemplate ( customAppTemplate )
if err := sdkserver . InterceptConfigsPreRunHandler ( cmd , customAppTemplate , customAppConfig ) ; err != nil {
2020-07-31 21:42:04 +00:00
return err
}
2021-06-29 17:02:21 +00:00
srvconfig . WriteConfigFile ( filepath . Join ( nodeDir , "config/app.toml" ) , appConfig )
2020-07-31 21:42:04 +00:00
}
2021-11-14 13:34:10 +00:00
if err := initGenFiles ( clientCtx , mbm , args . chainID , ethermint . AttoPhoton , genAccounts , genBalances , genFiles , args . numValidators ) ; err != nil {
2020-07-31 21:42:04 +00:00
return err
}
err := collectGenFiles (
2021-11-14 13:34:10 +00:00
clientCtx , nodeConfig , args . chainID , nodeIDs , valPubKeys , args . numValidators ,
args . outputDir , args . nodeDirPrefix , args . nodeDaemonHome , genBalIterator ,
2020-07-31 21:42:04 +00:00
)
if err != nil {
return err
}
2021-11-14 13:34:10 +00:00
cmd . PrintErrf ( "Successfully initialized %d node directories\n" , args . numValidators )
2020-07-31 21:42:04 +00:00
return nil
}
func initGenFiles (
2021-04-17 10:00:07 +00:00
clientCtx client . Context ,
mbm module . BasicManager ,
chainID ,
coinDenom string ,
genAccounts [ ] authtypes . GenesisAccount ,
genBalances [ ] banktypes . Balance ,
genFiles [ ] string ,
numValidators int ,
2020-07-31 21:42:04 +00:00
) error {
2021-11-14 13:34:10 +00:00
appGenState := mbm . DefaultGenesis ( clientCtx . Codec )
2020-07-31 21:42:04 +00:00
// set the accounts in the genesis state
var authGenState authtypes . GenesisState
2021-08-26 15:45:45 +00:00
clientCtx . Codec . MustUnmarshalJSON ( appGenState [ authtypes . ModuleName ] , & authGenState )
2021-04-17 10:00:07 +00:00
accounts , err := authtypes . PackAccounts ( genAccounts )
if err != nil {
return err
}
authGenState . Accounts = accounts
2021-08-26 15:45:45 +00:00
appGenState [ authtypes . ModuleName ] = clientCtx . Codec . MustMarshalJSON ( & authGenState )
2020-07-31 21:42:04 +00:00
2021-04-17 10:00:07 +00:00
// set the balances in the genesis state
var bankGenState banktypes . GenesisState
2021-08-26 15:45:45 +00:00
clientCtx . Codec . MustUnmarshalJSON ( appGenState [ banktypes . ModuleName ] , & bankGenState )
2021-04-17 10:00:07 +00:00
bankGenState . Balances = genBalances
2021-08-26 15:45:45 +00:00
appGenState [ banktypes . ModuleName ] = clientCtx . Codec . MustMarshalJSON ( & bankGenState )
2020-07-31 21:42:04 +00:00
var stakingGenState stakingtypes . GenesisState
2021-08-26 15:45:45 +00:00
clientCtx . Codec . MustUnmarshalJSON ( appGenState [ stakingtypes . ModuleName ] , & stakingGenState )
2020-07-31 21:42:04 +00:00
2020-09-08 14:39:48 +00:00
stakingGenState . Params . BondDenom = coinDenom
2021-08-26 15:45:45 +00:00
appGenState [ stakingtypes . ModuleName ] = clientCtx . Codec . MustMarshalJSON ( & stakingGenState )
2020-07-31 21:42:04 +00:00
var govGenState govtypes . GenesisState
2021-08-26 15:45:45 +00:00
clientCtx . Codec . MustUnmarshalJSON ( appGenState [ govtypes . ModuleName ] , & govGenState )
2020-07-31 21:42:04 +00:00
2020-09-08 14:39:48 +00:00
govGenState . DepositParams . MinDeposit [ 0 ] . Denom = coinDenom
2021-08-26 15:45:45 +00:00
appGenState [ govtypes . ModuleName ] = clientCtx . Codec . MustMarshalJSON ( & govGenState )
2020-07-31 21:42:04 +00:00
2021-04-17 10:00:07 +00:00
var mintGenState mintypes . GenesisState
2021-08-26 15:45:45 +00:00
clientCtx . Codec . MustUnmarshalJSON ( appGenState [ mintypes . ModuleName ] , & mintGenState )
2020-07-31 21:42:04 +00:00
2020-09-08 14:39:48 +00:00
mintGenState . Params . MintDenom = coinDenom
2021-08-26 15:45:45 +00:00
appGenState [ mintypes . ModuleName ] = clientCtx . Codec . MustMarshalJSON ( & mintGenState )
2020-07-31 21:42:04 +00:00
2021-04-17 10:00:07 +00:00
var crisisGenState crisistypes . GenesisState
2021-08-26 15:45:45 +00:00
clientCtx . Codec . MustUnmarshalJSON ( appGenState [ crisistypes . ModuleName ] , & crisisGenState )
2020-07-31 21:42:04 +00:00
2020-09-08 14:39:48 +00:00
crisisGenState . ConstantFee . Denom = coinDenom
2021-08-26 15:45:45 +00:00
appGenState [ crisistypes . ModuleName ] = clientCtx . Codec . MustMarshalJSON ( & crisisGenState )
2020-07-31 21:42:04 +00:00
2020-09-08 14:39:48 +00:00
var evmGenState evmtypes . GenesisState
2021-08-26 15:45:45 +00:00
clientCtx . Codec . MustUnmarshalJSON ( appGenState [ evmtypes . ModuleName ] , & evmGenState )
2020-09-08 14:39:48 +00:00
evmGenState . Params . EvmDenom = coinDenom
2021-08-26 15:45:45 +00:00
appGenState [ evmtypes . ModuleName ] = clientCtx . Codec . MustMarshalJSON ( & evmGenState )
2020-09-08 14:39:48 +00:00
2021-04-17 10:00:07 +00:00
appGenStateJSON , err := json . MarshalIndent ( appGenState , "" , " " )
2020-07-31 21:42:04 +00:00
if err != nil {
return err
}
2021-04-17 10:00:07 +00:00
genDoc := types . GenesisDoc {
2020-07-31 21:42:04 +00:00
ChainID : chainID ,
AppState : appGenStateJSON ,
Validators : nil ,
}
// generate empty genesis files for each validator and save
for i := 0 ; i < numValidators ; i ++ {
if err := genDoc . SaveAs ( genFiles [ i ] ) ; err != nil {
return err
}
}
return nil
}
func collectGenFiles (
2021-04-17 10:00:07 +00:00
clientCtx client . Context , nodeConfig * tmconfig . Config , chainID string ,
nodeIDs [ ] string , valPubKeys [ ] cryptotypes . PubKey , numValidators int ,
outputDir , nodeDirPrefix , nodeDaemonHome string , genBalIterator banktypes . GenesisBalancesIterator ,
2020-07-31 21:42:04 +00:00
) error {
2021-11-14 13:34:10 +00:00
2020-07-31 21:42:04 +00:00
var appState json . RawMessage
genTime := tmtime . Now ( )
for i := 0 ; i < numValidators ; i ++ {
nodeDirName := fmt . Sprintf ( "%s%d" , nodeDirPrefix , i )
nodeDir := filepath . Join ( outputDir , nodeDirName , nodeDaemonHome )
gentxsDir := filepath . Join ( outputDir , "gentxs" )
2021-04-17 10:00:07 +00:00
nodeConfig . Moniker = nodeDirName
2020-07-31 21:42:04 +00:00
2021-04-17 10:00:07 +00:00
nodeConfig . SetRoot ( nodeDir )
2020-07-31 21:42:04 +00:00
nodeID , valPubKey := nodeIDs [ i ] , valPubKeys [ i ]
2021-04-17 10:00:07 +00:00
initCfg := genutiltypes . NewInitConfig ( chainID , gentxsDir , nodeID , valPubKey )
2020-07-31 21:42:04 +00:00
2021-04-17 10:00:07 +00:00
genDoc , err := types . GenesisDocFromFile ( nodeConfig . GenesisFile ( ) )
2020-07-31 21:42:04 +00:00
if err != nil {
return err
}
2021-08-26 15:45:45 +00:00
nodeAppState , err := genutil . GenAppStateFromConfig ( clientCtx . Codec , clientCtx . TxConfig , nodeConfig , initCfg , * genDoc , genBalIterator )
2020-07-31 21:42:04 +00:00
if err != nil {
return err
}
if appState == nil {
// set the canonical application state (they should not differ)
appState = nodeAppState
}
2021-04-17 10:00:07 +00:00
genFile := nodeConfig . GenesisFile ( )
2020-07-31 21:42:04 +00:00
// overwrite each validator's genesis file to have a canonical genesis time
if err := genutil . ExportGenesisFileWithTime ( genFile , chainID , nil , appState , genTime ) ; err != nil {
return err
}
}
return nil
}
func getIP ( i int , startingIPAddr string ) ( ip string , err error ) {
if len ( startingIPAddr ) == 0 {
2021-11-14 13:34:10 +00:00
ip , err = sdkserver . ExternalIP ( )
2020-07-31 21:42:04 +00:00
if err != nil {
return "" , err
}
return ip , nil
}
return calculateIP ( startingIPAddr , i )
}
func calculateIP ( ip string , i int ) ( string , error ) {
ipv4 := net . ParseIP ( ip ) . To4 ( )
if ipv4 == nil {
return "" , fmt . Errorf ( "%v: non ipv4 address" , ip )
}
for j := 0 ; j < i ; j ++ {
ipv4 [ 3 ] ++
}
return ipv4 . String ( ) , nil
}
2021-11-14 13:34:10 +00:00
// startTestnet starts an in-process testnet
func startTestnet ( cmd * cobra . Command , args startArgs ) error {
networkConfig := network . DefaultConfig ( )
// Default networkConfig.ChainID is random, and we should only override it if chainID provided
// is non-empty
if args . chainID != "" {
networkConfig . ChainID = args . chainID
}
networkConfig . SigningAlgo = args . algo
networkConfig . MinGasPrices = args . minGasPrices
networkConfig . NumValidators = args . numValidators
networkConfig . EnableTMLogging = args . enableLogging
networkConfig . RPCAddress = args . rpcAddress
networkConfig . APIAddress = args . apiAddress
networkConfig . GRPCAddress = args . grpcAddress
networkConfig . JSONRPCAddress = args . jsonrpcAddress
networkConfig . PrintMnemonic = args . printMnemonic
networkLogger := network . NewCLILogger ( cmd )
baseDir := fmt . Sprintf ( "%s/%s" , args . outputDir , networkConfig . ChainID )
if _ , err := os . Stat ( baseDir ) ; ! os . IsNotExist ( err ) {
return fmt . Errorf (
"testnests directory already exists for chain-id '%s': %s, please remove or select a new --chain-id" ,
networkConfig . ChainID , baseDir )
}
2020-07-31 21:42:04 +00:00
2021-11-14 13:34:10 +00:00
testnet , err := network . New ( networkLogger , baseDir , networkConfig )
2020-07-31 21:42:04 +00:00
if err != nil {
return err
}
2021-11-14 13:34:10 +00:00
_ , err = testnet . WaitForHeight ( 1 )
2020-07-31 21:42:04 +00:00
if err != nil {
return err
}
2021-11-14 13:34:10 +00:00
cmd . Println ( "press the Enter Key to terminate" )
2021-11-25 15:12:57 +00:00
_ , err = fmt . Scanln ( ) // wait for Enter Key
if err != nil {
return err
}
2021-11-14 13:34:10 +00:00
testnet . Cleanup ( )
2020-07-31 21:42:04 +00:00
return nil
}