Commit f8289cb4 authored by Barnabas Busa's avatar Barnabas Busa Committed by GitHub

feat: enable syncing ephemery (#459)

parent b9523cb7
......@@ -6,7 +6,7 @@ participants:
- el_client_type: nethermind
el_client_image: ethpandaops/nethermind:master
cl_client_type: prysm
cl_client_image: ethpandaops/prysm:develop,ethpandaops/prysm-validator:develop
cl_client_image: gcr.io/prysmaticlabs/prysm/beacon-chain:latest,gcr.io/prysmaticlabs/prysm/validator:latest
- el_client_type: erigon
el_client_image: ethpandaops/erigon:devel
cl_client_type: nimbus
......@@ -24,5 +24,5 @@ participants:
cl_client_type: teku
cl_client_image: ethpandaops/teku:master
network_params:
network: "dencun-devnet-12"
network: "ephemery"
additional_services: []
......@@ -674,8 +674,7 @@ This note is from 2023-10-05
`flashbots/mev-boost-relay:0.27` and later support `capella_fork_epoch` at `0` but this seems to require a few flags enabled
on the `lighthouse` beacon client including `--always-prefer-builder-payload` and `--disable-peer-scoring`
Users are recommended to use [`examples/capella-mev.yaml`](./examples/capella-mev.yaml); as inspiration for reliable payload
delivery.
Users are recommended to browse the example tests [`./.github/tests`](./.github/tests); as inspiration for different ways to use the package.
## Pre-funded accounts at Genesis
......
Please find the example configurations in the [../.github/tests](../.github/tests) directory.
mev_type: full
participants:
- el_client_type: geth
cl_client_type: lighthouse
cl_client_image: ethpandaops/lighthouse:unstable-c55608b
beacon_extra_params:
- "--always-prefer-builder-payload"
- "--disable-peer-scoring"
network_config:
deneb_fork_epoch: 1
mev_params:
mev_flood_seconds_per_bundle: 12
mev_flood_extra_args:
- "--txsPerBundle=300"
mev_flood_image: flashbots/mev-flood:0.0.9
mev_relay_image: flashbots/mev-boost-relay:0.28.0a7
mev_boost_image: flashbots/mev-boost:1.6.4844.dev5
mev_builder_image: flashbots/builder:1.13.2.4844.dev7-4d161de
participants:
- el_client_type: geth
el_client_image: ethpandaops/geth:master-5b57727
cl_client_type: lighthouse
cl_client_image: ethpandaops/lighthouse:proposer-signature-cache-29ecfc3
- el_client_type: erigon
el_client_image: ethpandaops/erigon:devel-8cfafa4
cl_client_type: lodestar
cl_client_image: ethpandaops/lodestar:blobs-inclproof-d5a5a47
- el_client_type: nethermind
el_client_image: ethpandaops/nethermind:master-dcec565
cl_client_type: teku
cl_client_image: ethpandaops/teku:master-16c4354
- el_client_type: besu
el_client_image: ethpandaops/besu:main-be5cc68
cl_client_type: teku
cl_client_image: ethpandaops/teku:master-16c4354
- el_client_type: reth
el_client_image: ethpandaops/reth:main-b0c4d99
cl_client_type: nimbus
cl_client_image: ethpandaops/nimbus:unstable-15147cc
- el_client_type: geth
el_client_image: ethpandaops/geth:master-5b57727
cl_client_type: prysm
cl_client_image: ethpandaops/prysm:develop-381116a,ethpandaops/prysm-validator:develop-linux-amd64-381116a
network_params:
deneb_fork_epoch: 1
additional_services:
- el_forkmon
- tx_spammer
- dora
snooper_enabled: true
participants:
- el_client_type: geth
el_client_image: ethpandaops/geth:gballet-kaustinen-with-shapella-fc8f4b9
cl_client_type: lighthouse
cl_client_image: ethpandaops/lighthouse:verkle-trees-capella-2ffb8a9
- el_client_type: geth
el_client_image: ethpandaops/geth:gballet-kaustinen-with-shapella-fc8f4b9
cl_client_type: lodestar
cl_client_image: ethpandaops/lodestar:g11tech-verge-815364b
- el_client_type: nethermind
el_client_image: nethermindeth/nethermind:kaustinen-648c6b8
cl_client_type: lodestar
cl_client_image: ethpandaops/lodestar:g11tech-verge-815364b
validator_count: 0
el_client_log_level: "debug"
- el_client_type: nethermind
el_client_image: nethermindeth/nethermind:kaustinen-648c6b8
cl_client_type: lodestar
cl_client_image: ethpandaops/lodestar:g11tech-verge-815364b
validator_count: 0
el_client_log_level: "debug"
network_params:
electra_fork_epoch: 0
genesis_delay: 0
seconds_per_slot: 8
additional_services:
- el_forkmon
- tx_spammer
- dora
- prometheus_grafana
snooper_enabled: true
ethereum_metrics_exporter_enabled: true
participants:
- el_client_type: geth
el_client_image: ethpandaops/geth:gballet-kaustinen-with-shapella-fc8f4b9
cl_client_type: lighthouse
cl_client_image: ethpandaops/lighthouse:verkle-trees-capella-2ffb8a9
count: 2
- el_client_type: geth
el_client_image: ethpandaops/geth:gballet-kaustinen-with-shapella-fc8f4b9
cl_client_type: lodestar
cl_client_image: ethpandaops/lodestar:g11tech-verge-815364b
network_params:
electra_fork_epoch: 0
additional_services:
- el_forkmon
- tx_spammer
- dora
snooper_enabled: true
participants:
- el_client_type: geth
el_client_image: ethpandaops/geth:transition-post-genesis-1d80ebd
cl_client_type: lighthouse
cl_client_image: ethpandaops/lighthouse:verkle-trees-capella-2ffb8a9
count: 2
- el_client_type: geth
el_client_image: ethpandaops/geth:transition-post-genesis-1d80ebd
cl_client_type: lodestar
cl_client_image: ethpandaops/lodestar:g11tech-verge-815364b
network_params:
electra_fork_epoch: 1
additional_services:
- el_forkmon
- tx_spammer
- dora
snooper_enabled: true
......@@ -128,7 +128,7 @@ def run(plan, args={}):
all_cl_client_contexts,
args_with_right_defaults.participants,
)
if network_params.network == "kurtosis":
if network_params.network == constants.NETWORK_NAME.kurtosis:
if network_params.deneb_fork_epoch != 0:
plan.print("Launching 4788 contract deployer")
el_uri = "http://{0}:{1}".format(
......
......@@ -353,46 +353,59 @@ def get_beacon_config(
"--metrics-allow-origin=*",
"--metrics-port={0}".format(BEACON_METRICS_PORT_NUM),
# ^^^^^^^^^^^^^^^^^^^ METRICS CONFIG ^^^^^^^^^^^^^^^^^^^^^
# Enable this flag once we have https://github.com/sigp/lighthouse/issues/5054 fixed
# "--allow-insecure-genesis-sync",
]
if network not in constants.PUBLIC_NETWORKS:
cmd.append("--testnet-dir=" + constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER)
else:
cmd.append("--network=" + network)
cmd.append("--checkpoint-sync-url=" + constants.CHECKPOINT_SYNC_URL[network])
if network == "kurtosis":
if boot_cl_client_ctxs != None:
if network == constants.NETWORK_NAME.kurtosis:
if boot_cl_client_ctxs != None:
cmd.append(
"--boot-nodes="
+ ",".join(
[
ctx.enr
for ctx in boot_cl_client_ctxs[: constants.MAX_ENR_ENTRIES]
]
)
)
cmd.append(
"--trusted-peers="
+ ",".join(
[
ctx.peer_id
for ctx in boot_cl_client_ctxs[: constants.MAX_ENR_ENTRIES]
]
)
)
elif network == constants.NETWORK_NAME.ephemery:
cmd.append(
"--checkpoint-sync-url=" + constants.CHECKPOINT_SYNC_URL[network]
)
cmd.append(
"--boot-nodes="
+ ",".join(
[
ctx.enr
for ctx in boot_cl_client_ctxs[: constants.MAX_ENR_ENTRIES]
]
+ shared_utils.get_devnet_enrs_list(
plan, el_cl_genesis_data.files_artifact_uuid
)
)
else: # Devnets
# TODO Remove once checkpoint sync is working for verkle
if constants.NETWORK_NAME.verkle not in network:
cmd.append(
"--checkpoint-sync-url=https://checkpoint-sync.{0}.ethpandaops.io".format(
network
)
)
cmd.append(
"--trusted-peers="
+ ",".join(
[
ctx.peer_id
for ctx in boot_cl_client_ctxs[: constants.MAX_ENR_ENTRIES]
]
"--boot-nodes="
+ shared_utils.get_devnet_enrs_list(
plan, el_cl_genesis_data.files_artifact_uuid
)
)
elif network not in constants.PUBLIC_NETWORKS:
cmd.append(
"--checkpoint-sync-url=https://checkpoint-sync.{0}.ethpandaops.io".format(
network
)
)
cmd.append(
"--boot-nodes="
+ shared_utils.get_devnet_enrs_list(
plan, el_cl_genesis_data.files_artifact_uuid
)
)
else: # Public networks
cmd.append("--network=" + network)
cmd.append("--checkpoint-sync-url=" + constants.CHECKPOINT_SYNC_URL[network])
if len(extra_params) > 0:
# this is a repeated<proto type>, we convert it into Starlark
......
......@@ -327,7 +327,7 @@ def get_beacon_config(
+ constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER
+ "/genesis.ssz"
)
if network == "kurtosis": # kurtosis
if network == constants.NETWORK_NAME.kurtosis:
if bootnode_contexts != None:
cmd.append(
"--bootnodes="
......@@ -338,19 +338,29 @@ def get_beacon_config(
]
)
)
else: # devnet
elif network == constants.NETWORK_NAME.ephemery:
cmd.append("--checkpointSyncUrl=" + constants.CHECKPOINT_SYNC_URL[network])
cmd.append(
"--checkpointSyncUrl=https://checkpoint-sync.{0}.ethpandaops.io".format(
network
"--bootnodes="
+ shared_utils.get_devnet_enrs_list(
plan, el_cl_genesis_data.files_artifact_uuid
)
)
else: # Devnets
# TODO Remove once checkpoint sync is working for verkle
if constants.NETWORK_NAME.verkle not in network:
cmd.append(
"--checkpointSyncUrl=https://checkpoint-sync.{0}.ethpandaops.io".format(
network
)
)
cmd.append(
"--bootnodes="
+ shared_utils.get_devnet_enrs_list(
plan, el_cl_genesis_data.files_artifact_uuid
)
)
else: # public testnet
else: # Public testnet
cmd.append("--network=" + network)
cmd.append("--checkpointSyncUrl=" + constants.CHECKPOINT_SYNC_URL[network])
......
......@@ -147,7 +147,7 @@ def launch(
)
# Holesky has a bigger memory footprint, so it needs more memory
if launcher.network == "holesky":
if launcher.network == constants.NETWORK_NAME.holesky:
holesky_beacon_memory_limit = 4096
bn_max_mem = (
int(bn_max_mem) if int(bn_max_mem) > 0 else holesky_beacon_memory_limit
......@@ -160,7 +160,7 @@ def launch(
network_name = (
"devnets"
if launcher.network != "kurtosis"
if launcher.network != constants.NETWORK_NAME.kurtosis
and launcher.network not in constants.PUBLIC_NETWORKS
else launcher.network
)
......@@ -374,21 +374,20 @@ def get_beacon_config(
if node_keystore_files != None and not split_mode_enabled:
cmd.extend(validator_flags)
if network == "kurtosis":
if bootnode_contexts == None:
# Copied from https://github.com/status-im/nimbus-eth2/blob/67ab477a27e358d605e99bffeb67f98d18218eca/scripts/launch_local_testnet.sh#L417
# See explanation there
cmd.append("--subscribe-all-subnets")
else:
for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES]:
cmd.append("--bootstrap-node=" + ctx.enr)
cmd.append("--direct-peer=" + ctx.multiaddr)
elif network not in constants.PUBLIC_NETWORKS:
if network not in constants.PUBLIC_NETWORKS:
cmd.append(
"--bootstrap-file="
+ constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER
+ "/bootstrap_nodes.txt"
)
if network == constants.NETWORK_NAME.kurtosis:
if bootnode_contexts == None:
cmd.append("--subscribe-all-subnets")
else:
for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES]:
cmd.append("--bootstrap-node=" + ctx.enr)
cmd.append("--direct-peer=" + ctx.multiaddr)
if len(extra_params) > 0:
cmd.extend([param for param in extra_params])
......
......@@ -324,6 +324,7 @@ def get_beacon_config(
"--monitoring-port={0}".format(BEACON_MONITORING_PORT_NUM)
# ^^^^^^^^^^^^^^^^^^^ METRICS CONFIG ^^^^^^^^^^^^^^^^^^^^^
]
if network not in constants.PUBLIC_NETWORKS:
cmd.append("--p2p-static-id=true")
cmd.append(
......@@ -336,22 +337,41 @@ def get_beacon_config(
+ constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER
+ "/genesis.ssz",
)
if network == "kurtosis": # Kurtosis
if network == constants.NETWORK_NAME.kurtosis:
if bootnode_contexts != None:
for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES]:
cmd.append("--peer=" + ctx.multiaddr)
cmd.append("--bootstrap-node=" + ctx.enr)
else: # Devnet
elif network == constants.NETWORK_NAME.ephemery:
cmd.append(
"--checkpoint-sync-url=https://checkpoint-sync.{0}.ethpandaops.io".format(
network
)
"--genesis-beacon-api-url=" + constants.CHECKPOINT_SYNC_URL[network]
)
cmd.append(
"--checkpoint-sync-url=" + constants.CHECKPOINT_SYNC_URL[network]
)
cmd.append(
"--bootstrap-node="
+ constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER
+ "/boot_enr.yaml"
)
else: # Devnets
# TODO Remove once checkpoint sync is working for verkle
if constants.NETWORK_NAME.verkle not in network:
cmd.append(
"--genesis-beacon-api-url=https://checkpoint-sync.{0}.ethpandaops.io".format(
network
)
)
cmd.append(
"--checkpoint-sync-url=https://checkpoint-sync.{0}.ethpandaops.io".format(
network
)
)
cmd.append(
"--bootstrap-node="
+ constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER
+ "/boot_enr.yaml"
)
else: # Public network
cmd.append("--{}".format(network))
cmd.append("--genesis-beacon-api-url=" + constants.CHECKPOINT_SYNC_URL[network])
......
......@@ -370,46 +370,61 @@ def get_beacon_config(
+ el_client_context.client_name,
]
if node_keystore_files != None and not split_mode_enabled:
cmd.extend(validator_flags)
if network not in constants.PUBLIC_NETWORKS:
cmd.append(
"--initial-state="
+ constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER
+ "/genesis.ssz"
)
else:
cmd.append("--checkpoint-sync-url=" + constants.CHECKPOINT_SYNC_URL[network])
if node_keystore_files != None and not split_mode_enabled:
cmd.extend(validator_flags)
if network == "kurtosis":
if bootnode_contexts != None:
if network == constants.NETWORK_NAME.kurtosis:
if bootnode_contexts != None:
cmd.append(
"--p2p-discovery-bootnodes="
+ ",".join(
[
ctx.enr
for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES]
]
)
)
cmd.append(
"--p2p-static-peers="
+ ",".join(
[
ctx.multiaddr
for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES]
]
)
)
elif network == constants.NETWORK_NAME.ephemery:
cmd.append(
"--checkpoint-sync-url=" + constants.CHECKPOINT_SYNC_URL[network]
)
cmd.append(
"--p2p-discovery-bootnodes="
+ ",".join(
[ctx.enr for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES]]
+ shared_utils.get_devnet_enrs_list(
plan, el_cl_genesis_data.files_artifact_uuid
)
)
else: # Devnets
# TODO Remove once checkpoint sync is working for verkle
if constants.NETWORK_NAME.verkle not in network:
cmd.append(
"--checkpoint-sync-url=https://checkpoint-sync.{0}.ethpandaops.io".format(
network
)
)
cmd.append(
"--p2p-static-peers="
+ ",".join(
[
ctx.multiaddr
for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES]
]
"--p2p-discovery-bootnodes="
+ shared_utils.get_devnet_enrs_list(
plan, el_cl_genesis_data.files_artifact_uuid
)
)
elif network not in constants.PUBLIC_NETWORKS:
cmd.append(
"--checkpoint-sync-url=https://checkpoint-sync.{0}.ethpandaops.io".format(
network
)
)
cmd.append(
"--p2p-discovery-bootnodes="
+ shared_utils.get_devnet_enrs_list(
plan, el_cl_genesis_data.files_artifact_uuid
)
)
else: # Public networks
cmd.append("--checkpoint-sync-url=" + constants.CHECKPOINT_SYNC_URL[network])
if len(extra_params) > 0:
# we do the list comprehension as the default extra_params is a proto repeated string
......
......@@ -198,7 +198,7 @@ def get_config(
else:
cmd.append("--network=" + network)
if network == "kurtosis":
if network == constants.NETWORK_NAME.kurtosis:
if len(existing_el_clients) > 0:
cmd.append(
"--bootnodes="
......
......@@ -213,7 +213,7 @@ def get_config(
size=el_volume_size,
)
if network == "kurtosis":
if network == constants.NETWORK_NAME.kurtosis:
if len(existing_el_clients) > 0:
cmd.append(
"--bootnodes="
......
......@@ -197,7 +197,7 @@ def get_config(
else:
cmd.append("--network=" + network)
if network == "kurtosis":
if network == constants.NETWORK_NAME.kurtosis:
if len(existing_el_clients) > 0:
cmd.append(
"--bootnodes="
......
......@@ -184,8 +184,10 @@ def get_config(
el_volume_size,
):
# TODO: Remove this once electra fork has path based storage scheme implemented
if electra_fork_epoch != None or "verkle" in network:
if electra_fork_epoch == 0 or "verkle-gen" in network: # verkle-gen
if electra_fork_epoch != None or constants.NETWORK_NAME.verkle in network:
if (
electra_fork_epoch == 0 or constants.NETWORK_NAME.verkle + "-gen" in network
): # verkle-gen
init_datadir_cmd_str = "geth --datadir={0} --cache.preimages --override.prague={1} init {2}".format(
EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER,
final_genesis_timestamp,
......@@ -273,7 +275,7 @@ def get_config(
if "--ws.api" in arg:
cmd[index] = "--ws.api=admin,engine,net,eth,web3,debug,mev,flashbots"
if network == "kurtosis":
if network == constants.NETWORK_NAME.kurtosis:
if len(existing_el_clients) > 0:
cmd.append(
"--bootnodes="
......
......@@ -194,7 +194,7 @@ def get_config(
else:
cmd.append("--config=" + network)
if network == "kurtosis":
if network == constants.NETWORK_NAME.kurtosis:
if len(existing_el_clients) > 0:
cmd.append(
"--Network.StaticPeers="
......
......@@ -198,7 +198,7 @@ def get_config(
"--authrpc.addr=0.0.0.0",
"--metrics=0.0.0.0:{0}".format(METRICS_PORT_NUM),
]
if network == "kurtosis":
if network == constants.NETWORK_NAME.kurtosis:
if len(existing_el_clients) > 0:
cmd.append(
"--bootnodes="
......
......@@ -53,6 +53,16 @@ CAPELLA_FORK_VERSION = "0x40000038"
DENEB_FORK_VERSION = "0x50000038"
ELECTRA_FORK_VERSION = "0x60000038"
NETWORK_NAME = struct(
mainnet="mainnet",
goerli="goerli",
sepolia="sepolia",
holesky="holesky",
ephemery="ephemery",
kurtosis="kurtosis",
verkle="verkle",
)
PUBLIC_NETWORKS = (
"mainnet",
"goerli",
......@@ -72,6 +82,7 @@ CHECKPOINT_SYNC_URL = {
"goerli": "https://checkpoint-sync.goerli.ethpandaops.io",
"sepolia": "https://checkpoint-sync.sepolia.ethpandaops.io",
"holesky": "https://checkpoint-sync.holesky.ethpandaops.io",
"ephemery": "https://checkpointz.bordel.wtf/",
}
GENESIS_VALIDATORS_ROOT = {
......
......@@ -67,7 +67,7 @@ def launch_participant_network(
parallel_keystore_generation=False,
):
num_participants = len(participants)
if network_params.network == "kurtosis":
if network_params.network == constants.NETWORK_NAME.kurtosis:
# We are running a kurtosis network
plan.print("Generating cl validator key stores")
validator_data = None
......@@ -168,6 +168,27 @@ def launch_participant_network(
final_genesis_timestamp = constants.GENESIS_TIME[network_params.network]
network_id = constants.NETWORK_ID[network_params.network]
validator_data = None
elif network_params.network == constants.NETWORK_NAME.ephemery:
el_cl_genesis_data_uuid = plan.run_sh(
run="mkdir -p /network-configs/ && \
curl -o latest.tar.gz https://ephemery.dev/latest.tar.gz && \
tar xvzf latest.tar.gz -C /network-configs && \
cat /network-configs/genesis_validators_root.txt",
image="badouralix/curl-jq",
store=[StoreSpec(src="/network-configs/", name="el_cl_genesis_data")],
)
genesis_validators_root = el_cl_genesis_data_uuid.output
el_cl_data = el_cl_genesis_data.new_el_cl_genesis_data(
el_cl_genesis_data_uuid.files_artifacts[0],
genesis_validators_root,
)
final_genesis_timestamp = shared_utils.read_genesis_timestamp_from_config(
plan, el_cl_genesis_data_uuid.files_artifacts[0]
)
network_id = shared_utils.read_genesis_network_id_from_config(
plan, el_cl_genesis_data_uuid.files_artifacts[0]
)
validator_data = None
else:
# We are running a devnet
url = calculate_devnet_url(network_params.network)
......@@ -187,10 +208,10 @@ def launch_participant_network(
genesis_validators_root,
)
final_genesis_timestamp = shared_utils.read_genesis_timestamp_from_config(
plan, el_cl_genesis_uuid
plan, el_cl_genesis_data_uuid.files_artifacts[0]
)
network_id = shared_utils.read_genesis_network_id_from_config(
plan, el_cl_genesis_uuid
plan, el_cl_genesis_data_uuid.files_artifacts[0]
)
validator_data = None
......@@ -318,12 +339,12 @@ def launch_participant_network(
plan.print("Launching CL network")
prysm_password_relative_filepath = (
validator_data.prysm_password_relative_filepath
if network_params.network == "kurtosis"
if network_params.network == constants.NETWORK_NAME.kurtosis
else None
)
prysm_password_artifact_uuid = (
validator_data.prysm_password_artifact_uuid
if network_params.network == "kurtosis"
if network_params.network == constants.NETWORK_NAME.kurtosis
else None
)
cl_launchers = {
......@@ -371,7 +392,7 @@ def launch_participant_network(
all_xatu_sentry_contexts = []
preregistered_validator_keys_for_nodes = (
validator_data.per_node_keystores
if network_params.network == "kurtosis"
if network_params.network == constants.NETWORK_NAME.kurtosis
else None
)
......
......@@ -114,7 +114,7 @@ def read_genesis_timestamp_from_config(plan, filename):
packages=["PyYAML"],
run="""
import yaml
with open("/network-configs/config.yaml", "r") as f:
with open("/network-configs/network-configs/config.yaml", "r") as f:
yaml_data = yaml.safe_load(f)
min_genesis_time = int(yaml_data.get("MIN_GENESIS_TIME", 0))
......@@ -132,7 +132,7 @@ def read_genesis_network_id_from_config(plan, filename):
packages=["PyYAML"],
run="""
import yaml
with open("/network-configs/config.yaml", "r") as f:
with open("/network-configs/network-configs/config.yaml", "r") as f:
yaml_data = yaml.safe_load(f)
network_id = int(yaml_data.get("DEPOSIT_NETWORK_ID", 0))
print(network_id, end="")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment