Skip to content

Commit

Permalink
[TT-1094] Add Reth support (#1018)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tofel authored Jul 10, 2024
1 parent 06979d6 commit 9172f5c
Show file tree
Hide file tree
Showing 7 changed files with 438 additions and 2 deletions.
17 changes: 16 additions & 1 deletion config/private_ethereum_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
var (
ErrMissingEthereumVersion = errors.New("ethereum version is required")
ErrMissingExecutionLayer = errors.New("execution layer is required")
Eth1NotSupportedByRethMsg = "eth1 is not supported by Reth, please use eth2"
DefaultNodeLogLevel = "info"
)

Expand Down Expand Up @@ -46,7 +47,7 @@ func (en *EthereumNetworkConfig) Validate() error {

if en.EthereumVersion == nil && en.ConsensusType != nil {
l.Debug().Msg("Using _deprecated_ ConsensusType as EthereumVersion")
tempEthVersion := (*EthereumVersion)(en.ConsensusType)
tempEthVersion := en.ConsensusType
switch *tempEthVersion {
case EthereumVersion_Eth1, EthereumVersion_Eth1_Legacy:
*tempEthVersion = EthereumVersion_Eth1
Expand Down Expand Up @@ -81,6 +82,19 @@ func (en *EthereumNetworkConfig) Validate() error {
en.NodeLogLevel = &DefaultNodeLogLevel
}

if *en.EthereumVersion == EthereumVersion_Eth1 && *en.ExecutionLayer == ExecutionLayer_Reth {
msg := `%s
If you are using builder to create the network, please change the EthereumVersion to EthereumVersion_Eth2 by calling this method:
WithEthereumVersion(config.EthereumVersion_Eth2).
If you are using a TOML file, please change the EthereumVersion to "eth2" in the TOML file:
[PrivateEthereumNetwork]
ethereum_version="eth2"
`
return fmt.Errorf(msg, Eth1NotSupportedByRethMsg)
}

switch strings.ToLower(*en.NodeLogLevel) {
case "trace", "debug", "info", "warn", "error":
default:
Expand Down Expand Up @@ -167,6 +181,7 @@ const (
ExecutionLayer_Nethermind ExecutionLayer = "nethermind"
ExecutionLayer_Erigon ExecutionLayer = "erigon"
ExecutionLayer_Besu ExecutionLayer = "besu"
ExecutionLayer_Reth ExecutionLayer = "reth"
)

type ConsensusLayer string
Expand Down
1 change: 0 additions & 1 deletion docker/test_env/erigon_eth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ 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 Down
4 changes: 4 additions & 0 deletions docker/test_env/ethereum_env.go
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,8 @@ func (en *EthereumNetwork) startEth2() (blockchain.EVMNetwork, RpcProvider, erro
case config.ExecutionLayer_Besu:
client, clientErr = NewBesuEth2(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, config.ConsensusLayer_Prysm, opts...)
chainReadyWaitTime = chainReadyWaitTime * 2
case config.ExecutionLayer_Reth:
client, clientErr = NewRethEth2(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, config.ConsensusLayer_Prysm, opts...)
default:
return blockchain.EVMNetwork{}, RpcProvider{}, fmt.Errorf(MsgUnsupportedExecutionLayer, *en.ExecutionLayer)
}
Expand Down Expand Up @@ -563,6 +565,8 @@ func (en *EthereumNetwork) startEth1() (blockchain.EVMNetwork, RpcProvider, erro
client, clientErr = NewErigonEth1(dockerNetworks, en.EthereumChainConfig, opts...)
case config.ExecutionLayer_Nethermind:
client, clientErr = NewNethermindEth1(dockerNetworks, en.EthereumChainConfig, opts...)
case config.ExecutionLayer_Reth:
clientErr = errors.New(config.Eth1NotSupportedByRethMsg)
default:
return blockchain.EVMNetwork{}, RpcProvider{}, fmt.Errorf(MsgUnsupportedExecutionLayer, *en.ExecutionLayer)
}
Expand Down
172 changes: 172 additions & 0 deletions docker/test_env/reth_base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package test_env

import (
"context"
"errors"
"fmt"
"testing"
"time"

"github.com/rs/zerolog"

tc "github.com/testcontainers/testcontainers-go"
tcwait "github.com/testcontainers/testcontainers-go/wait"

"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/config"
"github.com/smartcontractkit/chainlink-testing-framework/docker"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
)

const (
defaultRethEth2Image = "ghcr.io/paradigmxyz/reth:v1.0.0"
rethBaseImageName = "ghcr.io/paradigmxyz/reth"
rethGitRepo = "paradigmxyz/reth"
)

type Reth struct {
EnvComponent
ExternalHttpUrl string
InternalHttpUrl string
ExternalWsUrl string
InternalWsUrl string
InternalExecutionURL string
ExternalExecutionURL string
generatedDataHostDir string
chainConfig *config.EthereumChainConfig
consensusLayer config.ConsensusLayer
ethereumVersion config.EthereumVersion
l zerolog.Logger
t *testing.T
}

func (g *Reth) WithTestInstance(t *testing.T) ExecutionClient {
g.l = logging.GetTestLogger(t)
g.t = t
return g
}

func (g *Reth) StartContainer() (blockchain.EVMNetwork, error) {
if g.GetEthereumVersion() == config.EthereumVersion_Eth1 {
return blockchain.EVMNetwork{}, errors.New(config.Eth1NotSupportedByRethMsg)
}

r, err := g.getEth2ContainerRequest()

if err != nil {
return blockchain.EVMNetwork{}, err
}

l := logging.GetTestContainersGoTestLogger(g.t)
ct, err := docker.StartContainerWithRetry(g.l, tc.GenericContainerRequest{
ContainerRequest: *r,
Reuse: g.WasRecreated,
Started: true,
Logger: l,
})
if err != nil {
return blockchain.EVMNetwork{}, fmt.Errorf("cannot start reth container: %w", err)
}

host, err := GetHost(testcontext.Get(g.t), ct)
if err != nil {
return blockchain.EVMNetwork{}, err
}
httpPort, err := ct.MappedPort(testcontext.Get(g.t), NatPort(DEFAULT_EVM_NODE_HTTP_PORT))
if err != nil {
return blockchain.EVMNetwork{}, err
}

wsPort, err := ct.MappedPort(testcontext.Get(g.t), NatPort(DEFAULT_EVM_NODE_WS_PORT))
if err != nil {
return blockchain.EVMNetwork{}, err
}

if g.GetEthereumVersion() == config.EthereumVersion_Eth2 {
executionPort, err := ct.MappedPort(testcontext.Get(g.t), NatPort(ETH2_EXECUTION_PORT))
if err != nil {
return blockchain.EVMNetwork{}, err
}
g.InternalExecutionURL = FormatHttpUrl(g.ContainerName, ETH2_EXECUTION_PORT)
g.ExternalExecutionURL = FormatHttpUrl(host, executionPort.Port())
}

g.Container = ct
g.ExternalHttpUrl = FormatHttpUrl(host, httpPort.Port())
g.InternalHttpUrl = FormatHttpUrl(g.ContainerName, DEFAULT_EVM_NODE_HTTP_PORT)
g.ExternalWsUrl = FormatWsUrl(host, wsPort.Port())
g.InternalWsUrl = FormatWsUrl(g.ContainerName, DEFAULT_EVM_NODE_WS_PORT)

networkConfig := blockchain.SimulatedEVMNetwork
if g.GetEthereumVersion() == config.EthereumVersion_Eth1 {
networkConfig.Name = fmt.Sprintf("Private Eth-1-PoW [reth %s]", g.ContainerVersion)
} else {
networkConfig.Name = fmt.Sprintf("Private Eth-2-PoS [reth %s] + %s", g.ContainerVersion, g.consensusLayer)
}
networkConfig.URLs = []string{g.ExternalWsUrl}
networkConfig.HTTPURLs = []string{g.ExternalHttpUrl}
networkConfig.SimulationType = "Reth"

g.l.Info().Str("containerName", g.ContainerName).
Msg("Started Reth container")

return networkConfig, nil
}

func (g *Reth) GetInternalExecutionURL() string {
if g.GetEthereumVersion() == config.EthereumVersion_Eth1 {
panic("eth1 node doesn't have an execution URL")
}
return g.InternalExecutionURL
}

func (g *Reth) GetExternalExecutionURL() string {
if g.GetEthereumVersion() == config.EthereumVersion_Eth1 {
panic("eth1 node doesn't have an execution URL")
}
return g.ExternalExecutionURL
}

func (g *Reth) GetInternalHttpUrl() string {
return g.InternalHttpUrl
}

func (g *Reth) GetInternalWsUrl() string {
return g.InternalWsUrl
}

func (g *Reth) GetExternalHttpUrl() string {
return g.ExternalHttpUrl
}

func (g *Reth) GetExternalWsUrl() string {
return g.ExternalWsUrl
}

func (g *Reth) GetContainerName() string {
return g.ContainerName
}

func (g *Reth) GetContainer() *tc.Container {
return &g.Container
}

func (g *Reth) GetEthereumVersion() config.EthereumVersion {
return g.ethereumVersion
}

func (g *Reth) WaitUntilChainIsReady(ctx context.Context, waitTime time.Duration) error {
if g.GetEthereumVersion() == config.EthereumVersion_Eth1 {
return nil
}
waitForFirstBlock := tcwait.NewLogStrategy("Block added to canonical chain").WithPollInterval(1 * time.Second).WithStartupTimeout(waitTime)
return waitForFirstBlock.WaitUntilReady(ctx, *g.GetContainer())
}

func (g *Reth) GethConsensusMechanism() ConsensusMechanism {
if g.GetEthereumVersion() == config.EthereumVersion_Eth1 {
return ConsensusMechanism_PoW
}
return ConsensusMechanism_PoS
}
Loading

0 comments on commit 9172f5c

Please sign in to comment.