Skip to content

Commit

Permalink
feat: Adding op-nethermind (#46)
Browse files Browse the repository at this point in the history
The op-nethermind image is found here:
`nethermindeth/nethermind:op-9b835cf`, it isn't stable/out yet so this
is probably best left as a WIP for now.

The major missing piece: op-nethermind needs a config.json file, but
op-node doesn't seem to output it. So we gotta find a way to template or
generate that file for the network before this PR can have a chance to
work.

---------

Signed-off-by: Barnabas Busa <[email protected]>
Co-authored-by: Barnabas Busa <[email protected]>
Co-authored-by: Barnabas Busa <[email protected]>
  • Loading branch information
3 people authored Jul 4, 2024
1 parent 0452e11 commit fba71dd
Show file tree
Hide file tree
Showing 9 changed files with 417 additions and 1 deletion.
13 changes: 13 additions & 0 deletions .github/tests/op-nethermind.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
optimism_package:
participants:
- el_type: op-geth
- el_type: op-nethermind
cl_type: op-node
ethereum_package:
participants:
- el_type: geth
- el_type: nethermind
network_params:
preset: minimal
additional_services:
- dora
2 changes: 2 additions & 0 deletions .github/tests/op-node.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ optimism_package:
cl_type: op-node
- el_type: op-erigon
cl_type: op-node
- el_type: op-nethermind
cl_type: op-node
ethereum_package:
participants:
- el_type: geth
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ optimism_package:
participants:
- el_type: op-geth
cl_type: op-node
- el_type: op-reth
- el_type: op-erigon
- el_type: op-nethermind
ethereum_package:
participants:
- el_type: geth
Expand Down
3 changes: 2 additions & 1 deletion network_params.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ optimism_package:
- el_type: op-geth
- el_type: op-reth
- el_type: op-erigon
- el_type: op-nethermind
additional_services:
- blockscout
ethereum_package:
Expand All @@ -13,4 +14,4 @@ ethereum_package:
preset: minimal
additional_services:
- dora
- blockscout
- blockscout
11 changes: 11 additions & 0 deletions src/contracts/contract_deployer.star
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ FACTORY_ADDRESS = "0x4e59b44847b379578588920cA78FbF26c0B4956C"
# raw tx data for deploying Create2Factory contract to L1
FACTORY_DEPLOYER_CODE = "0xf8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222"

CHAINSPEC_JQ_FILEPATH = "../../static_files/chainspec_template/gen2spec.jq"


def deploy_factory_contract(
plan,
Expand Down Expand Up @@ -49,6 +51,11 @@ def deploy_l2_contracts(
l2_config_env_vars,
l2_services_suffix,
):
chainspec_files_artifact = plan.upload_files(
src=CHAINSPEC_JQ_FILEPATH,
name="chainspec-config",
)

op_genesis = plan.run_sh(
name="op-deploy-l2-contracts",
description="Deploying L2 contracts (takes about a minute)",
Expand All @@ -61,6 +68,9 @@ def deploy_l2_contracts(
}
| l1_config_env_vars
| l2_config_env_vars,
files={
"/workspace/optimism/packages/contracts-bedrock/deploy-config/chainspec-generator/": chainspec_files_artifact,
},
store=[
StoreSpec(
src="/network-configs",
Expand Down Expand Up @@ -105,6 +115,7 @@ def deploy_l2_contracts(
"echo -n $GS_SEQUENCER_PRIVATE_KEY > /network-configs/GS_SEQUENCER_PRIVATE_KEY",
"echo -n $GS_BATCHER_PRIVATE_KEY > /network-configs/GS_BATCHER_PRIVATE_KEY",
"echo -n $GS_PROPOSER_PRIVATE_KEY > /network-configs/GS_PROPOSER_PRIVATE_KEY",
"cat /network-configs/genesis.json | jq --from-file /workspace/optimism/packages/contracts-bedrock/deploy-config/chainspec-generator/gen2spec.jq > /network-configs/chainspec.json",
]
),
wait="300s",
Expand Down
213 changes: 213 additions & 0 deletions src/el/op-nethermind/op_nethermind_launcher.star
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
shared_utils = import_module(
"github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star"
)

el_context = import_module(
"github.com/ethpandaops/ethereum-package/src/el/el_context.star"
)
el_admin_node_info = import_module(
"github.com/ethpandaops/ethereum-package/src/el/el_admin_node_info.star"
)

node_metrics = import_module(
"github.com/ethpandaops/ethereum-package/src/node_metrics_info.star"
)
constants = import_module(
"github.com/ethpandaops/ethereum-package/src/package_io/constants.star"
)

RPC_PORT_NUM = 8545
WS_PORT_NUM = 8546
DISCOVERY_PORT_NUM = 30303
ENGINE_RPC_PORT_NUM = 8551
METRICS_PORT_NUM = 9001

# The min/max CPU/memory that the execution node can use
EXECUTION_MIN_CPU = 300
EXECUTION_MIN_MEMORY = 512

# Port IDs
RPC_PORT_ID = "rpc"
WS_PORT_ID = "ws"
TCP_DISCOVERY_PORT_ID = "tcp-discovery"
UDP_DISCOVERY_PORT_ID = "udp-discovery"
ENGINE_RPC_PORT_ID = "engine-rpc"
ENGINE_WS_PORT_ID = "engineWs"
METRICS_PORT_ID = "metrics"

# TODO(old) Scale this dynamically based on CPUs available and Nethermind nodes mining
NUM_MINING_THREADS = 1

METRICS_PATH = "/debug/metrics/prometheus"

# The dirpath of the execution data directory on the client container
EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER = "/data/nethermind/execution-data"


def get_used_ports(discovery_port=DISCOVERY_PORT_NUM):
used_ports = {
RPC_PORT_ID: shared_utils.new_port_spec(
RPC_PORT_NUM,
shared_utils.TCP_PROTOCOL,
shared_utils.HTTP_APPLICATION_PROTOCOL,
),
WS_PORT_ID: shared_utils.new_port_spec(WS_PORT_NUM, shared_utils.TCP_PROTOCOL),
TCP_DISCOVERY_PORT_ID: shared_utils.new_port_spec(
discovery_port, shared_utils.TCP_PROTOCOL
),
UDP_DISCOVERY_PORT_ID: shared_utils.new_port_spec(
discovery_port, shared_utils.UDP_PROTOCOL
),
ENGINE_RPC_PORT_ID: shared_utils.new_port_spec(
ENGINE_RPC_PORT_NUM,
shared_utils.TCP_PROTOCOL,
),
METRICS_PORT_ID: shared_utils.new_port_spec(
METRICS_PORT_NUM, shared_utils.TCP_PROTOCOL
),
}
return used_ports


VERBOSITY_LEVELS = {
constants.GLOBAL_LOG_LEVEL.error: "1",
constants.GLOBAL_LOG_LEVEL.warn: "2",
constants.GLOBAL_LOG_LEVEL.info: "3",
constants.GLOBAL_LOG_LEVEL.debug: "4",
constants.GLOBAL_LOG_LEVEL.trace: "5",
}


def launch(
plan,
launcher,
service_name,
image,
existing_el_clients,
sequencer_enabled,
sequencer_context,
):
network_name = shared_utils.get_network_name(launcher.network)

config = get_config(
plan,
launcher.el_cl_genesis_data,
launcher.jwt_file,
launcher.network,
launcher.network_id,
image,
service_name,
existing_el_clients,
sequencer_enabled,
sequencer_context,
)

service = plan.add_service(service_name, config)

enode = el_admin_node_info.get_enode_for_node(plan, service_name, RPC_PORT_ID)

metrics_url = "{0}:{1}".format(service.ip_address, METRICS_PORT_NUM)
nethermind_metrics_info = node_metrics.new_node_metrics_info(
service_name, METRICS_PATH, metrics_url
)

http_url = "http://{0}:{1}".format(service.ip_address, RPC_PORT_NUM)
ws_url = "ws://{0}:{1}".format(service.ip_address, WS_PORT_NUM)

return el_context.new_el_context(
"op-nethermind",
"",
enode,
service.ip_address,
RPC_PORT_NUM,
WS_PORT_NUM,
ENGINE_RPC_PORT_NUM,
http_url,
service_name,
[nethermind_metrics_info],
)


def get_config(
plan,
el_cl_genesis_data,
jwt_file,
network,
network_id,
image,
service_name,
existing_el_clients,
sequencer_enabled,
sequencer_context,
):
discovery_port = DISCOVERY_PORT_NUM
used_ports = get_used_ports(discovery_port)
cmd = [
"--log=debug",
"--datadir=" + EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER,
"--Init.WebSocketsEnabled=true",
"--JsonRpc.Enabled=true",
"--JsonRpc.EnabledModules=net,eth,consensus,subscribe,web3,admin",
"--JsonRpc.Host=0.0.0.0",
"--JsonRpc.Port={0}".format(RPC_PORT_NUM),
"--JsonRpc.WebSocketsPort={0}".format(WS_PORT_NUM),
"--JsonRpc.EngineHost=0.0.0.0",
"--JsonRpc.EnginePort={0}".format(ENGINE_RPC_PORT_NUM),
"--Network.ExternalIp=" + constants.PRIVATE_IP_ADDRESS_PLACEHOLDER,
"--Network.DiscoveryPort={0}".format(discovery_port),
"--Network.P2PPort={0}".format(discovery_port),
"--JsonRpc.JwtSecretFile=" + constants.JWT_MOUNT_PATH_ON_CONTAINER,
"--Metrics.Enabled=true",
"--Metrics.ExposePort={0}".format(METRICS_PORT_NUM),
"--Metrics.ExposeHost=0.0.0.0",
]
if not sequencer_enabled:
cmd.append(
"--Optimism.SequencerUrl={0}".format(sequencer_context.beacon_http_url)
)

if len(existing_el_clients) > 0:
cmd.append(
"--Discovery.Bootnodes="
+ ",".join(
[
ctx.enode
for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES]
]
)
)

# TODO: Adding the chainspec and config separately as we may want to have support for public networks and shadowforks
cmd.append("--config=none.cfg")
cmd.append(
"--Init.ChainSpecPath="
+ constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER
+ "/chainspec.json"
)

files = {
constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data,
constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file,
}

return ServiceConfig(
image=image,
ports=used_ports,
cmd=cmd,
files=files,
private_ip_address_placeholder=constants.PRIVATE_IP_ADDRESS_PLACEHOLDER,
)


def new_nethermind_launcher(
el_cl_genesis_data,
jwt_file,
network,
network_id,
):
return struct(
el_cl_genesis_data=el_cl_genesis_data,
jwt_file=jwt_file,
network=network,
network_id=network_id,
)
10 changes: 10 additions & 0 deletions src/el_cl_launcher.star
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ shared_utils = import_module(
op_geth = import_module("./el/op-geth/op_geth_launcher.star")
op_reth = import_module("./el/op-reth/op_reth_launcher.star")
op_erigon = import_module("./el/op-erigon/op_erigon_launcher.star")
op_nethermind = import_module("./el/op-nethermind/op_nethermind_launcher.star")
# CL
op_node = import_module("./cl/op-node/op_node_launcher.star")

Expand Down Expand Up @@ -51,6 +52,15 @@ def launch(
),
"launch_method": op_erigon.launch,
},
"op-nethermind": {
"launcher": op_nethermind.new_nethermind_launcher(
el_cl_data,
jwt_file,
network_params.network,
network_params.network_id,
),
"launch_method": op_nethermind.launch,
},
}

cl_launchers = {
Expand Down
1 change: 1 addition & 0 deletions src/package_io/input_parser.star
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ DEFAULT_EL_IMAGES = {
"op-geth": "us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:latest",
"op-reth": "parithoshj/op-reth:latest",
"op-erigon": "testinprod/op-erigon:latest",
"op-nethermind": "nethermindeth/nethermind:op-c482d56",
}

DEFAULT_CL_IMAGES = {
Expand Down
Loading

0 comments on commit fba71dd

Please sign in to comment.