feat: simd runs in-process testnet by default (#9246)

<!-- < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < ☺
v                               ✰  Thanks for creating a PR! ✰
v    Before smashing the submit button please review the checkboxes.
v    If a checkbox is n/a - please still include it but + a little note why
☺ > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >  -->

## Description

ref: #9183 

After some more recent conversations w/ @aaronc, I decided to go back to his original proposal of setting up a subcommand for running in-process testnets. 

This PR splits the `simd testnet` command into two subcommands:
- `simd testnet start` which starts an in-process n-node testnet
- `simd testnet init-files` which sets up configuration & genesis files for an n-node testnet to be run as separate processes (one per node, most likely via Docker Compose)


---

Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.

- [x] Targeted PR against correct branch (see [CONTRIBUTING.md](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [x] Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
- [x] Code follows the [module structure standards](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/structure.md). - **n/a**
- [ ] Wrote unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [x] Updated relevant documentation (`docs/`) or specification (`x/<module>/spec/`) - **see #9411**
- [x] Added relevant `godoc` [comments](https://blog.golang.org/godoc-documenting-go-code).
- [x] Added a relevant changelog entry to the `Unreleased` section in `CHANGELOG.md`
- [x] Re-reviewed `Files changed` in the Github PR explorer
- [ ] Review `Codecov Report` in the comment section below once CI passes
This commit is contained in:
Cory 2021-06-29 12:41:55 +02:00 committed by GitHub
parent 7a8b273d93
commit aef416f91e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 526 additions and 190 deletions

2
.gitignore vendored
View File

@ -26,7 +26,7 @@ artifacts
# Data - ideally these don't exist # Data - ideally these don't exist
baseapp/data/* baseapp/data/*
client/lcd/keys/* client/lcd/keys/*
mytestnet .testnets
# Testing # Testing
coverage.txt coverage.txt

View File

@ -46,6 +46,11 @@ Ref: https://keepachangelog.com/en/1.0.0/
* [\#9427](https://github.com/cosmos/cosmos-sdk/pull/9427) Move simapp `FundAccount` and `FundModuleAccount` to `x/bank/testutil` * [\#9427](https://github.com/cosmos/cosmos-sdk/pull/9427) Move simapp `FundAccount` and `FundModuleAccount` to `x/bank/testutil`
* (client/tx) [\#9421](https://github.com/cosmos/cosmos-sdk/pull/9421/) `BuildUnsignedTx`, `BuildSimTx`, `PrintUnsignedStdTx` functions are moved to * (client/tx) [\#9421](https://github.com/cosmos/cosmos-sdk/pull/9421/) `BuildUnsignedTx`, `BuildSimTx`, `PrintUnsignedStdTx` functions are moved to
the Tx Factory as methods. the Tx Factory as methods.
* [\#9246](https://github.com/cosmos/cosmos-sdk/pull/9246) The `New` method for the network package now returns an error.
### CLI Breaking Changes
* [\#9246](https://github.com/cosmos/cosmos-sdk/pull/9246) Removed the CLI flag `--setup-config-only` from the `testnet` command and added the subcommand `init-files`.
### Improvements ### Improvements
* (cli) [\#9593](https://github.com/cosmos/cosmos-sdk/pull/9593) Check if chain-id is blank before verifying signatures in multisign and error. * (cli) [\#9593](https://github.com/cosmos/cosmos-sdk/pull/9593) Check if chain-id is blank before verifying signatures in multisign and error.

View File

@ -475,16 +475,16 @@ proto-update-deps:
### Localnet ### ### Localnet ###
############################################################################### ###############################################################################
# Run a 4-node testnet locally # Run a 4-node testnet locally via docker compose
localnet-start: build-linux localnet-stop localnet-start: build-linux localnet-stop
$(if $(shell $(DOCKER) inspect -f '{{ .Id }}' cosmossdk/simd-env 2>/dev/null),$(info found image cosmossdk/simd-env),$(MAKE) -C contrib/images simd-env) $(if $(shell $(DOCKER) inspect -f '{{ .Id }}' cosmossdk/simd-env 2>/dev/null),$(info found image cosmossdk/simd-env),$(MAKE) -C contrib/images simd-env)
if ! [ -f build/node0/simd/config/genesis.json ]; then $(DOCKER) run --rm \ if ! test -f build/node0/simd/config/genesis.json; then $(DOCKER) run --rm \
--user $(shell id -u):$(shell id -g) \ --user $(shell id -u):$(shell id -g) \
-v $(BUILDDIR):/simd:Z \ -v $(BUILDDIR):/simd:Z \
-v /etc/group:/etc/group:ro \ -v /etc/group:/etc/group:ro \
-v /etc/passwd:/etc/passwd:ro \ -v /etc/passwd:/etc/passwd:ro \
-v /etc/shadow:/etc/shadow:ro \ -v /etc/shadow:/etc/shadow:ro \
cosmossdk/simd-env testnet --v 4 -o . --starting-ip-address 192.168.10.2 --keyring-backend=test ; fi cosmossdk/simd-env testnet init-files --v 4 -o . --starting-ip-address 192.168.10.2 --keyring-backend=test ; fi
docker-compose up -d docker-compose up -d
localnet-stop: localnet-stop:

View File

@ -105,7 +105,8 @@ func TestCLIQueryConn(t *testing.T) {
cfg := network.DefaultConfig() cfg := network.DefaultConfig()
cfg.NumValidators = 1 cfg.NumValidators = 1
n := network.New(t, cfg) n, err := network.New(t, t.TempDir(), cfg)
require.NoError(t, err)
defer n.Cleanup() defer n.Cleanup()
testClient := testdata.NewQueryClient(n.Validators[0].ClientCtx) testClient := testdata.NewQueryClient(n.Validators[0].ClientCtx)

View File

@ -32,11 +32,12 @@ func (s *IntegrationTestSuite) SetupSuite() {
cfg.NumValidators = 1 cfg.NumValidators = 1
s.cfg = cfg s.cfg = cfg
s.network = network.New(s.T(), cfg)
s.Require().NotNil(s.network) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err := s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
s.queryClient = tmservice.NewServiceClient(s.network.Validators[0].ClientCtx) s.queryClient = tmservice.NewServiceClient(s.network.Validators[0].ClientCtx)

View File

@ -27,10 +27,11 @@ type IntegrationTestSuite struct {
func (s *IntegrationTestSuite) SetupSuite() { func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite") s.T().Log("setting up integration test suite")
s.network = network.New(s.T(), network.DefaultConfig()) var err error
s.Require().NotNil(s.network) s.network, err = network.New(s.T(), s.T().TempDir(), network.DefaultConfig())
s.Require().NoError(err)
_, err := s.network.WaitForHeight(2) _, err = s.network.WaitForHeight(2)
s.Require().NoError(err) s.Require().NoError(err)
} }

View File

@ -23,8 +23,9 @@ type IntegrationTestSuite struct {
func (s *IntegrationTestSuite) SetupSuite() { func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite") s.T().Log("setting up integration test suite")
s.network = network.New(s.T(), network.DefaultConfig()) var err error
s.Require().NotNil(s.network) s.network, err = network.New(s.T(), s.T().TempDir(), network.DefaultConfig())
s.Require().NoError(err)
s.Require().NoError(s.network.WaitForNextBlock()) s.Require().NoError(s.network.WaitForNextBlock())
} }

View File

@ -45,10 +45,12 @@ func (s *GRPCWebTestSuite) SetupSuite() {
cfg := network.DefaultConfig() cfg := network.DefaultConfig()
cfg.NumValidators = 1 cfg.NumValidators = 1
s.cfg = cfg s.cfg = cfg
s.network = network.New(s.T(), s.cfg)
s.Require().NotNil(s.network)
_, err := s.network.WaitForHeight(2) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(2)
s.Require().NoError(err) s.Require().NoError(err)
s.protoCdc = codec.NewProtoCodec(s.cfg.InterfaceRegistry) s.protoCdc = codec.NewProtoCodec(s.cfg.InterfaceRegistry)

View File

@ -48,10 +48,12 @@ func (s *IntegrationTestSuite) SetupSuite() {
s.app = simapp.Setup(false) s.app = simapp.Setup(false)
s.cfg = network.DefaultConfig() s.cfg = network.DefaultConfig()
s.cfg.NumValidators = 1 s.cfg.NumValidators = 1
s.network = network.New(s.T(), s.cfg)
s.Require().NotNil(s.network)
_, err := s.network.WaitForHeight(2) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(2)
s.Require().NoError(err) s.Require().NoError(err)
val0 := s.network.Validators[0] val0 := s.network.Validators[0]

View File

@ -146,7 +146,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) {
genutilcli.ValidateGenesisCmd(simapp.ModuleBasics), genutilcli.ValidateGenesisCmd(simapp.ModuleBasics),
AddGenesisAccountCmd(simapp.DefaultNodeHome), AddGenesisAccountCmd(simapp.DefaultNodeHome),
tmcli.NewCompletionCmd(rootCmd, true), tmcli.NewCompletionCmd(rootCmd, true),
testnetCmd(simapp.ModuleBasics, banktypes.GenesisBalancesIterator{}), NewTestnetCmd(simapp.ModuleBasics, banktypes.GenesisBalancesIterator{}),
debug.Cmd(), debug.Cmd(),
config.Cmd(), config.Cmd(),
) )

View File

@ -25,6 +25,7 @@ import (
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server"
srvconfig "github.com/cosmos/cosmos-sdk/server/config" srvconfig "github.com/cosmos/cosmos-sdk/server/config"
"github.com/cosmos/cosmos-sdk/testutil/network"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/types/module"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
@ -40,20 +41,78 @@ var (
flagOutputDir = "output-dir" flagOutputDir = "output-dir"
flagNodeDaemonHome = "node-daemon-home" flagNodeDaemonHome = "node-daemon-home"
flagStartingIPAddress = "starting-ip-address" flagStartingIPAddress = "starting-ip-address"
flagEnableLogging = "enable-logging"
flagGRPCAddress = "grpc.address"
flagRPCAddress = "rpc.address"
flagAPIAddress = "api.address"
flagPrintMnemonic = "print-mnemonic"
) )
type initArgs struct {
algo string
chainID string
keyringBackend string
minGasPrices string
nodeDaemonHome string
nodeDirPrefix string
numValidators int
outputDir string
startingIPAddress string
}
type startArgs struct {
algo string
apiAddress string
chainID string
enableLogging bool
grpcAddress string
minGasPrices string
numValidators int
outputDir string
printMnemonic bool
rpcAddress string
}
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(server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom), "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.Secp256k1Type), "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 // get cmd to initialize all files for tendermint testnet and application
func testnetCmd(mbm module.BasicManager, genBalIterator banktypes.GenesisBalancesIterator) *cobra.Command { func testnetInitFilesCmd(mbm module.BasicManager, genBalIterator banktypes.GenesisBalancesIterator) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "testnet", Use: "init-files",
Short: "Initialize files for a simapp testnet", Short: "Initialize config directories & files for a multi-validator testnet running locally via separate processes (e.g. Docker Compose or similar)",
Long: `testnet will create "v" number of directories and populate each with Long: `init-files will setup "v" number of directories and populate each with
necessary files (private validator, genesis, config, etc.). 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.
Note, strict routability for addresses is turned off in the config file. Note, strict routability for addresses is turned off in the config file.
Example: Example:
simd testnet --v 4 --output-dir ./output --starting-ip-address 192.168.10.2 simd testnet init-files --v 4 --output-dir ./.testnets --starting-ip-address 192.168.10.2
`, `,
RunE: func(cmd *cobra.Command, _ []string) error { RunE: func(cmd *cobra.Command, _ []string) error {
clientCtx, err := client.GetClientQueryContext(cmd) clientCtx, err := client.GetClientQueryContext(cmd)
@ -64,70 +123,97 @@ Example:
serverCtx := server.GetServerContextFromCmd(cmd) serverCtx := server.GetServerContextFromCmd(cmd)
config := serverCtx.Config config := serverCtx.Config
outputDir, _ := cmd.Flags().GetString(flagOutputDir) args := initArgs{}
keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend) args.outputDir, _ = cmd.Flags().GetString(flagOutputDir)
chainID, _ := cmd.Flags().GetString(flags.FlagChainID) args.keyringBackend, _ = cmd.Flags().GetString(flags.FlagKeyringBackend)
minGasPrices, _ := cmd.Flags().GetString(server.FlagMinGasPrices) args.chainID, _ = cmd.Flags().GetString(flags.FlagChainID)
nodeDirPrefix, _ := cmd.Flags().GetString(flagNodeDirPrefix) args.minGasPrices, _ = cmd.Flags().GetString(server.FlagMinGasPrices)
nodeDaemonHome, _ := cmd.Flags().GetString(flagNodeDaemonHome) args.nodeDirPrefix, _ = cmd.Flags().GetString(flagNodeDirPrefix)
startingIPAddress, _ := cmd.Flags().GetString(flagStartingIPAddress) args.nodeDaemonHome, _ = cmd.Flags().GetString(flagNodeDaemonHome)
numValidators, _ := cmd.Flags().GetInt(flagNumValidators) args.startingIPAddress, _ = cmd.Flags().GetString(flagStartingIPAddress)
algo, _ := cmd.Flags().GetString(flags.FlagKeyAlgorithm) args.numValidators, _ = cmd.Flags().GetInt(flagNumValidators)
args.algo, _ = cmd.Flags().GetString(flags.FlagKeyAlgorithm)
return initTestnetFiles(clientCtx, cmd, config, mbm, genBalIterator, args)
return InitTestnet(
clientCtx, cmd, config, mbm, genBalIterator, outputDir, chainID, minGasPrices,
nodeDirPrefix, nodeDaemonHome, startingIPAddress, keyringBackend, algo, numValidators,
)
}, },
} }
cmd.Flags().Int(flagNumValidators, 4, "Number of validators to initialize the testnet with") addTestnetFlagsToCmd(cmd)
cmd.Flags().StringP(flagOutputDir, "o", "./mytestnet", "Directory to store initialization data for the testnet")
cmd.Flags().String(flagNodeDirPrefix, "node", "Prefix the directory name for each node with (node results in node0, node1, ...)") cmd.Flags().String(flagNodeDirPrefix, "node", "Prefix the directory name for each node with (node results in node0, node1, ...)")
cmd.Flags().String(flagNodeDaemonHome, "simd", "Home directory of the node's daemon configuration") cmd.Flags().String(flagNodeDaemonHome, "simd", "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, ...)") 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, ...)")
cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
cmd.Flags().String(server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom), "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.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)") cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
cmd.Flags().String(flags.FlagKeyAlgorithm, string(hd.Secp256k1Type), "Key signing algorithm to generate keys for")
return cmd return cmd
} }
// 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:
simd 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(server.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(flagGRPCAddress)
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(flagGRPCAddress, "0.0.0.0:9090", "the gRPC server address to listen on")
cmd.Flags().Bool(flagPrintMnemonic, true, "print mnemonic of first validator to stdout for manual testing")
return cmd
}
const nodeDirPerm = 0755 const nodeDirPerm = 0755
// Initialize the testnet // initTestnetFiles initializes testnet files for a testnet to be run in a separate process
func InitTestnet( func initTestnetFiles(
clientCtx client.Context, clientCtx client.Context,
cmd *cobra.Command, cmd *cobra.Command,
nodeConfig *tmconfig.Config, nodeConfig *tmconfig.Config,
mbm module.BasicManager, mbm module.BasicManager,
genBalIterator banktypes.GenesisBalancesIterator, genBalIterator banktypes.GenesisBalancesIterator,
outputDir, args initArgs,
chainID,
minGasPrices,
nodeDirPrefix,
nodeDaemonHome,
startingIPAddress,
keyringBackend,
algoStr string,
numValidators int,
) error { ) error {
if chainID == "" { if args.chainID == "" {
chainID = "chain-" + tmrand.NewRand().Str(6) args.chainID = "chain-" + tmrand.NewRand().Str(6)
} }
nodeIDs := make([]string, numValidators) nodeIDs := make([]string, args.numValidators)
valPubKeys := make([]cryptotypes.PubKey, numValidators) valPubKeys := make([]cryptotypes.PubKey, args.numValidators)
simappConfig := srvconfig.DefaultConfig() simappConfig := srvconfig.DefaultConfig()
simappConfig.MinGasPrices = minGasPrices simappConfig.MinGasPrices = args.minGasPrices
simappConfig.API.Enable = true simappConfig.API.Enable = true
simappConfig.Telemetry.Enabled = true simappConfig.Telemetry.Enabled = true
simappConfig.Telemetry.PrometheusRetentionTime = 60 simappConfig.Telemetry.PrometheusRetentionTime = 60
simappConfig.Telemetry.EnableHostnameLabel = false simappConfig.Telemetry.EnableHostnameLabel = false
simappConfig.Telemetry.GlobalLabels = [][]string{{"chain_id", chainID}} simappConfig.Telemetry.GlobalLabels = [][]string{{"chain_id", args.chainID}}
var ( var (
genAccounts []authtypes.GenesisAccount genAccounts []authtypes.GenesisAccount
@ -137,50 +223,50 @@ func InitTestnet(
inBuf := bufio.NewReader(cmd.InOrStdin()) inBuf := bufio.NewReader(cmd.InOrStdin())
// generate private keys, node IDs, and initial transactions // generate private keys, node IDs, and initial transactions
for i := 0; i < numValidators; i++ { for i := 0; i < args.numValidators; i++ {
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i) nodeDirName := fmt.Sprintf("%s%d", args.nodeDirPrefix, i)
nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome) nodeDir := filepath.Join(args.outputDir, nodeDirName, args.nodeDaemonHome)
gentxsDir := filepath.Join(outputDir, "gentxs") gentxsDir := filepath.Join(args.outputDir, "gentxs")
nodeConfig.SetRoot(nodeDir) nodeConfig.SetRoot(nodeDir)
nodeConfig.RPC.ListenAddress = "tcp://0.0.0.0:26657" nodeConfig.RPC.ListenAddress = "tcp://0.0.0.0:26657"
if err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm); err != nil { if err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm); err != nil {
_ = os.RemoveAll(outputDir) _ = os.RemoveAll(args.outputDir)
return err return err
} }
nodeConfig.Moniker = nodeDirName nodeConfig.Moniker = nodeDirName
ip, err := getIP(i, startingIPAddress) ip, err := getIP(i, args.startingIPAddress)
if err != nil { if err != nil {
_ = os.RemoveAll(outputDir) _ = os.RemoveAll(args.outputDir)
return err return err
} }
nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(nodeConfig) nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(nodeConfig)
if err != nil { if err != nil {
_ = os.RemoveAll(outputDir) _ = os.RemoveAll(args.outputDir)
return err return err
} }
memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip) memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip)
genFiles = append(genFiles, nodeConfig.GenesisFile()) genFiles = append(genFiles, nodeConfig.GenesisFile())
kb, err := keyring.New(sdk.KeyringServiceName(), keyringBackend, nodeDir, inBuf) kb, err := keyring.New(sdk.KeyringServiceName(), args.keyringBackend, nodeDir, inBuf)
if err != nil { if err != nil {
return err return err
} }
keyringAlgos, _ := kb.SupportedAlgorithms() keyringAlgos, _ := kb.SupportedAlgorithms()
algo, err := keyring.NewSigningAlgoFromString(algoStr, keyringAlgos) algo, err := keyring.NewSigningAlgoFromString(args.algo, keyringAlgos)
if err != nil { if err != nil {
return err return err
} }
addr, secret, err := server.GenerateSaveCoinKey(kb, nodeDirName, true, algo) addr, secret, err := server.GenerateSaveCoinKey(kb, nodeDirName, true, algo)
if err != nil { if err != nil {
_ = os.RemoveAll(outputDir) _ = os.RemoveAll(args.outputDir)
return err return err
} }
@ -228,7 +314,7 @@ func InitTestnet(
txFactory := tx.Factory{} txFactory := tx.Factory{}
txFactory = txFactory. txFactory = txFactory.
WithChainID(chainID). WithChainID(args.chainID).
WithMemo(memo). WithMemo(memo).
WithKeybase(kb). WithKeybase(kb).
WithTxConfig(clientCtx.TxConfig) WithTxConfig(clientCtx.TxConfig)
@ -249,19 +335,19 @@ func InitTestnet(
srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), simappConfig) srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), simappConfig)
} }
if err := initGenFiles(clientCtx, mbm, chainID, genAccounts, genBalances, genFiles, numValidators); err != nil { if err := initGenFiles(clientCtx, mbm, args.chainID, genAccounts, genBalances, genFiles, args.numValidators); err != nil {
return err return err
} }
err := collectGenFiles( err := collectGenFiles(
clientCtx, nodeConfig, chainID, nodeIDs, valPubKeys, numValidators, clientCtx, nodeConfig, args.chainID, nodeIDs, valPubKeys, args.numValidators,
outputDir, nodeDirPrefix, nodeDaemonHome, genBalIterator, args.outputDir, args.nodeDirPrefix, args.nodeDaemonHome, genBalIterator,
) )
if err != nil { if err != nil {
return err return err
} }
cmd.PrintErrf("Successfully initialized %d node directories\n", numValidators) cmd.PrintErrf("Successfully initialized %d node directories\n", args.numValidators)
return nil return nil
} }
@ -401,3 +487,42 @@ func writeFile(name string, dir string, contents []byte) error {
return nil return nil
} }
// 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.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)
}
testnet, err := network.New(networkLogger, baseDir, networkConfig)
if err != nil {
return err
}
testnet.WaitForHeight(1)
cmd.Println("press the Enter Key to terminate")
fmt.Scanln() // wait for Enter Key
testnet.Cleanup()
return nil
}

View File

@ -36,7 +36,7 @@ func Test_TestnetCmd(t *testing.T) {
ctx := context.Background() ctx := context.Background()
ctx = context.WithValue(ctx, server.ServerContextKey, serverCtx) ctx = context.WithValue(ctx, server.ServerContextKey, serverCtx)
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx) ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
cmd := testnetCmd(simapp.ModuleBasics, banktypes.GenesisBalancesIterator{}) cmd := testnetInitFilesCmd(simapp.ModuleBasics, banktypes.GenesisBalancesIterator{})
cmd.SetArgs([]string{fmt.Sprintf("--%s=test", flags.FlagKeyringBackend), fmt.Sprintf("--output-dir=%s", home)}) cmd.SetArgs([]string{fmt.Sprintf("--%s=test", flags.FlagKeyringBackend), fmt.Sprintf("--output-dir=%s", home)})
err = cmd.ExecuteContext(ctx) err = cmd.ExecuteContext(ctx)
require.NoError(t, err) require.NoError(t, err)

View File

@ -6,16 +6,16 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"sync" "sync"
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/require" "github.com/spf13/cobra"
tmcfg "github.com/tendermint/tendermint/config" tmcfg "github.com/tendermint/tendermint/config"
tmflags "github.com/tendermint/tendermint/libs/cli/flags" tmflags "github.com/tendermint/tendermint/libs/cli/flags"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
@ -87,10 +87,14 @@ type Config struct {
StakingTokens sdk.Int // the amount of tokens each validator has available to stake StakingTokens sdk.Int // the amount of tokens each validator has available to stake
BondedTokens sdk.Int // the amount of tokens each validator stakes BondedTokens sdk.Int // the amount of tokens each validator stakes
PruningStrategy string // the pruning strategy each validator will have PruningStrategy string // the pruning strategy each validator will have
EnableLogging bool // enable Tendermint logging to STDOUT EnableTMLogging bool // enable Tendermint logging to STDOUT
CleanupDir bool // remove base temporary directory during cleanup CleanupDir bool // remove base temporary directory during cleanup
SigningAlgo string // signing algorithm for keys SigningAlgo string // signing algorithm for keys
KeyringOptions []keyring.Option KeyringOptions []keyring.Option // keyring configuration options
RPCAddress string // RPC listen address (including port)
APIAddress string // REST API listen address (including port)
GRPCAddress string // GRPC server listen address (including port)
PrintMnemonic bool // print the mnemonic of first validator as log output for testing
} }
// DefaultConfig returns a sane default configuration suitable for nearly all // DefaultConfig returns a sane default configuration suitable for nearly all
@ -118,6 +122,7 @@ func DefaultConfig() Config {
CleanupDir: true, CleanupDir: true,
SigningAlgo: string(hd.Secp256k1Type), SigningAlgo: string(hd.Secp256k1Type),
KeyringOptions: []keyring.Option{}, KeyringOptions: []keyring.Option{},
PrintMnemonic: false,
} }
} }
@ -133,7 +138,7 @@ type (
// to create networks. In addition, only the first validator will have a valid // to create networks. In addition, only the first validator will have a valid
// RPC and API server/client. // RPC and API server/client.
Network struct { Network struct {
T *testing.T Logger Logger
BaseDir string BaseDir string
Validators []*Validator Validators []*Validator
@ -165,24 +170,46 @@ type (
} }
) )
// New creates a new Network for integration tests. // Logger is a network logger interface that exposes testnet-level Log() methods for an in-process testing network
func New(t *testing.T, cfg Config) *Network { // This is not to be confused with logging that may happen at an individual node or validator level
type Logger interface {
Log(args ...interface{})
Logf(format string, args ...interface{})
}
var _ Logger = (*testing.T)(nil)
var _ Logger = (*CLILogger)(nil)
type CLILogger struct {
cmd *cobra.Command
}
func (s CLILogger) Log(args ...interface{}) {
s.cmd.Println(args...)
}
func (s CLILogger) Logf(format string, args ...interface{}) {
s.cmd.Printf(format, args...)
}
func NewCLILogger(cmd *cobra.Command) CLILogger {
return CLILogger{cmd}
}
// New creates a new Network for integration tests or in-process testnets run via the CLI
func New(l Logger, baseDir string, cfg Config) (*Network, error) {
// only one caller/test can create and use a network at a time // only one caller/test can create and use a network at a time
t.Log("acquiring test network lock") l.Log("acquiring test network lock")
lock.Lock() lock.Lock()
baseDir, err := ioutil.TempDir(t.TempDir(), cfg.ChainID)
require.NoError(t, err)
t.Logf("created temporary directory: %s", baseDir)
network := &Network{ network := &Network{
T: t, Logger: l,
BaseDir: baseDir, BaseDir: baseDir,
Validators: make([]*Validator, cfg.NumValidators), Validators: make([]*Validator, cfg.NumValidators),
Config: cfg, Config: cfg,
} }
t.Log("preparing test network...") l.Logf("preparing test network with chain-id \"%s\"\n", cfg.ChainID)
monikers := make([]string, cfg.NumValidators) monikers := make([]string, cfg.NumValidators)
nodeIDs := make([]string, cfg.NumValidators) nodeIDs := make([]string, cfg.NumValidators)
@ -215,32 +242,56 @@ func New(t *testing.T, cfg Config) *Network {
tmCfg.RPC.ListenAddress = "" tmCfg.RPC.ListenAddress = ""
appCfg.GRPC.Enable = false appCfg.GRPC.Enable = false
appCfg.GRPCWeb.Enable = false appCfg.GRPCWeb.Enable = false
apiListenAddr := ""
if i == 0 { if i == 0 {
apiListenAddr, _, err := server.FreeTCPAddr() if cfg.APIAddress != "" {
require.NoError(t, err) apiListenAddr = cfg.APIAddress
appCfg.API.Address = apiListenAddr } else {
var err error
apiListenAddr, _, err = server.FreeTCPAddr()
if err != nil {
return nil, err
}
}
appCfg.API.Address = apiListenAddr
apiURL, err := url.Parse(apiListenAddr) apiURL, err := url.Parse(apiListenAddr)
require.NoError(t, err) if err != nil {
return nil, err
}
apiAddr = fmt.Sprintf("http://%s:%s", apiURL.Hostname(), apiURL.Port()) apiAddr = fmt.Sprintf("http://%s:%s", apiURL.Hostname(), apiURL.Port())
rpcAddr, _, err := server.FreeTCPAddr() if cfg.RPCAddress != "" {
require.NoError(t, err) tmCfg.RPC.ListenAddress = cfg.RPCAddress
tmCfg.RPC.ListenAddress = rpcAddr } else {
rpcAddr, _, err := server.FreeTCPAddr()
if err != nil {
return nil, err
}
tmCfg.RPC.ListenAddress = rpcAddr
}
_, grpcPort, err := server.FreeTCPAddr() if cfg.GRPCAddress != "" {
require.NoError(t, err) appCfg.GRPC.Address = cfg.GRPCAddress
appCfg.GRPC.Address = fmt.Sprintf("0.0.0.0:%s", grpcPort) } else {
_, grpcPort, err := server.FreeTCPAddr()
if err != nil {
return nil, err
}
appCfg.GRPC.Address = fmt.Sprintf("0.0.0.0:%s", grpcPort)
}
appCfg.GRPC.Enable = true appCfg.GRPC.Enable = true
_, grpcWebPort, err := server.FreeTCPAddr() _, grpcWebPort, err := server.FreeTCPAddr()
require.NoError(t, err) if err != nil {
return nil, err
}
appCfg.GRPCWeb.Address = fmt.Sprintf("0.0.0.0:%s", grpcWebPort) appCfg.GRPCWeb.Address = fmt.Sprintf("0.0.0.0:%s", grpcWebPort)
appCfg.GRPCWeb.Enable = true appCfg.GRPCWeb.Enable = true
} }
logger := log.NewNopLogger() logger := log.NewNopLogger()
if cfg.EnableLogging { if cfg.EnableTMLogging {
logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout))
logger, _ = tmflags.ParseLogLevel("info", logger, tmcfg.DefaultLogLevel) logger, _ = tmflags.ParseLogLevel("info", logger, tmcfg.DefaultLogLevel)
} }
@ -252,44 +303,74 @@ func New(t *testing.T, cfg Config) *Network {
clientDir := filepath.Join(network.BaseDir, nodeDirName, "simcli") clientDir := filepath.Join(network.BaseDir, nodeDirName, "simcli")
gentxsDir := filepath.Join(network.BaseDir, "gentxs") gentxsDir := filepath.Join(network.BaseDir, "gentxs")
require.NoError(t, os.MkdirAll(filepath.Join(nodeDir, "config"), 0755)) err := os.MkdirAll(filepath.Join(nodeDir, "config"), 0755)
require.NoError(t, os.MkdirAll(clientDir, 0755)) if err != nil {
return nil, err
}
err = os.MkdirAll(clientDir, 0755)
if err != nil {
return nil, err
}
tmCfg.SetRoot(nodeDir) tmCfg.SetRoot(nodeDir)
tmCfg.Moniker = nodeDirName tmCfg.Moniker = nodeDirName
monikers[i] = nodeDirName monikers[i] = nodeDirName
proxyAddr, _, err := server.FreeTCPAddr() proxyAddr, _, err := server.FreeTCPAddr()
require.NoError(t, err) if err != nil {
return nil, err
}
tmCfg.ProxyApp = proxyAddr tmCfg.ProxyApp = proxyAddr
p2pAddr, _, err := server.FreeTCPAddr() p2pAddr, _, err := server.FreeTCPAddr()
require.NoError(t, err) if err != nil {
return nil, err
}
tmCfg.P2P.ListenAddress = p2pAddr tmCfg.P2P.ListenAddress = p2pAddr
tmCfg.P2P.AddrBookStrict = false tmCfg.P2P.AddrBookStrict = false
tmCfg.P2P.AllowDuplicateIP = true tmCfg.P2P.AllowDuplicateIP = true
nodeID, pubKey, err := genutil.InitializeNodeValidatorFiles(tmCfg) nodeID, pubKey, err := genutil.InitializeNodeValidatorFiles(tmCfg)
require.NoError(t, err) if err != nil {
return nil, err
}
nodeIDs[i] = nodeID nodeIDs[i] = nodeID
valPubKeys[i] = pubKey valPubKeys[i] = pubKey
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, cfg.KeyringOptions...) kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, cfg.KeyringOptions...)
require.NoError(t, err) if err != nil {
return nil, err
}
keyringAlgos, _ := kb.SupportedAlgorithms() keyringAlgos, _ := kb.SupportedAlgorithms()
algo, err := keyring.NewSigningAlgoFromString(cfg.SigningAlgo, keyringAlgos) algo, err := keyring.NewSigningAlgoFromString(cfg.SigningAlgo, keyringAlgos)
require.NoError(t, err) if err != nil {
return nil, err
}
addr, secret, err := server.GenerateSaveCoinKey(kb, nodeDirName, true, algo) addr, secret, err := server.GenerateSaveCoinKey(kb, nodeDirName, true, algo)
require.NoError(t, err) if err != nil {
return nil, err
}
// if PrintMnemonic is set to true, we print the first validator node's secret to the network's logger
// for debugging and manual testing
if cfg.PrintMnemonic && i == 0 {
printMnemonic(l, secret)
}
info := map[string]string{"secret": secret} info := map[string]string{"secret": secret}
infoBz, err := json.Marshal(info) infoBz, err := json.Marshal(info)
require.NoError(t, err) if err != nil {
return nil, err
}
// save private key seed words // save private key seed words
require.NoError(t, writeFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, infoBz)) err = writeFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, infoBz)
if err != nil {
return nil, err
}
balances := sdk.NewCoins( balances := sdk.NewCoins(
sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), cfg.AccountTokens), sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), cfg.AccountTokens),
@ -301,7 +382,9 @@ func New(t *testing.T, cfg Config) *Network {
genAccounts = append(genAccounts, authtypes.NewBaseAccount(addr, nil, 0, 0)) genAccounts = append(genAccounts, authtypes.NewBaseAccount(addr, nil, 0, 0))
commission, err := sdk.NewDecFromStr("0.5") commission, err := sdk.NewDecFromStr("0.5")
require.NoError(t, err) if err != nil {
return nil, err
}
createValMsg, err := stakingtypes.NewMsgCreateValidator( createValMsg, err := stakingtypes.NewMsgCreateValidator(
sdk.ValAddress(addr), sdk.ValAddress(addr),
@ -311,15 +394,22 @@ func New(t *testing.T, cfg Config) *Network {
stakingtypes.NewCommissionRates(commission, sdk.OneDec(), sdk.OneDec()), stakingtypes.NewCommissionRates(commission, sdk.OneDec(), sdk.OneDec()),
sdk.OneInt(), sdk.OneInt(),
) )
require.NoError(t, err) if err != nil {
return nil, err
}
p2pURL, err := url.Parse(p2pAddr) p2pURL, err := url.Parse(p2pAddr)
require.NoError(t, err) if err != nil {
return nil, err
}
memo := fmt.Sprintf("%s@%s:%s", nodeIDs[i], p2pURL.Hostname(), p2pURL.Port()) memo := fmt.Sprintf("%s@%s:%s", nodeIDs[i], p2pURL.Hostname(), p2pURL.Port())
fee := sdk.NewCoins(sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), sdk.NewInt(0))) fee := sdk.NewCoins(sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), sdk.NewInt(0)))
txBuilder := cfg.TxConfig.NewTxBuilder() txBuilder := cfg.TxConfig.NewTxBuilder()
require.NoError(t, txBuilder.SetMsgs(createValMsg)) err = txBuilder.SetMsgs(createValMsg)
if err != nil {
return nil, err
}
txBuilder.SetFeeAmount(fee) // Arbitrary fee txBuilder.SetFeeAmount(fee) // Arbitrary fee
txBuilder.SetGasLimit(1000000) // Need at least 100386 txBuilder.SetGasLimit(1000000) // Need at least 100386
txBuilder.SetMemo(memo) txBuilder.SetMemo(memo)
@ -332,11 +422,18 @@ func New(t *testing.T, cfg Config) *Network {
WithTxConfig(cfg.TxConfig) WithTxConfig(cfg.TxConfig)
err = tx.Sign(txFactory, nodeDirName, txBuilder, true) err = tx.Sign(txFactory, nodeDirName, txBuilder, true)
require.NoError(t, err) if err != nil {
return nil, err
}
txBz, err := cfg.TxConfig.TxJSONEncoder()(txBuilder.GetTx()) txBz, err := cfg.TxConfig.TxJSONEncoder()(txBuilder.GetTx())
require.NoError(t, err) if err != nil {
require.NoError(t, writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz)) return nil, err
}
err = writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz)
if err != nil {
return nil, err
}
srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), appCfg) srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), appCfg)
@ -367,21 +464,30 @@ func New(t *testing.T, cfg Config) *Network {
} }
} }
require.NoError(t, initGenFiles(cfg, genAccounts, genBalances, genFiles)) err := initGenFiles(cfg, genAccounts, genBalances, genFiles)
require.NoError(t, collectGenFiles(cfg, network.Validators, network.BaseDir)) if err != nil {
return nil, err
t.Log("starting test network...") }
for _, v := range network.Validators { err = collectGenFiles(cfg, network.Validators, network.BaseDir)
require.NoError(t, startInProcess(cfg, v)) if err != nil {
return nil, err
} }
t.Log("started test network") l.Log("starting test network...")
for _, v := range network.Validators {
err := startInProcess(cfg, v)
if err != nil {
return nil, err
}
}
l.Log("started test network")
// Ensure we cleanup incase any test was abruptly halted (e.g. SIGINT) as any // Ensure we cleanup incase any test was abruptly halted (e.g. SIGINT) as any
// defer in a test would not be called. // defer in a test would not be called.
server.TrapSignal(network.Cleanup) server.TrapSignal(network.Cleanup)
return network return network, nil
} }
// LatestHeight returns the latest height of the network or an error if the // LatestHeight returns the latest height of the network or an error if the
@ -459,10 +565,10 @@ func (n *Network) WaitForNextBlock() error {
func (n *Network) Cleanup() { func (n *Network) Cleanup() {
defer func() { defer func() {
lock.Unlock() lock.Unlock()
n.T.Log("released test network lock") n.Logger.Log("released test network lock")
}() }()
n.T.Log("cleaning up test network...") n.Logger.Log("cleaning up test network...")
for _, v := range n.Validators { for _, v := range n.Validators {
if v.tmNode != nil && v.tmNode.IsRunning() { if v.tmNode != nil && v.tmNode.IsRunning() {
@ -485,5 +591,47 @@ func (n *Network) Cleanup() {
_ = os.RemoveAll(n.BaseDir) _ = os.RemoveAll(n.BaseDir)
} }
n.T.Log("finished cleaning up test network") n.Logger.Log("finished cleaning up test network")
}
// printMnemonic prints a provided mnemonic seed phrase on a network logger
// for debugging and manual testing
func printMnemonic(l Logger, secret string) {
lines := []string{
"THIS MNEMONIC IS FOR TESTING PURPOSES ONLY",
"DO NOT USE IN PRODUCTION",
"",
strings.Join(strings.Fields(secret)[0:8], " "),
strings.Join(strings.Fields(secret)[8:16], " "),
strings.Join(strings.Fields(secret)[16:24], " "),
}
lineLengths := make([]int, len(lines))
for i, line := range lines {
lineLengths[i] = len(line)
}
maxLineLength := 0
for _, lineLen := range lineLengths {
if lineLen > maxLineLength {
maxLineLength = lineLen
}
}
l.Log("\n")
l.Log(strings.Repeat("+", maxLineLength+8))
for _, line := range lines {
l.Logf("++ %s ++\n", centerText(line, maxLineLength))
}
l.Log(strings.Repeat("+", maxLineLength+8))
l.Log("\n")
}
// centerText centers text across a fixed width, filling either side with whitespace buffers
func centerText(text string, width int) string {
textLen := len(text)
leftBuffer := strings.Repeat(" ", (width-textLen)/2)
rightBuffer := strings.Repeat(" ", (width-textLen)/2+(width-textLen)%2)
return fmt.Sprintf("%s%s%s", leftBuffer, text, rightBuffer)
} }

View File

@ -20,10 +20,11 @@ type IntegrationTestSuite struct {
func (s *IntegrationTestSuite) SetupSuite() { func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite") s.T().Log("setting up integration test suite")
s.network = network.New(s.T(), network.DefaultConfig()) var err error
s.Require().NotNil(s.network) s.network, err = network.New(s.T(), s.T().TempDir(), network.DefaultConfig())
s.Require().NoError(err)
_, err := s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
} }

View File

@ -48,12 +48,14 @@ func (s *IntegrationTestSuite) SetupSuite() {
cfg := network.DefaultConfig() cfg := network.DefaultConfig()
cfg.NumValidators = 2 cfg.NumValidators = 2
s.cfg = cfg s.cfg = cfg
s.network = network.New(s.T(), cfg)
var err error
s.network, err = network.New(s.T(), s.T().TempDir(), cfg)
s.Require().NoError(err)
kb := s.network.Validators[0].ClientCtx.Keyring kb := s.network.Validators[0].ClientCtx.Keyring
_, _, err := kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) _, _, err = kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
s.Require().NoError(err) s.Require().NoError(err)
account1, _, err := kb.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) account1, _, err := kb.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)

View File

@ -48,10 +48,12 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
func (s *IntegrationTestSuite) SetupSuite() { func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite") s.T().Log("setting up integration test suite")
s.network = network.New(s.T(), s.cfg) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
kb := s.network.Validators[0].ClientCtx.Keyring kb := s.network.Validators[0].ClientCtx.Keyring
_, _, err := kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) _, _, err = kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
s.Require().NoError(err) s.Require().NoError(err)
account1, _, err := kb.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) account1, _, err := kb.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)

View File

@ -49,14 +49,15 @@ func (s *IntegrationTestSuite) SetupSuite() {
cfg := network.DefaultConfig() cfg := network.DefaultConfig()
cfg.NumValidators = 1 cfg.NumValidators = 1
s.cfg = cfg s.cfg = cfg
s.network = network.New(s.T(), cfg)
s.Require().NotNil(s.network) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
val := s.network.Validators[0] val := s.network.Validators[0]
_, err := s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
s.queryClient = tx.NewServiceClient(val.ClientCtx) s.queryClient = tx.NewServiceClient(val.ClientCtx)

View File

@ -13,10 +13,11 @@ func TestAccountRetriever(t *testing.T) {
cfg := network.DefaultConfig() cfg := network.DefaultConfig()
cfg.NumValidators = 1 cfg.NumValidators = 1
network := network.New(t, cfg) network, err := network.New(t, t.TempDir(), cfg)
require.NoError(t, err)
defer network.Cleanup() defer network.Cleanup()
_, err := network.WaitForHeight(3) _, err = network.WaitForHeight(3)
require.NoError(t, err) require.NoError(t, err)
val := network.Validators[0] val := network.Validators[0]

View File

@ -27,9 +27,11 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
func (s *IntegrationTestSuite) SetupSuite() { func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite") s.T().Log("setting up integration test suite")
s.network = network.New(s.T(), s.cfg) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err := s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
} }

View File

@ -37,10 +37,12 @@ func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite") s.T().Log("setting up integration test suite")
cfg := network.DefaultConfig() cfg := network.DefaultConfig()
cfg.NumValidators = 1 cfg.NumValidators = 1
s.cfg = cfg s.cfg = cfg
s.network = network.New(s.T(), cfg)
var err error
s.network, err = network.New(s.T(), s.T().TempDir(), cfg)
s.Require().NoError(err)
val := s.network.Validators[0] val := s.network.Validators[0]
// Create new account in the keyring. // Create new account in the keyring.

View File

@ -38,7 +38,9 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
func (s *IntegrationTestSuite) SetupSuite() { func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite") s.T().Log("setting up integration test suite")
s.network = network.New(s.T(), s.cfg) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
val := s.network.Validators[0] val := s.network.Validators[0]

View File

@ -58,9 +58,10 @@ func (s *IntegrationTestSuite) SetupSuite() {
s.Require().NoError(err) s.Require().NoError(err)
genesisState[types.ModuleName] = bankGenesisBz genesisState[types.ModuleName] = bankGenesisBz
cfg.GenesisState = genesisState cfg.GenesisState = genesisState
s.cfg = cfg s.cfg = cfg
s.network = network.New(s.T(), cfg)
s.network, err = network.New(s.T(), s.T().TempDir(), cfg)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(2) _, err = s.network.WaitForHeight(2)
s.Require().NoError(err) s.Require().NoError(err)

View File

@ -80,7 +80,8 @@ func (s *IntegrationTestSuite) SetupSuite() {
genesisState[types.ModuleName] = bankGenesisBz genesisState[types.ModuleName] = bankGenesisBz
s.cfg.GenesisState = genesisState s.cfg.GenesisState = genesisState
s.network = network.New(s.T(), s.cfg) s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)

View File

@ -27,8 +27,11 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
func (s *IntegrationTestSuite) SetupSuite() { func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite") s.T().Log("setting up integration test suite")
s.network = network.New(s.T(), s.cfg) var err error
_, err := s.network.WaitForHeight(1) s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
} }

View File

@ -28,11 +28,13 @@ func (s *IntegrationTestSuite) SetupSuite() {
cfg := network.DefaultConfig() cfg := network.DefaultConfig()
cfg.NumValidators = 1 cfg.NumValidators = 1
s.cfg = cfg s.cfg = cfg
s.network = network.New(s.T(), cfg)
_, err := s.network.WaitForHeight(1) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), cfg)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
} }

View File

@ -50,7 +50,8 @@ func (s *IntegrationTestSuite) SetupTest() {
genesisState[minttypes.ModuleName] = mintDataBz genesisState[minttypes.ModuleName] = mintDataBz
s.cfg.GenesisState = genesisState s.cfg.GenesisState = genesisState
s.network = network.New(s.T(), s.cfg) s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)

View File

@ -24,9 +24,11 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
func (s *IntegrationTestSuite) SetupSuite() { func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite") s.T().Log("setting up integration test suite")
s.network = network.New(s.T(), s.cfg) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err := s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
} }

View File

@ -50,9 +50,11 @@ func (s *IntegrationTestSuite) SetupSuite() {
s.T().Skip("skipping test in unit-tests mode.") s.T().Skip("skipping test in unit-tests mode.")
} }
s.network = network.New(s.T(), s.cfg) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err := s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
val := s.network.Validators[0] val := s.network.Validators[0]

View File

@ -34,9 +34,11 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
func (s *IntegrationTestSuite) SetupSuite() { func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite") s.T().Log("setting up integration test suite")
s.network = network.New(s.T(), s.cfg) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err := s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
} }

View File

@ -32,9 +32,11 @@ func (s *IntegrationTestSuite) SetupSuite() {
s.cfg = network.DefaultConfig() s.cfg = network.DefaultConfig()
s.cfg.NumValidators = 1 s.cfg.NumValidators = 1
s.network = network.New(s.T(), s.cfg) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err := s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
val := s.network.Validators[0] val := s.network.Validators[0]

View File

@ -28,9 +28,11 @@ func NewDepositTestSuite(cfg network.Config) *DepositTestSuite {
func (s *DepositTestSuite) SetupSuite() { func (s *DepositTestSuite) SetupSuite() {
s.T().Log("setting up test suite") s.T().Log("setting up test suite")
s.network = network.New(s.T(), s.cfg) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err := s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
s.fees = sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(20))).String() s.fees = sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(20))).String()

View File

@ -33,9 +33,11 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
func (s *IntegrationTestSuite) SetupSuite() { func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite") s.T().Log("setting up integration test suite")
s.network = network.New(s.T(), s.cfg) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err := s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
val := s.network.Validators[0] val := s.network.Validators[0]

View File

@ -45,7 +45,8 @@ func (s *IntegrationTestSuite) SetupSuite() {
cfg.GenesisState = genesisState cfg.GenesisState = genesisState
s.cfg = cfg s.cfg = cfg
s.network = network.New(s.T(), cfg) s.network, err = network.New(s.T(), s.T().TempDir(), cfg)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)

View File

@ -44,7 +44,8 @@ func (s *IntegrationTestSuite) SetupSuite() {
genesisState[minttypes.ModuleName] = mintDataBz genesisState[minttypes.ModuleName] = mintDataBz
s.cfg.GenesisState = genesisState s.cfg.GenesisState = genesisState
s.network = network.New(s.T(), s.cfg) s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)

View File

@ -24,11 +24,13 @@ func (s *IntegrationTestSuite) SetupSuite() {
cfg := network.DefaultConfig() cfg := network.DefaultConfig()
cfg.NumValidators = 1 cfg.NumValidators = 1
s.cfg = cfg s.cfg = cfg
s.network = network.New(s.T(), cfg)
_, err := s.network.WaitForHeight(1) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), cfg)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
} }

View File

@ -26,9 +26,11 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
func (s *IntegrationTestSuite) SetupSuite() { func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite") s.T().Log("setting up integration test suite")
s.network = network.New(s.T(), s.cfg) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err := s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
} }

View File

@ -28,11 +28,13 @@ func (s *IntegrationTestSuite) SetupSuite() {
cfg := network.DefaultConfig() cfg := network.DefaultConfig()
cfg.NumValidators = 1 cfg.NumValidators = 1
s.cfg = cfg s.cfg = cfg
s.network = network.New(s.T(), cfg)
_, err := s.network.WaitForHeight(1) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), cfg)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
} }

View File

@ -31,9 +31,11 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
func (s *IntegrationTestSuite) SetupSuite() { func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite") s.T().Log("setting up integration test suite")
s.network = network.New(s.T(), s.cfg) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err := s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
} }

View File

@ -35,11 +35,13 @@ func (s *IntegrationTestSuite) SetupSuite() {
cfg := network.DefaultConfig() cfg := network.DefaultConfig()
cfg.NumValidators = 2 cfg.NumValidators = 2
s.cfg = cfg s.cfg = cfg
s.network = network.New(s.T(), cfg)
_, err := s.network.WaitForHeight(1) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), cfg)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
unbond, err := sdk.ParseCoinNormalized("10stake") unbond, err := sdk.ParseCoinNormalized("10stake")

View File

@ -43,9 +43,11 @@ func (s *IntegrationTestSuite) SetupSuite() {
s.T().Skip("skipping test in unit-tests mode.") s.T().Skip("skipping test in unit-tests mode.")
} }
s.network = network.New(s.T(), s.cfg) var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err := s.network.WaitForHeight(1) _, err = s.network.WaitForHeight(1)
s.Require().NoError(err) s.Require().NoError(err)
unbond, err := sdk.ParseCoinNormalized("10stake") unbond, err := sdk.ParseCoinNormalized("10stake")

View File

@ -36,7 +36,10 @@ func (s *IntegrationTestSuite) SetupSuite() {
cfg.NumValidators = 1 cfg.NumValidators = 1
s.cfg = cfg s.cfg = cfg
s.network = network.New(s.T(), cfg)
var err error
s.network, err = network.New(s.T(), s.T().TempDir(), cfg)
s.Require().NoError(err)
} }
func (s *IntegrationTestSuite) TearDownSuite() { func (s *IntegrationTestSuite) TearDownSuite() {