erigon-pulse/cmd/devnet/args/node_test.go
Mark Holt f110102023
Devnet scenarios (#7723)
This is an update to the devnet code which introduces the concept of
configurable scenarios. This replaces the previous hard coded execution
function.

The intention is that now both the network and the operations to run on
the network can be described in a data structure which is configurable
and composable.

The operating model is to create a network and then ask it to run
scenarios:

```go
network.Run(
		runCtx,
		scenarios.Scenario{
			Name: "all",
			Steps: []*scenarios.Step{
				&scenarios.Step{Text: "InitSubscriptions", Args: []any{[]requests.SubMethod{requests.Methods.ETHNewHeads}}},
				&scenarios.Step{Text: "PingErigonRpc"},
				&scenarios.Step{Text: "CheckTxPoolContent", Args: []any{0, 0, 0}},
				&scenarios.Step{Text: "SendTxWithDynamicFee", Args: []any{recipientAddress, services.DevAddress, sendValue}},
				&scenarios.Step{Text: "AwaitBlocks", Args: []any{2 * time.Second}},
			},
		})
```
The steps here refer to step handlers which can be defined as follows:

```go
func init() {
	scenarios.MustRegisterStepHandlers(
		scenarios.StepHandler(GetBalance),
	)
}

func GetBalance(ctx context.Context, addr string, blockNum requests.BlockNumber, checkBal uint64) {
...
```
This commit is an initial implementation of the scenario running - which
is working, but will need to be enhanced to make it more usable &
developable.

The current version of the code is working and has been tested with the
dev network, and bor withoutheimdall. There is a multi miner bor
heimdall configuration but this is yet to be tested.

Note that by default the scenario runner picks nodes at random on the
network to send transactions to. this causes the dev network to run very
slowly as it seems to take a long time to include transactions where the
nonce is incremented across nodes. It seems to take a long time for the
nonce to catch up in the transaction pool processing. This is yet to be
investigated.
2023-06-14 12:35:22 +01:00

188 lines
6.5 KiB
Go

package args_test
import (
"errors"
"fmt"
"path/filepath"
"testing"
"github.com/ledgerwatch/erigon/cmd/devnet/args"
)
func TestNodeArgs(t *testing.T) {
asMap := map[string]struct{}{}
nodeArgs, _ := args.AsArgs(args.Miner{
Node: args.Node{
DataDir: filepath.Join("data", fmt.Sprintf("%d", 1)),
PrivateApiAddr: "localhost:9092",
},
DevPeriod: 30,
})
for _, arg := range nodeArgs {
asMap[arg] = struct{}{}
}
for _, arg := range miningNodeArgs("data", 1) {
if _, ok := asMap[arg]; !ok {
t.Fatal(arg, "missing")
}
delete(asMap, arg)
}
if len(asMap) > 0 {
t.Fatal(asMap, "not found")
}
nodeArgs, _ = args.AsArgs(args.NonMiner{
Node: args.Node{
DataDir: filepath.Join("data", fmt.Sprintf("%d", 2)),
StaticPeers: "enode",
PrivateApiAddr: "localhost:9091",
},
})
for _, arg := range nodeArgs {
asMap[arg] = struct{}{}
}
for _, arg := range nonMiningNodeArgs("data", 2, "enode") {
if _, ok := asMap[arg]; !ok {
t.Fatal(arg, "missing")
}
delete(asMap, arg)
}
if len(asMap) > 0 {
t.Fatal(asMap, "not found")
}
}
func TestParameterFromArgument(t *testing.T) {
enode := fmt.Sprintf("%q", "1234567")
testCases := []struct {
argInput string
paramInput string
expectedRes string
expectedErr error
}{
{"--datadir", "./dev", "--datadir=./dev", nil},
{"--chain", "dev", "--chain=dev", nil},
{"--dev.period", "30", "--dev.period=30", nil},
{"--staticpeers", enode, "--staticpeers=" + enode, nil},
{"", "30", "", errInvalidArgument},
}
for _, testCase := range testCases {
got, err := parameterFromArgument(testCase.argInput, testCase.paramInput)
if got != testCase.expectedRes {
t.Errorf("expected %s, got %s", testCase.expectedRes, got)
}
if err != testCase.expectedErr {
t.Errorf("expected error: %s, got error: %s", testCase.expectedErr, err)
}
}
}
// errInvalidArgument for invalid arguments
var errInvalidArgument = errors.New("invalid argument")
// ParameterFromArgument merges the argument and parameter and returns a flag input string
func parameterFromArgument(arg, param string) (string, error) {
if arg == "" {
return "", errInvalidArgument
}
return fmt.Sprintf("%s=%s", arg, param), nil
}
const (
// BuildDirArg is the build directory for the devnet executable
buildDirArg = "./build/bin/devnet"
// DataDirArg is the datadir flag
dataDirArg = "--datadir"
// ChainArg is the chain flag
chainArg = "--chain"
// DevPeriodArg is the dev.period flag
devPeriodArg = "--dev.period"
// ConsoleVerbosityArg is the log.console.verbosity flag
consoleVerbosityArg = "--log.console.verbosity"
// LogDirArg is the log.dir.path flag
logDirArg = "--log.dir.path"
// TorrentPortArg is the --torrent.port flag argument
torrentPortArg = "--torrent.port"
// Mine is the mine flag
mine = "--mine"
// NoDiscover is the nodiscover flag
noDiscover = "--nodiscover"
// PrivateApiAddrArg is the private.api.addr flag
privateApiAddrArg = "--private.api.addr"
// StaticPeersArg is the staticpeers flag
staticPeersArg = "--staticpeers"
// HttpApiArg is the http.api flag
httpApiArg = "--http.api"
// WSArg is the --ws flag for rpcdaemon
wsArg = "--ws"
// DataDirParam is the datadir parameter
dataDirParam = "./dev"
// ChainParam is the chain parameter
chainParam = "dev"
// DevPeriodParam is the dev.period parameter
devPeriodParam = "30"
// ConsoleVerbosityParam is the verbosity parameter for the console logs
consoleVerbosityParam = "0"
// LogDirParam is the log directory parameter for logging to disk
logDirParam = "./cmd/devnet/debug_logs"
// TorrentPortParam is the port parameter for the second node
torrentPortParam = "42070"
// PrivateApiParamMine is the private.api.addr parameter for the mining node
privateApiParamMine = "localhost:9092"
// PrivateApiParamNoMine is the private.api.addr parameter for the non-mining node
privateApiParamNoMine = "localhost:9091"
// HttpApiParam is the http.api default parameter for rpcdaemon
httpApiParam = "admin,eth,erigon,web3,net,debug,trace,txpool,parity,ots"
)
// miningNodeArgs returns custom args for starting a mining node
func miningNodeArgs(dataDir string, nodeNumber int) []string {
nodeDataDir := filepath.Join(dataDir, fmt.Sprintf("%d", nodeNumber))
dataDirArg, _ := parameterFromArgument(dataDirArg, nodeDataDir)
chainType, _ := parameterFromArgument(chainArg, chainParam)
devPeriod, _ := parameterFromArgument(devPeriodArg, devPeriodParam)
privateApiAddr, _ := parameterFromArgument(privateApiAddrArg, privateApiParamMine)
httpApi, _ := parameterFromArgument(httpApiArg, httpApiParam)
ws := wsArg
consoleVerbosity, _ := parameterFromArgument(consoleVerbosityArg, consoleVerbosityParam)
p2pProtocol, _ := parameterFromArgument("--p2p.protocol", "68")
downloaderArg, _ := parameterFromArgument("--no-downloader", "true")
httpPortArg, _ := parameterFromArgument("--http.port", "8545")
authrpcPortArg, _ := parameterFromArgument("--authrpc.port", "8551")
natArg, _ := parameterFromArgument("--nat", "none")
accountSlotsArg, _ := parameterFromArgument("--txpool.accountslots", "16")
return []string{buildDirArg, dataDirArg, chainType, privateApiAddr, httpPortArg, authrpcPortArg, mine, httpApi, ws, natArg, devPeriod, consoleVerbosity, p2pProtocol, downloaderArg, accountSlotsArg}
}
// nonMiningNodeArgs returns custom args for starting a non-mining node
func nonMiningNodeArgs(dataDir string, nodeNumber int, enode string) []string {
nodeDataDir := filepath.Join(dataDir, fmt.Sprintf("%d", nodeNumber))
dataDirArg, _ := parameterFromArgument(dataDirArg, nodeDataDir)
chainType, _ := parameterFromArgument(chainArg, chainParam)
privateApiAddr, _ := parameterFromArgument(privateApiAddrArg, privateApiParamNoMine)
staticPeers, _ := parameterFromArgument(staticPeersArg, enode)
consoleVerbosity, _ := parameterFromArgument(consoleVerbosityArg, consoleVerbosityParam)
torrentPort, _ := parameterFromArgument(torrentPortArg, torrentPortParam)
p2pProtocol, _ := parameterFromArgument("--p2p.protocol", "68")
downloaderArg, _ := parameterFromArgument("--no-downloader", "true")
httpPortArg, _ := parameterFromArgument("--http.port", "8545")
httpApi, _ := parameterFromArgument(httpApiArg, "admin,eth,debug,net,trace,web3,erigon,txpool")
authrpcPortArg, _ := parameterFromArgument("--authrpc.port", "8551")
natArg, _ := parameterFromArgument("--nat", "none")
ws := wsArg
return []string{buildDirArg, dataDirArg, chainType, privateApiAddr, httpPortArg, authrpcPortArg, httpApi, ws, natArg, staticPeers, noDiscover, consoleVerbosity, torrentPort, p2pProtocol, downloaderArg}
}