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

feat: Adding op-nethermind #46

Merged
merged 14 commits into from
Jul 4, 2024
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
7 changes: 3 additions & 4 deletions network_params.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
optimism_package:
participants:
- el_type: op-geth
- el_type: op-reth
- el_type: op-erigon
- el_type: op-nethermind
additional_services:
- blockscout
ethereum_package:
participants:
- el_type: geth
- el_type: reth
count: 2
network_params:
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 @@ -5,6 +5,8 @@ FACTORY_DEPLOYER_ADDRESS = "0x3fAB184622Dc19b6109349B94811493BF2a45362"
# 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 @@ -46,6 +48,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 @@ -58,6 +65,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 @@ -102,6 +112,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-4fd53a3",
}

DEFAULT_CL_IMAGES = {
Expand Down
Loading