Skip to content

Commit

Permalink
add otterscan to kurtosis (#1519)
Browse files Browse the repository at this point in the history
Signed-off-by: nidhi-singh02 <[email protected]>
Co-authored-by: corduroy <[email protected]>
  • Loading branch information
nidhi-singh02 and corduroybera authored Jul 18, 2024
1 parent 9b59273 commit 6bc9394
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 22 deletions.
4 changes: 3 additions & 1 deletion kurtosis/beaconkit-all.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ network_configuration:
- el_type: besu
replicas: 0
- el_type: erigon
replicas: 0
replicas: 1
- el_type: ethereumjs
replicas: 0
seed_nodes:
Expand Down Expand Up @@ -118,3 +118,5 @@ additional_services:
- name: "pyroscope"
- name: "blockscout"
client: "el-full-reth-0"
- name: "otterscan" # otterscan supports only erigon nodes
client: "el-full-erigon-3"
11 changes: 8 additions & 3 deletions kurtosis/main.star
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pyroscope = import_module("./src/observability/pyroscope/pyroscope.star")
tx_fuzz = import_module("./src/services/tx_fuzz/launcher.star")
blutgang = import_module("./src/services/blutgang/launcher.star")
blockscout = import_module("./src/services/blockscout/launcher.star")
otterscan = import_module("./src/services/otterscan/launcher.star")

def run(plan, network_configuration = {}, node_settings = {}, eth_json_rpc_endpoints = [], additional_services = [], metrics_enabled_services = []):
"""
Expand Down Expand Up @@ -103,7 +104,7 @@ def run(plan, network_configuration = {}, node_settings = {}, eth_json_rpc_endpo
full_node_el_client_configs.append(el_client_config)

if full_node_el_client_configs != []:
full_node_el_clients = execution.deploy_nodes(plan, full_node_el_client_configs)
full_node_el_clients = execution.deploy_nodes(plan, full_node_el_client_configs, True)

for n, full in enumerate(full_nodes):
metrics_enabled_services = execution.add_metrics(metrics_enabled_services, full, full.el_service_name, full_node_el_clients[full.el_service_name], node_modules)
Expand All @@ -117,7 +118,6 @@ def run(plan, network_configuration = {}, node_settings = {}, eth_json_rpc_endpo
services = plan.add_services(
configs = full_node_configs,
)

for n, full_node in enumerate(full_nodes):
# excluding ethereumjs from metrics as it is the last full node in the args file beaconkit-all.yaml, TO-DO: to improve this later
peer_info = beacond.get_peer_info(plan, full_node.cl_service_name)
Expand Down Expand Up @@ -223,5 +223,10 @@ def run(plan, network_configuration = {}, node_settings = {}, eth_json_rpc_endpo
s.client,
False,
)

elif s.name == "otterscan":
plan.print("Launching otterscan")
otterscan.launch_otterscan(
plan,
s.client,
)
plan.print("Successfully launched development network")
15 changes: 14 additions & 1 deletion kurtosis/src/lib/service_config.star
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def get_service_config_template(
name,
image,
ports = None,
public_ports = None,
files = None,
entrypoint = None,
cmd = None,
Expand All @@ -39,6 +40,7 @@ def get_service_config_template(
"name": name,
"image": image,
"ports": ports,
"public_ports": public_ports,
"files": files,
"entrypoint": entrypoint,
"cmd": cmd,
Expand Down Expand Up @@ -131,12 +133,23 @@ def validate_service_config_types(service_config):
# TODO(validation): Implement validation for tolerations
# TODO(validation): Implement validation for node_selectors

def create_from_config(config):
def create_public_port_specs_from_config(config, is_full_node):
ports = {}
if is_full_node:
ports = {}
for port_key, port_spec in config["public_ports"].items():
ports[port_key] = port_spec_lib.create_port_spec(port_spec)

return ports

def create_from_config(config, is_full_node = False):
validate_service_config_types(config)

return ServiceConfig(
image = config["image"],
ports = port_spec_lib.create_port_specs_from_config(config),
# public port exposed for erigon node
public_ports = create_public_port_specs_from_config(config, is_full_node) if config["public_ports"] else {},
files = config["files"] if config["files"] else {},
entrypoint = config["entrypoint"] if config["entrypoint"] else [],
cmd = [" ".join(config["cmd"])] if config["cmd"] else [],
Expand Down
2 changes: 1 addition & 1 deletion kurtosis/src/nodes/execution/erigon/config.star
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ CMD = [
"--port",
str(DISCOVERY_PORT_NUM),
"--http.api",
"eth,erigon,engine,web3,net,debug,trace,txpool,admin",
"eth,erigon,engine,web3,net,debug,trace,txpool,admin,ots",
"--http.vhosts",
"'*'",
"--ws",
Expand Down
47 changes: 31 additions & 16 deletions kurtosis/src/nodes/execution/execution.star
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
constants = import_module("../../constants.star")
service_config_lib = import_module("../../lib/service_config.star")
builtins = import_module("../../lib/builtins.star")
port_spec_lib = import_module("../../lib/port_spec.star")
shared_utils = import_module("github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star")

RPC_PORT_NUM = 8545
ENGINE_RPC_PORT_NUM = 8551
PUBLIC_RPC_PORT_NUM = 8547

# Port IDs
RPC_PORT_ID = "eth-json-rpc"
Expand All @@ -15,20 +18,32 @@ def get_default_service_config(node_struct, node_module):
node_labels = dict(settings.labels)
node_labels["node_type"] = "execution"

sc = service_config_lib.get_service_config_template(
name = node_struct.el_service_name,
image = node_struct.el_image,
ports = node_module.USED_PORTS_TEMPLATE,
entrypoint = node_module.ENTRYPOINT,
cmd = node_module.CMD,
files = node_module.FILES,
min_cpu = settings.specs.min_cpu,
max_cpu = settings.specs.max_cpu,
min_memory = settings.specs.min_memory,
max_memory = settings.specs.max_memory,
labels = node_labels,
node_selectors = settings.node_selectors,
)
# Define common parameters
common_params = {
"name": node_struct.el_service_name,
"image": node_struct.el_image,
"ports": node_module.USED_PORTS_TEMPLATE,
"entrypoint": node_module.ENTRYPOINT,
"cmd": node_module.CMD,
"files": node_module.FILES,
"min_cpu": settings.specs.min_cpu,
"max_cpu": settings.specs.max_cpu,
"min_memory": settings.specs.min_memory,
"max_memory": settings.specs.max_memory,
"labels": node_labels,
"node_selectors": settings.node_selectors,
}

# Check if the node_struct.el_image has erigon keyword in it
# For otterscan, we need erigon RPC URL to connect to. By default, kurtosis assigns random public port to the service.
# We need to assign a specific port to the service to connect to the RPC URL.
# Note : public port is not supported on kubenernetes
if "erigon" in node_struct.el_image:
# Update common parameters with erigon-specific ones
common_params["public_ports"] = {"eth-json-rpc": port_spec_lib.get_port_spec_template(PUBLIC_RPC_PORT_NUM, shared_utils.TCP_PROTOCOL)}

# Get the service config template
sc = service_config_lib.get_service_config_template(**common_params)

return sc

Expand Down Expand Up @@ -98,10 +113,10 @@ def add_bootnodes(node_module, config, bootnodes):

return config

def deploy_nodes(plan, configs):
def deploy_nodes(plan, configs, is_full_node = False):
service_configs = {}
for config in configs:
service_configs[config["name"]] = service_config_lib.create_from_config(config)
service_configs[config["name"]] = service_config_lib.create_from_config(config, is_full_node)

return plan.add_services(
configs = service_configs,
Expand Down
36 changes: 36 additions & 0 deletions kurtosis/src/services/otterscan/launcher.star
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
shared_utils = import_module("github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star")

SERVICE_NAME = "otterscan"
IMAGE_NAME = "otterscan/otterscan:latest"
HTTP_PORT_ID = "http"
HTTP_PORT_NUMBER = 80
USED_PORTS = {
HTTP_PORT_ID: shared_utils.new_port_spec(
HTTP_PORT_NUMBER,
shared_utils.TCP_PROTOCOL,
shared_utils.HTTP_APPLICATION_PROTOCOL,
),
}

def launch_otterscan(
plan,
client_from_user):
# Currently fetching the public port from service config is not allowed,
# .ports["eth-json-rpc"].number returns the private port. Hence hardcoding the public port.
if client_from_user.split("-")[2] != "erigon":
fail("Currently only erigon client is supported for otterscan")
config = get_config()
plan.add_service(SERVICE_NAME, config)

def get_config():
public_rpc_port_num = 8547
el_client_rpc_url = "http://localhost:{}/".format(
public_rpc_port_num,
)
return ServiceConfig(
image = IMAGE_NAME,
ports = USED_PORTS,
env_vars = {
"ERIGON_URL": el_client_rpc_url,
},
)

0 comments on commit 6bc9394

Please sign in to comment.