Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TT-1136, CCIP-2255] make eth node log level configurable via TOML #943

Merged
merged 7 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions config/private_ethereum_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
_ "embed"
"errors"
"fmt"
"strings"
"time"

"github.com/pelletier/go-toml/v2"
Expand All @@ -17,6 +18,7 @@ import (
var (
ErrMissingEthereumVersion = errors.New("ethereum version is required")
ErrMissingExecutionLayer = errors.New("execution layer is required")
DefaultNodeLogLevel = "info"
)

type EthereumNetworkConfig struct {
Expand All @@ -31,6 +33,7 @@ type EthereumNetworkConfig struct {
ValKeysDir *string `toml:"val_keys_dir"`
EthereumChainConfig *EthereumChainConfig `toml:"EthereumChainConfig"`
CustomDockerImages map[ContainerType]string `toml:"CustomDockerImages"`
NodeLogLevel *string `toml:"node_log_level,omitempty"`
}

func (en *EthereumNetworkConfig) Validate() error {
Expand Down Expand Up @@ -74,6 +77,16 @@ func (en *EthereumNetworkConfig) Validate() error {
en.ConsensusLayer = nil
}

if en.NodeLogLevel == nil {
en.NodeLogLevel = &DefaultNodeLogLevel
}

switch strings.ToLower(*en.NodeLogLevel) {
case "trace", "debug", "info", "warn", "error":
default:
return fmt.Errorf("invalid node log level: %s", *en.NodeLogLevel)
}

if en.EthereumChainConfig == nil {
return errors.New("ethereum chain config is required")
}
Expand Down
1 change: 1 addition & 0 deletions config/tomls/default_ethereum_env.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ ethereum_version="eth2"
consensus_layer="prysm"
execution_layer="geth"
wait_for_finalization=false
node_log_level="info"

[PrivateEthereumNetwork.EthereumChainConfig]
seconds_per_slot=12
Expand Down
2 changes: 1 addition & 1 deletion docker/test_env/besu_eth1.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (g *Besu) getEth1ContainerRequest() (*tc.ContainerRequest, error) {
"--miner-enabled=true",
"--miner-coinbase", RootFundingAddr,
fmt.Sprintf("--network-id=%d", g.chainConfig.ChainID),
"--logging=DEBUG",
fmt.Sprintf("--logging=%s", strings.ToUpper(g.LogLevel)),
},
Files: []tc.ContainerFile{
{
Expand Down
2 changes: 1 addition & 1 deletion docker/test_env/besu_eth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (g *Besu) getEth2ContainerRequest() (*tc.ContainerRequest, error) {
fmt.Sprintf("--engine-rpc-port=%s", ETH2_EXECUTION_PORT),
"--sync-mode=FULL",
"--data-storage-format=BONSAI",
// "--logging=DEBUG",
fmt.Sprintf("--logging=%s", strings.ToUpper(g.LogLevel)),
"--rpc-tx-feecap=0",
},
Env: map[string]string{
Expand Down
9 changes: 9 additions & 0 deletions docker/test_env/env_component.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type EnvComponent struct {
PostStartsHooks []tc.ContainerHook `json:"-"`
PostStopsHooks []tc.ContainerHook `json:"-"`
PreTerminatesHooks []tc.ContainerHook `json:"-"`
LogLevel string `json:"-"`
}

type EnvComponentOption = func(c *EnvComponent)
Expand All @@ -52,6 +53,14 @@ func WithContainerImageWithVersion(imageWithVersion string) EnvComponentOption {
}
}

func WithLogLevel(logLevel string) EnvComponentOption {
return func(c *EnvComponent) {
if logLevel != "" {
c.LogLevel = logLevel
}
}
}

func WithLogStream(ls *logstream.LogStream) EnvComponentOption {
return func(c *EnvComponent) {
c.LogStream = ls
Expand Down
4 changes: 3 additions & 1 deletion docker/test_env/erigon_eth1.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,16 +166,18 @@ func (g *Erigon) buildPowInitScript(minerAddr string) (string, error) {

echo "Starting Erigon..."
erigon --http --http.api=eth,erigon,engine,web3,net,debug,trace,txpool,admin --http.addr=0.0.0.0 --http.corsdomain=* --http.vhosts=* --http.port={{.HttpPort}} --ws \
--allow-insecure-unlock --nodiscover --networkid={{.ChainID}} --mine --miner.etherbase={{.MinerAddr}} --fakepow`
--allow-insecure-unlock --nodiscover --networkid={{.ChainID}} --mine --miner.etherbase={{.MinerAddr}} --fakepow --log.console.verbosity={{.LogLevel}}`

data := struct {
HttpPort string
ChainID int
MinerAddr string
LogLevel string
}{
HttpPort: DEFAULT_EVM_NODE_HTTP_PORT,
ChainID: g.chainConfig.ChainID,
MinerAddr: minerAddr,
LogLevel: g.LogLevel,
}

t, err := template.New("init").Parse(initTemplate)
Expand Down
16 changes: 13 additions & 3 deletions docker/test_env/erigon_eth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ func (g *Erigon) buildPosInitScript() (string, error) {
}

initTemplate := `#!/bin/bash
echo "BAM!"
echo "Copied genesis file to {{.ExecutionDir}}"
mkdir -p {{.ExecutionDir}}
cp {{.GeneratedDataDir}}/genesis.json {{.ExecutionDir}}/genesis.json
Expand All @@ -124,9 +125,14 @@ func (g *Erigon) buildPosInitScript() (string, error) {
fi

echo "Starting Erigon..."
erigon --http --http.api=eth,erigon,engine,web3,net,debug,trace,txpool,admin --http.addr=0.0.0.0 --http.corsdomain=* \
--http.vhosts=* --http.port={{.HttpPort}} --ws --authrpc.vhosts=* --authrpc.addr=0.0.0.0 --authrpc.jwtsecret={{.JwtFileLocation}} \
--datadir={{.ExecutionDir}} {{.ExtraExecutionFlags}} --allow-insecure-unlock --nodiscover --networkid={{.ChainID}}`
command="erigon --http --http.api=eth,erigon,engine,web3,net,debug,trace,txpool,admin --http.addr=0.0.0.0 --http.corsdomain=* --http.vhosts=* --http.port={{.HttpPort}} --ws --authrpc.vhosts=* --authrpc.addr=0.0.0.0 --authrpc.jwtsecret={{.JwtFileLocation}} --datadir={{.ExecutionDir}} {{.ExtraExecutionFlags}} --allow-insecure-unlock --nodiscover --networkid={{.ChainID}} --log.console.verbosity={{.LogLevel}} --verbosity={{.LogLevel}}"

if [ "{{.LogLevel}}" == "trace" ]; then
echo "Enabling trace logging for senders: {{.SendersToTrace}}"
command="$command --txpool.trace.senders=\"{{.SendersToTrace}}\""
fi

eval $command`

data := struct {
HttpPort string
Expand All @@ -135,13 +141,17 @@ func (g *Erigon) buildPosInitScript() (string, error) {
JwtFileLocation string
ExecutionDir string
ExtraExecutionFlags string
SendersToTrace string
LogLevel string
}{
HttpPort: DEFAULT_EVM_NODE_HTTP_PORT,
ChainID: g.chainConfig.ChainID,
GeneratedDataDir: GENERATED_DATA_DIR_INSIDE_CONTAINER,
JwtFileLocation: JWT_SECRET_FILE_LOCATION_INSIDE_CONTAINER,
ExecutionDir: "/home/erigon/execution-data",
ExtraExecutionFlags: extraExecutionFlags,
SendersToTrace: strings.Join(g.chainConfig.AddressesToFund, ","),
LogLevel: g.LogLevel,
}

t, err := template.New("init").Parse(initTemplate)
Expand Down
37 changes: 30 additions & 7 deletions docker/test_env/ethereum_env.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package test_env
import (
"fmt"
"os"
"strings"
"testing"
"time"

Expand All @@ -20,14 +21,12 @@ import (
)

const (
CONFIG_ENV_VAR_NAME = "PRIVATE_ETHEREUM_NETWORK_CONFIG_PATH"
EXEC_CLIENT_ENV_VAR_NAME = "ETH2_EL_CLIENT"
CONFIG_ENV_VAR_NAME = "PRIVATE_ETHEREUM_NETWORK_CONFIG_PATH"
)

var (
ErrMissingConsensusLayer = errors.New("consensus layer is required for PoS")
ErrConsensusLayerNotAllowed = errors.New("consensus layer is not allowed for PoW")
ErrTestConfigNotSaved = errors.New("could not save test env config")
ErrMissingConsensusLayer = errors.New("consensus layer is required for PoS")
ErrTestConfigNotSaved = errors.New("could not save test env config")
)

var MsgMismatchedExecutionClient = "you provided a custom docker image for %s execution client, but explicitly set a execution client to %s. Make them match or remove one or the other"
Expand All @@ -45,6 +44,7 @@ type EthereumNetworkBuilder struct {
addressesToFund []string
waitForFinalization bool
existingFromEnvVar bool
nodeLogLevel string
}

func NewEthereumNetworkBuilder() EthereumNetworkBuilder {
Expand Down Expand Up @@ -95,6 +95,11 @@ func (b *EthereumNetworkBuilder) WithDockerNetworks(networks []string) *Ethereum
return b
}

func (b *EthereumNetworkBuilder) WithNodeLogLevel(nodeLogLevel string) *EthereumNetworkBuilder {
b.nodeLogLevel = nodeLogLevel
return b
}

func (b *EthereumNetworkBuilder) WithExistingConfig(config config.EthereumNetworkConfig) *EthereumNetworkBuilder {
b.existingConfig = &config
return b
Expand Down Expand Up @@ -145,6 +150,7 @@ func (b *EthereumNetworkBuilder) buildNetworkConfig() EthereumNetwork {
n.WaitForFinalization = &b.waitForFinalization
n.EthereumNetworkConfig.EthereumChainConfig = b.ethereumChainConfig
n.EthereumNetworkConfig.CustomDockerImages = b.customDockerImages
n.NodeLogLevel = &b.nodeLogLevel
n.t = b.t
n.ls = b.ls

Expand Down Expand Up @@ -189,7 +195,9 @@ func (b *EthereumNetworkBuilder) Build() (EthereumNetwork, error) {
return EthereumNetwork{}, err
}

return b.buildNetworkConfig(), nil
network := b.buildNetworkConfig()

return network, network.Validate()
}

func (b *EthereumNetworkBuilder) importExistingConfig() bool {
Expand All @@ -215,6 +223,12 @@ func (b *EthereumNetworkBuilder) importExistingConfig() bool {
b.ethereumChainConfig = b.existingConfig.EthereumChainConfig
b.customDockerImages = b.existingConfig.CustomDockerImages

if b.existingConfig.NodeLogLevel != nil {
b.nodeLogLevel = *b.existingConfig.NodeLogLevel
} else {
b.nodeLogLevel = config.DefaultNodeLogLevel
}

return true
}

Expand Down Expand Up @@ -309,6 +323,10 @@ func (b *EthereumNetworkBuilder) autoFill() error {
b.ethereumVersion = config.EthereumVersion_Eth2
}

if b.nodeLogLevel == "" {
b.nodeLogLevel = config.DefaultNodeLogLevel
}

return nil
}

Expand Down Expand Up @@ -416,7 +434,7 @@ func (en *EthereumNetwork) startEth2() (blockchain.EVMNetwork, RpcProvider, erro
case config.ExecutionLayer_Geth:
client, clientErr = NewGethEth2(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, config.ConsensusLayer_Prysm, opts...)
case config.ExecutionLayer_Nethermind:
client, clientErr = NewNethermindEth2(dockerNetworks, generatedDataHostDir, config.ConsensusLayer_Prysm, opts...)
client, clientErr = NewNethermindEth2(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, config.ConsensusLayer_Prysm, opts...)
case config.ExecutionLayer_Erigon:
client, clientErr = NewErigonEth2(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, config.ConsensusLayer_Prysm, opts...)
case config.ExecutionLayer_Besu:
Expand Down Expand Up @@ -711,6 +729,11 @@ func (en *EthereumNetwork) getExecutionLayerEnvComponentOpts() []EnvComponentOpt
opts = append(opts, en.getImageOverride(config.ContainerType_ExecutionLayer)...)
opts = append(opts, en.setExistingContainerName(config.ContainerType_ExecutionLayer))
opts = append(opts, WithLogStream(en.ls))

if en.NodeLogLevel != nil && *en.NodeLogLevel != "" {
opts = append(opts, WithLogLevel(strings.ToLower(*en.NodeLogLevel)))
}

return opts
}

Expand Down
85 changes: 85 additions & 0 deletions docker/test_env/ethereum_env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,91 @@ func TestEthEnvCustomDockerImagesFromToml(t *testing.T) {
require.Contains(t, fmt.Sprintf(MsgUnsupportedDockerImage, "i-dont-exist"), err.Error(), "Error message is not correct")
}

func TestEthNoLogLevelDefaultsToInfo(t *testing.T) {
t.Parallel()
tomlStr := `
[EthereumNetwork]
consensus_type="pos"
consensus_layer="prysm"
execution_layer="geth"
wait_for_finalization=false

[EthereumNetwork.EthereumChainConfig]
seconds_per_slot=12
slots_per_epoch=2
genesis_delay=20
validator_count=8
chain_id=1234
addresses_to_fund=["0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "0x742d35Cc6634C0532925a3b844Bc454e4438f44f"]
`

tomlCfg, err := readEthereumNetworkConfig(tomlStr)
require.NoError(t, err, "Couldn't read config")

tomlCfg.EthereumChainConfig.GenerateGenesisTimestamp()

err = tomlCfg.Validate()
require.NoError(t, err, "Failed to validate correct TOML config")
require.Equal(t, config.DefaultNodeLogLevel, *tomlCfg.NodeLogLevel, "Incorrect default log level")
}

func TestEthLogLevelTrace(t *testing.T) {
t.Parallel()
tomlStr := `
[EthereumNetwork]
consensus_type="pos"
consensus_layer="prysm"
execution_layer="geth"
wait_for_finalization=false
node_log_level="trace"

[EthereumNetwork.EthereumChainConfig]
seconds_per_slot=12
slots_per_epoch=2
genesis_delay=20
validator_count=8
chain_id=1234
addresses_to_fund=["0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "0x742d35Cc6634C0532925a3b844Bc454e4438f44f"]
`

tomlCfg, err := readEthereumNetworkConfig(tomlStr)
require.NoError(t, err, "Couldn't read config")

tomlCfg.EthereumChainConfig.GenerateGenesisTimestamp()

err = tomlCfg.Validate()
require.NoError(t, err, "Failed to validate correct TOML config")
require.Equal(t, "trace", *tomlCfg.NodeLogLevel, "Incorrect default log level")
}

func TestEthInvalidLogLevel(t *testing.T) {
t.Parallel()
tomlStr := `
[EthereumNetwork]
consensus_type="pos"
consensus_layer="prysm"
execution_layer="geth"
wait_for_finalization=false
node_log_level="random"

[EthereumNetwork.EthereumChainConfig]
seconds_per_slot=12
slots_per_epoch=2
genesis_delay=20
validator_count=8
chain_id=1234
addresses_to_fund=["0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "0x742d35Cc6634C0532925a3b844Bc454e4438f44f"]
`

tomlCfg, err := readEthereumNetworkConfig(tomlStr)
require.NoError(t, err, "Couldn't read config")

tomlCfg.EthereumChainConfig.GenerateGenesisTimestamp()

err = tomlCfg.Validate()
require.Error(t, err, "Successfully validated incorrect TOML config")
}

type ethereumNetworkWrapper struct {
EthereumNetwork *config.EthereumNetworkConfig `toml:"EthereumNetwork"`
}
Expand Down
19 changes: 19 additions & 0 deletions docker/test_env/geth_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,22 @@ func (g *Geth) getWebsocketEnabledMessage() (string, error) {

return "WebSocket enabled", nil
}

func (g *Geth) logLevelToVerbosity() (int, error) {
switch g.LogLevel {
case "trace":
return 5, nil
case "debug":
return 4, nil
case "info":
return 3, nil
case "warn":
return 2, nil
case "error":
return 1, nil
case "silent":
return 0, nil
default:
return -1, fmt.Errorf("unknown log level: %s", g.LogLevel)
}
}
Loading
Loading