mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-03 09:37:38 +00:00
62d9f3793e
## Description Add the possibility to change the RPC address used in `devnet` without requiring a rebuild. ## Test - [x] `make devnet` - [x] `./build/bin/devnet --datadir tmp` - [x] `./build/bin/devnet --datadir tmp --rpc.host localhost --rpc.port 8546`
504 lines
14 KiB
Go
504 lines
14 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"path/filepath"
|
|
dbg "runtime/debug"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/ledgerwatch/erigon/cmd/devnet/accounts"
|
|
_ "github.com/ledgerwatch/erigon/cmd/devnet/accounts/steps"
|
|
_ "github.com/ledgerwatch/erigon/cmd/devnet/admin"
|
|
_ "github.com/ledgerwatch/erigon/cmd/devnet/contracts/steps"
|
|
account_services "github.com/ledgerwatch/erigon/cmd/devnet/services/accounts"
|
|
"github.com/ledgerwatch/erigon/cmd/devnet/services/polygon"
|
|
"github.com/ledgerwatch/erigon/cmd/devnet/transactions"
|
|
"github.com/ledgerwatch/erigon/core/types"
|
|
|
|
"github.com/ledgerwatch/erigon-lib/common/metrics"
|
|
"github.com/ledgerwatch/erigon/cmd/devnet/args"
|
|
"github.com/ledgerwatch/erigon/cmd/devnet/devnet"
|
|
"github.com/ledgerwatch/erigon/cmd/devnet/devnetutils"
|
|
"github.com/ledgerwatch/erigon/cmd/devnet/requests"
|
|
"github.com/ledgerwatch/erigon/cmd/devnet/scenarios"
|
|
"github.com/ledgerwatch/erigon/cmd/devnet/services"
|
|
"github.com/ledgerwatch/erigon/params/networkname"
|
|
"github.com/ledgerwatch/log/v3"
|
|
|
|
"github.com/ledgerwatch/erigon/cmd/utils/flags"
|
|
"github.com/ledgerwatch/erigon/params"
|
|
"github.com/ledgerwatch/erigon/turbo/app"
|
|
"github.com/ledgerwatch/erigon/turbo/debug"
|
|
"github.com/ledgerwatch/erigon/turbo/logging"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
var (
|
|
DataDirFlag = flags.DirectoryFlag{
|
|
Name: "datadir",
|
|
Usage: "Data directory for the devnet",
|
|
Value: flags.DirectoryString(""),
|
|
Required: true,
|
|
}
|
|
|
|
ChainFlag = cli.StringFlag{
|
|
Name: "chain",
|
|
Usage: "The devnet chain to run (dev,bor-devnet)",
|
|
Value: networkname.DevChainName,
|
|
}
|
|
|
|
ScenariosFlag = cli.StringFlag{
|
|
Name: "scenarios",
|
|
Usage: "Scenarios to be run on the devnet chain",
|
|
Value: "dynamic-tx-node-0",
|
|
}
|
|
|
|
BaseRpcHostFlag = cli.StringFlag{
|
|
Name: "rpc.host",
|
|
Usage: "The host of the base RPC service",
|
|
Value: "localhost",
|
|
}
|
|
|
|
BaseRpcPortFlag = cli.IntFlag{
|
|
Name: "rpc.port",
|
|
Usage: "The port of the base RPC service",
|
|
Value: 8545,
|
|
}
|
|
|
|
WithoutHeimdallFlag = cli.BoolFlag{
|
|
Name: "bor.withoutheimdall",
|
|
Usage: "Run without Heimdall service",
|
|
}
|
|
|
|
LocalHeimdallFlag = cli.BoolFlag{
|
|
Name: "bor.localheimdall",
|
|
Usage: "Run with a devnet local Heimdall service",
|
|
}
|
|
|
|
HeimdallgRPCAddressFlag = cli.StringFlag{
|
|
Name: "bor.heimdallgRPC",
|
|
Usage: "Address of Heimdall gRPC service",
|
|
Value: "localhost:8540",
|
|
}
|
|
|
|
BorSprintSizeFlag = cli.IntFlag{
|
|
Name: "bor.sprintsize",
|
|
Usage: "The bor sprint size to run",
|
|
}
|
|
|
|
MetricsEnabledFlag = cli.BoolFlag{
|
|
Name: "metrics",
|
|
Usage: "Enable metrics collection and reporting",
|
|
}
|
|
|
|
MetricsNodeFlag = cli.IntFlag{
|
|
Name: "metrics.node",
|
|
Usage: "Which node of the cluster to attach to",
|
|
Value: 0,
|
|
}
|
|
|
|
MetricsPortFlag = cli.IntFlag{
|
|
Name: "metrics.port",
|
|
Usage: "Metrics HTTP server listening port",
|
|
Value: metrics.DefaultConfig.Port,
|
|
}
|
|
|
|
DiagnosticsURLFlag = cli.StringFlag{
|
|
Name: "diagnostics.url",
|
|
Usage: "URL of the diagnostics system provided by the support team, include unique session PIN",
|
|
}
|
|
|
|
insecureFlag = cli.BoolFlag{
|
|
Name: "insecure",
|
|
Usage: "Allows communication with diagnostics system using self-signed TLS certificates",
|
|
}
|
|
|
|
metricsURLsFlag = cli.StringSliceFlag{
|
|
Name: "debug.urls",
|
|
Usage: "internal flag",
|
|
}
|
|
|
|
WaitFlag = cli.BoolFlag{
|
|
Name: "wait",
|
|
Usage: "Wait until interrupted after all scenarios have run",
|
|
}
|
|
)
|
|
|
|
type PanicHandler struct {
|
|
}
|
|
|
|
func (ph PanicHandler) Log(r *log.Record) error {
|
|
fmt.Printf("Msg: %s\nStack: %s\n", r.Msg, dbg.Stack())
|
|
os.Exit(1)
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
|
|
debug.RaiseFdLimit()
|
|
|
|
app := cli.NewApp()
|
|
app.Version = params.VersionWithCommit(params.GitCommit)
|
|
app.Action = func(ctx *cli.Context) error {
|
|
return action(ctx)
|
|
}
|
|
app.Flags = []cli.Flag{
|
|
&DataDirFlag,
|
|
&ChainFlag,
|
|
&ScenariosFlag,
|
|
&BaseRpcHostFlag,
|
|
&BaseRpcPortFlag,
|
|
&WithoutHeimdallFlag,
|
|
&LocalHeimdallFlag,
|
|
&HeimdallgRPCAddressFlag,
|
|
&BorSprintSizeFlag,
|
|
&MetricsEnabledFlag,
|
|
&MetricsNodeFlag,
|
|
&MetricsPortFlag,
|
|
&DiagnosticsURLFlag,
|
|
&insecureFlag,
|
|
&metricsURLsFlag,
|
|
&WaitFlag,
|
|
&logging.LogVerbosityFlag,
|
|
&logging.LogConsoleVerbosityFlag,
|
|
&logging.LogDirVerbosityFlag,
|
|
}
|
|
|
|
app.After = func(ctx *cli.Context) error {
|
|
// unsubscribe from all the subscriptions made
|
|
services.UnsubscribeAll()
|
|
return nil
|
|
}
|
|
if err := app.Run(os.Args); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
}
|
|
}
|
|
|
|
const (
|
|
recipientAddress = "0x71562b71999873DB5b286dF957af199Ec94617F7"
|
|
sendValue uint64 = 10000
|
|
)
|
|
|
|
func action(ctx *cli.Context) error {
|
|
dataDir := ctx.String("datadir")
|
|
logsDir := filepath.Join(dataDir, "logs")
|
|
|
|
if err := os.MkdirAll(logsDir, 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
logger := logging.SetupLoggerCtx("devnet", ctx, false /* rootLogger */)
|
|
|
|
// Make root logger fail
|
|
log.Root().SetHandler(PanicHandler{})
|
|
|
|
// clear all the dev files
|
|
if err := devnetutils.ClearDevDB(dataDir, logger); err != nil {
|
|
return err
|
|
}
|
|
|
|
network, err := initDevnet(ctx, logger)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
metrics := ctx.Bool("metrics")
|
|
|
|
if metrics {
|
|
// TODO should get this from the network as once we have multiple nodes we'll need to iterate the
|
|
// nodes and create a series of urls - for the moment only one is supported
|
|
ctx.Set("metrics.urls", fmt.Sprintf("http://localhost:%d/debug/", ctx.Int("metrics.port")))
|
|
}
|
|
|
|
// start the network with each node in a go routine
|
|
logger.Info("Starting Devnet")
|
|
|
|
runCtx, err := network.Start(ctx, logger)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("Devnet start failed: %w", err)
|
|
}
|
|
|
|
go func() {
|
|
signalCh := make(chan os.Signal, 1)
|
|
signal.Notify(signalCh, syscall.SIGTERM, syscall.SIGINT)
|
|
|
|
switch s := <-signalCh; s {
|
|
case syscall.SIGTERM:
|
|
logger.Info("Stopping networks")
|
|
network.Stop()
|
|
case syscall.SIGINT:
|
|
logger.Info("Terminating network")
|
|
os.Exit(-int(syscall.SIGINT))
|
|
}
|
|
}()
|
|
|
|
diagnosticsUrl := ctx.String("diagnostics.url")
|
|
|
|
if metrics && len(diagnosticsUrl) > 0 {
|
|
go func() {
|
|
app.ConnectDiagnostics(ctx, logger)
|
|
}()
|
|
}
|
|
|
|
if ctx.String(ChainFlag.Name) == networkname.DevChainName {
|
|
transactions.MaxNumberOfEmptyBlockChecks = 30
|
|
}
|
|
|
|
scenarios.Scenarios{
|
|
"dynamic-tx-node-0": {
|
|
Context: runCtx.
|
|
WithCurrentNetwork(0).
|
|
WithCurrentNode(0),
|
|
Steps: []*scenarios.Step{
|
|
{Text: "InitSubscriptions", Args: []any{[]requests.SubMethod{requests.Methods.ETHNewHeads}}},
|
|
{Text: "PingErigonRpc"},
|
|
{Text: "CheckTxPoolContent", Args: []any{0, 0, 0}},
|
|
{Text: "SendTxWithDynamicFee", Args: []any{recipientAddress, accounts.DevAddress, sendValue}},
|
|
{Text: "AwaitBlocks", Args: []any{2 * time.Second}},
|
|
},
|
|
},
|
|
"dynamic-tx-any-node": {
|
|
Context: runCtx.WithCurrentNetwork(0),
|
|
Steps: []*scenarios.Step{
|
|
{Text: "InitSubscriptions", Args: []any{[]requests.SubMethod{requests.Methods.ETHNewHeads}}},
|
|
{Text: "PingErigonRpc"},
|
|
{Text: "CheckTxPoolContent", Args: []any{0, 0, 0}},
|
|
{Text: "SendTxWithDynamicFee", Args: []any{recipientAddress, accounts.DevAddress, sendValue}},
|
|
{Text: "AwaitBlocks", Args: []any{2 * time.Second}},
|
|
},
|
|
},
|
|
"call-contract": {
|
|
Context: runCtx.WithCurrentNetwork(0),
|
|
Steps: []*scenarios.Step{
|
|
{Text: "InitSubscriptions", Args: []any{[]requests.SubMethod{requests.Methods.ETHNewHeads}}},
|
|
{Text: "DeployAndCallLogSubscriber", Args: []any{accounts.DevAddress}},
|
|
},
|
|
},
|
|
"state-sync": {
|
|
Steps: []*scenarios.Step{
|
|
{Text: "InitSubscriptions", Args: []any{[]requests.SubMethod{requests.Methods.ETHNewHeads}}},
|
|
{Text: "CreateAccountWithFunds", Args: []any{networkname.DevChainName, "root-funder", 200.0}},
|
|
{Text: "CreateAccountWithFunds", Args: []any{networkname.BorDevnetChainName, "child-funder", 200.0}},
|
|
{Text: "DeployChildChainReceiver", Args: []any{"child-funder"}},
|
|
{Text: "DeployRootChainSender", Args: []any{"root-funder"}},
|
|
{Text: "GenerateSyncEvents", Args: []any{"root-funder", 10, 2, 2}},
|
|
{Text: "ProcessRootTransfers", Args: []any{"root-funder", 10, 2, 2}},
|
|
{Text: "BatchProcessRootTransfers", Args: []any{"root-funder", 1, 10, 2, 2}},
|
|
},
|
|
},
|
|
"child-chain-exit": {
|
|
Steps: []*scenarios.Step{
|
|
{Text: "CreateAccountWithFunds", Args: []any{networkname.DevChainName, "root-funder", 200.0}},
|
|
{Text: "CreateAccountWithFunds", Args: []any{networkname.BorDevnetChainName, "child-funder", 200.0}},
|
|
{Text: "DeployRootChainReceiver", Args: []any{"root-funder"}},
|
|
{Text: "DeployChildChainSender", Args: []any{"child-funder"}},
|
|
{Text: "ProcessChildTransfers", Args: []any{"child-funder", 1, 2, 2}},
|
|
//{Text: "BatchProcessTransfers", Args: []any{"child-funder", 1, 10, 2, 2}},
|
|
},
|
|
},
|
|
}.Run(runCtx, strings.Split(ctx.String("scenarios"), ",")...)
|
|
|
|
if ctx.Bool("wait") || (metrics && len(diagnosticsUrl) > 0) {
|
|
logger.Info("Waiting")
|
|
network.Wait()
|
|
} else {
|
|
logger.Info("Stopping Networks")
|
|
network.Stop()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) {
|
|
dataDir := ctx.String(DataDirFlag.Name)
|
|
chain := ctx.String(ChainFlag.Name)
|
|
baseRpcHost := ctx.String(BaseRpcHostFlag.Name)
|
|
baseRpcPort := ctx.Int(BaseRpcPortFlag.Name)
|
|
|
|
faucetSource := accounts.NewAccount("faucet-source")
|
|
|
|
switch chain {
|
|
case networkname.BorDevnetChainName:
|
|
if ctx.Bool(WithoutHeimdallFlag.Name) {
|
|
return []*devnet.Network{
|
|
{
|
|
DataDir: dataDir,
|
|
Chain: networkname.BorDevnetChainName,
|
|
Logger: logger,
|
|
BasePort: 30303,
|
|
BasePrivateApiAddr: "localhost:10090",
|
|
BaseRPCHost: baseRpcHost,
|
|
BaseRPCPort: baseRpcPort,
|
|
//Snapshots: true,
|
|
Alloc: types.GenesisAlloc{
|
|
faucetSource.Address: {Balance: accounts.EtherAmount(200_000)},
|
|
},
|
|
Services: []devnet.Service{
|
|
account_services.NewFaucet(networkname.BorDevnetChainName, faucetSource),
|
|
},
|
|
Nodes: []devnet.Node{
|
|
args.BlockProducer{
|
|
Node: args.Node{
|
|
ConsoleVerbosity: "0",
|
|
DirVerbosity: "5",
|
|
WithoutHeimdall: true,
|
|
},
|
|
AccountSlots: 200,
|
|
},
|
|
args.NonBlockProducer{
|
|
Node: args.Node{
|
|
ConsoleVerbosity: "0",
|
|
DirVerbosity: "5",
|
|
WithoutHeimdall: true,
|
|
},
|
|
},
|
|
},
|
|
}}, nil
|
|
} else {
|
|
var heimdallGrpc string
|
|
var services []devnet.Service
|
|
|
|
checkpointOwner := accounts.NewAccount("checkpoint-owner")
|
|
|
|
if ctx.Bool(LocalHeimdallFlag.Name) {
|
|
config := *params.BorDevnetChainConfig
|
|
|
|
if sprintSize := uint64(ctx.Int(BorSprintSizeFlag.Name)); sprintSize > 0 {
|
|
config.Bor.Sprint = map[string]uint64{"0": sprintSize}
|
|
}
|
|
|
|
services = append(services, polygon.NewHeimdall(&config,
|
|
&polygon.CheckpointConfig{
|
|
CheckpointBufferTime: 60 * time.Second,
|
|
CheckpointAccount: checkpointOwner,
|
|
},
|
|
logger))
|
|
|
|
heimdallGrpc = polygon.HeimdallGRpc(devnet.WithCliContext(context.Background(), ctx))
|
|
}
|
|
|
|
return []*devnet.Network{
|
|
{
|
|
DataDir: dataDir,
|
|
Chain: networkname.BorDevnetChainName,
|
|
Logger: logger,
|
|
BasePort: 30303,
|
|
BasePrivateApiAddr: "localhost:10090",
|
|
BaseRPCHost: baseRpcHost,
|
|
BaseRPCPort: baseRpcPort,
|
|
BorStateSyncDelay: 5 * time.Second,
|
|
Services: append(services, account_services.NewFaucet(networkname.BorDevnetChainName, faucetSource)),
|
|
Alloc: types.GenesisAlloc{
|
|
faucetSource.Address: {Balance: accounts.EtherAmount(200_000)},
|
|
},
|
|
Nodes: []devnet.Node{
|
|
args.BlockProducer{
|
|
Node: args.Node{
|
|
ConsoleVerbosity: "0",
|
|
DirVerbosity: "5",
|
|
HeimdallGRpc: heimdallGrpc,
|
|
},
|
|
AccountSlots: 200,
|
|
},
|
|
args.BlockProducer{
|
|
Node: args.Node{
|
|
ConsoleVerbosity: "0",
|
|
DirVerbosity: "5",
|
|
HeimdallGRpc: heimdallGrpc,
|
|
},
|
|
AccountSlots: 200,
|
|
},
|
|
/*args.BlockProducer{
|
|
Node: args.Node{
|
|
ConsoleVerbosity: "0",
|
|
DirVerbosity: "5",
|
|
HeimdallGRpc: heimdallGrpc,
|
|
},
|
|
AccountSlots: 200,
|
|
},*/
|
|
args.NonBlockProducer{
|
|
Node: args.Node{
|
|
ConsoleVerbosity: "0",
|
|
DirVerbosity: "5",
|
|
HeimdallGRpc: heimdallGrpc,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
DataDir: dataDir,
|
|
Chain: networkname.DevChainName,
|
|
Logger: logger,
|
|
BasePort: 30403,
|
|
BasePrivateApiAddr: "localhost:10190",
|
|
BaseRPCHost: baseRpcHost,
|
|
BaseRPCPort: baseRpcPort,
|
|
Services: append(services, account_services.NewFaucet(networkname.DevChainName, faucetSource)),
|
|
Alloc: types.GenesisAlloc{
|
|
faucetSource.Address: {Balance: accounts.EtherAmount(200_000)},
|
|
checkpointOwner.Address: {Balance: accounts.EtherAmount(10_000)},
|
|
},
|
|
Nodes: []devnet.Node{
|
|
args.BlockProducer{
|
|
Node: args.Node{
|
|
ConsoleVerbosity: "0",
|
|
DirVerbosity: "5",
|
|
VMDebug: true,
|
|
HttpCorsDomain: "*",
|
|
},
|
|
DevPeriod: 5,
|
|
AccountSlots: 200,
|
|
},
|
|
args.NonBlockProducer{
|
|
Node: args.Node{
|
|
ConsoleVerbosity: "0",
|
|
DirVerbosity: "3",
|
|
},
|
|
},
|
|
},
|
|
}}, nil
|
|
}
|
|
|
|
case networkname.DevChainName:
|
|
return []*devnet.Network{
|
|
{
|
|
DataDir: dataDir,
|
|
Chain: networkname.DevChainName,
|
|
Logger: logger,
|
|
BasePrivateApiAddr: "localhost:10090",
|
|
BaseRPCHost: baseRpcHost,
|
|
BaseRPCPort: baseRpcPort,
|
|
Alloc: types.GenesisAlloc{
|
|
faucetSource.Address: {Balance: accounts.EtherAmount(200_000)},
|
|
},
|
|
Services: []devnet.Service{
|
|
account_services.NewFaucet(networkname.DevChainName, faucetSource),
|
|
},
|
|
Nodes: []devnet.Node{
|
|
args.BlockProducer{
|
|
Node: args.Node{
|
|
ConsoleVerbosity: "0",
|
|
DirVerbosity: "5",
|
|
},
|
|
AccountSlots: 200,
|
|
},
|
|
args.NonBlockProducer{
|
|
Node: args.Node{
|
|
ConsoleVerbosity: "0",
|
|
DirVerbosity: "5",
|
|
},
|
|
},
|
|
},
|
|
}}, nil
|
|
}
|
|
|
|
return nil, fmt.Errorf(`Unknown network: "%s"`, chain)
|
|
}
|