From 72582e82e86c4f991d326692b2f73666ddc9420e Mon Sep 17 00:00:00 2001 From: kalo <24719519+KaloyanTanev@users.noreply.github.com> Date: Wed, 16 Sep 2026 12:27:29 +0300 Subject: [PATCH 1/9] compose: mount charon vc-config into validator clients --- compose-vc.yml | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/compose-vc.yml b/compose-vc.yml index 5e3e8483..28ce26b8 100644 --- a/compose-vc.yml +++ b/compose-vc.yml @@ -12,7 +12,9 @@ services: vc-lodestar: profiles: [vc-lodestar] image: chainsafe/lodestar:${VC_LODESTAR_VERSION:-v1.46.0} - depends_on: [charon] + depends_on: + charon: + condition: service_healthy entrypoint: /opt/lodestar/run.sh networks: [dvnode] environment: @@ -25,6 +27,7 @@ services: volumes: - ./lodestar/run.sh:/opt/lodestar/run.sh - .charon/validator_keys:/home/charon/validator_keys + - .charon/vc-config:/home/charon/vc-config:ro - ./data/lodestar:/opt/data # Keep data in lodestar and not vc-lodestar for backwards compatibility restart: unless-stopped @@ -41,7 +44,9 @@ services: context: nimbus args: VERSION: ${VC_NIMBUS_VERSION:-multiarch-v26.7.0} - depends_on: [charon] + depends_on: + charon: + condition: service_healthy networks: [dvnode] environment: BEACON_NODE_ADDRESS: http://charon:3600 @@ -51,6 +56,7 @@ services: volumes: - ./nimbus/run.sh:/home/user/data/run.sh - .charon/validator_keys:/home/validator_keys + - .charon/vc-config:/home/charon/vc-config:ro - ./data/vc-nimbus:/home/user/data restart: unless-stopped @@ -64,7 +70,9 @@ services: profiles: [vc-prysm] image: offchainlabs/prysm-validator:${VC_PRYSM_VERSION:-v7.1.8} platform: "linux/amd64" - depends_on: [charon] + depends_on: + charon: + condition: service_healthy networks: [dvnode] entrypoint: /home/prysm/run.sh environment: @@ -76,6 +84,7 @@ services: - ./prysm/run.sh:/home/prysm/run.sh - ./data/vc-prysm:/data/vc - .charon/validator_keys:/home/charon/validator_keys + - .charon/vc-config:/home/charon/vc-config:ro restart: unless-stopped # _ _ @@ -87,23 +96,19 @@ services: vc-teku: profiles: [vc-teku] image: consensys/teku:${VC_TEKU_VERSION:-26.8.0} - command: | - validator-client - --beacon-node-api-endpoint "http://charon:3600" - --network="${NETWORK}" - --data-base-path=/home/data - --validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" - --validators-keystore-locking-enabled false - --validators-external-signer-slashing-protection-enabled true - --validators-builder-registration-default-enabled ${BUILDER_API_ENABLED:-true} - --validators-proposer-default-fee-recipient "0x0000000000000000000000000000000000000000" - --Xobol-dvt-integration-enabled true - --Xvalidator-client-beacon-api-executor-threads=50 - depends_on: [charon] + entrypoint: /opt/teku/run.sh + environment: + NETWORK: ${NETWORK} + BUILDER_API_ENABLED: ${BUILDER_API_ENABLED:-true} + depends_on: + charon: + condition: service_healthy networks: [dvnode] labels: - "alloy-monitored=${VC_TEKU_ALLOY_MONITORED:-true}" volumes: + - ./teku/run.sh:/opt/teku/run.sh - .charon/validator_keys:/opt/charon/validator_keys + - .charon/vc-config:/opt/charon/vc-config:ro - ./data/vc-teku:/home/data restart: unless-stopped From ad66a4f85f82447959107bc56a0bcf40487ca783 Mon Sep 17 00:00:00 2001 From: kalo <24719519+KaloyanTanev@users.noreply.github.com> Date: Wed, 16 Sep 2026 12:27:33 +0300 Subject: [PATCH 2/9] teku: read proposer config from charon with zero-address fallback --- compose-vc.yml | 1 + teku/run.sh | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100755 teku/run.sh diff --git a/compose-vc.yml b/compose-vc.yml index 28ce26b8..06498be0 100644 --- a/compose-vc.yml +++ b/compose-vc.yml @@ -98,6 +98,7 @@ services: image: consensys/teku:${VC_TEKU_VERSION:-26.8.0} entrypoint: /opt/teku/run.sh environment: + BEACON_NODE_ADDRESS: http://charon:3600 NETWORK: ${NETWORK} BUILDER_API_ENABLED: ${BUILDER_API_ENABLED:-true} depends_on: diff --git a/teku/run.sh b/teku/run.sh new file mode 100755 index 00000000..9e9b0736 --- /dev/null +++ b/teku/run.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Use the charon-generated proposer config when available, otherwise fall back to a +# zero default fee recipient, which charon overrides pre-gloas. +PROPOSER_CONFIG=() +if [[ -f /opt/charon/vc-config/proposer-config.json ]]; then + echo "proposer-config.json found, applying proposer settings" + PROPOSER_CONFIG+=(--validators-proposer-config="/opt/charon/vc-config/proposer-config.json") +else + echo "proposer-config.json not found, running with zero default fee recipient" + PROPOSER_CONFIG+=(--validators-proposer-default-fee-recipient="0x0000000000000000000000000000000000000000") +fi + +exec /opt/teku/bin/teku validator-client \ + --beacon-node-api-endpoint "${BEACON_NODE_ADDRESS}" \ + --network="${NETWORK}" \ + --data-base-path=/home/data \ + --validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" \ + --validators-keystore-locking-enabled false \ + --validators-external-signer-slashing-protection-enabled true \ + --validators-builder-registration-default-enabled "${BUILDER_API_ENABLED}" \ + --Xobol-dvt-integration-enabled true \ + --Xvalidator-client-beacon-api-executor-threads=50 \ + "${PROPOSER_CONFIG[@]}" From 88c826a0f641a539b253f28d47574e88c234769f Mon Sep 17 00:00:00 2001 From: kalo <24719519+KaloyanTanev@users.noreply.github.com> Date: Wed, 16 Sep 2026 12:27:37 +0300 Subject: [PATCH 3/9] prysm: read proposer config from charon --- prysm/run.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/prysm/run.sh b/prysm/run.sh index afbd3990..7f1eda52 100755 --- a/prysm/run.sh +++ b/prysm/run.sh @@ -41,6 +41,14 @@ rm -r ${tmpkeys} echo "Imported all keys" +PROPOSER_SETTINGS=() +if [[ -f /home/charon/vc-config/proposer-config.json ]]; then + echo "proposer-config.json found, applying proposer settings" + PROPOSER_SETTINGS+=(--proposer-settings-file="/home/charon/vc-config/proposer-config.json") +else + echo "proposer-config.json not found, running without proposer settings" +fi + # Now run prysm VC /app/cmd/validator/validator --wallet-dir="$WALLET_DIR" \ --accept-terms-of-use=true \ @@ -50,4 +58,5 @@ echo "Imported all keys" --beacon-rest-api-provider="${BEACON_NODE_ADDRESS}" \ --beacon-rpc-provider="${BEACON_NODE_ADDRESS}" \ --"${NETWORK}" \ - --distributed + --distributed \ + "${PROPOSER_SETTINGS[@]}" From bcb729a1a46829e950705c215bb4ea103bbb67da Mon Sep 17 00:00:00 2001 From: kalo <24719519+KaloyanTanev@users.noreply.github.com> Date: Wed, 16 Sep 2026 12:27:41 +0300 Subject: [PATCH 4/9] lodestar: read proposer config from charon --- lodestar/run.sh | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lodestar/run.sh b/lodestar/run.sh index 8841cca8..fc4c6776 100755 --- a/lodestar/run.sh +++ b/lodestar/run.sh @@ -40,6 +40,18 @@ done echo "Processed all keys imported=${IMPORTED_COUNT}, existing=${EXISTING_COUNT}, total=$(ls /home/charon/validator_keys/keystore-*.json | wc -l)" +PROPOSER_SETTINGS="" +if [ -f /home/charon/vc-config/proposer-config.json ]; then + echo "proposer-config.json found, applying proposer settings" + # Lodestar only accepts yml/yaml file extensions; JSON is valid YAML. + cp /home/charon/vc-config/proposer-config.json /tmp/proposer-config.yml + PROPOSER_SETTINGS="--proposerSettingsFile=/tmp/proposer-config.yml" +else + echo "proposer-config.json not found, running without proposer settings" +fi + +# Word splitting of $PROPOSER_SETTINGS is intentional, it is empty or a single flag. +# shellcheck disable=SC2086 exec node /usr/app/packages/cli/bin/lodestar validator \ --dataDir="$DATA_DIR" \ --keystoresDir="$KEYSTORES_DIR" \ @@ -51,4 +63,5 @@ exec node /usr/app/packages/cli/bin/lodestar validator \ --beaconNodes="$BEACON_NODE_ADDRESS" \ --builder="$BUILDER_API_ENABLED" \ --builder.selection="$BUILDER_SELECTION" \ - --distributed + --distributed \ + $PROPOSER_SETTINGS From b5766f4b20416b942dcdf433889af1d623611637 Mon Sep 17 00:00:00 2001 From: kalo <24719519+KaloyanTanev@users.noreply.github.com> Date: Wed, 16 Sep 2026 12:27:45 +0300 Subject: [PATCH 5/9] nimbus: render per-validator proposer config from charon --- nimbus/Dockerfile | 5 +++++ nimbus/run.sh | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/nimbus/Dockerfile b/nimbus/Dockerfile index ad27351a..c671ab4e 100755 --- a/nimbus/Dockerfile +++ b/nimbus/Dockerfile @@ -6,4 +6,9 @@ FROM statusim/nimbus-validator-client:${VERSION} COPY --from=nimbusbn /home/user/nimbus_beacon_node /home/user/nimbus_beacon_node +# jq is used by run.sh to render per-validator proposer config files. +USER root +RUN apt-get update && apt-get install -y --no-install-recommends jq && rm -rf /var/lib/apt/lists/* +USER user + ENTRYPOINT ["/home/user/data/run.sh"] diff --git a/nimbus/run.sh b/nimbus/run.sh index 464f535b..a59e320b 100755 --- a/nimbus/run.sh +++ b/nimbus/run.sh @@ -35,6 +35,24 @@ rm -r ${tmpkeys} echo "Imported all keys" +if [[ -f /home/charon/vc-config/proposer-config.json ]]; then + echo "proposer-config.json found, rendering per-validator proposer settings" + + # Emit " " per validator. + jq -r '.proposer_config | to_entries[] | "\(.key) \(.value.fee_recipient) \(.value.builder.gas_limit)"' \ + /home/charon/vc-config/proposer-config.json | + while read -r pubkey fee_recipient gas_limit; do + for dir in "/home/user/data/validators/${pubkey}" "/home/user/data/validators/${pubkey#0x}"; do + if [[ -d "${dir}" ]]; then + echo "${fee_recipient}" >"${dir}/suggested_fee_recipient.hex" + echo "${gas_limit}" >"${dir}/suggested_gas_limit.json" + fi + done + done +else + echo "proposer-config.json not found, running without proposer settings" +fi + # Now run nimbus VC exec /home/user/nimbus_validator_client \ --data-dir=/home/user/data \ From 0c1ca5c8699b9530b95117ad8c8c85c0146a8c2e Mon Sep 17 00:00:00 2001 From: kalo <24719519+KaloyanTanev@users.noreply.github.com> Date: Thu, 17 Sep 2026 00:45:49 +0300 Subject: [PATCH 6/9] prysm: exec the validator client so it receives shutdown signals --- prysm/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prysm/run.sh b/prysm/run.sh index 7f1eda52..22ddac22 100755 --- a/prysm/run.sh +++ b/prysm/run.sh @@ -50,7 +50,7 @@ else fi # Now run prysm VC -/app/cmd/validator/validator --wallet-dir="$WALLET_DIR" \ +exec /app/cmd/validator/validator --wallet-dir="$WALLET_DIR" \ --accept-terms-of-use=true \ --datadir="/data/vc" \ --wallet-password-file="/wallet-password.txt" \ From cdcca8af289692d438ac8431616fdb6fe1abc607 Mon Sep 17 00:00:00 2001 From: kalo <24719519+KaloyanTanev@users.noreply.github.com> Date: Thu, 17 Sep 2026 00:46:29 +0300 Subject: [PATCH 7/9] vc: expose teku and prysm metrics on their default ports --- prometheus/prometheus.yml.example | 7 ++++++- prysm/run.sh | 1 + teku/run.sh | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/prometheus/prometheus.yml.example b/prometheus/prometheus.yml.example index bdb3b85b..00e99e5b 100644 --- a/prometheus/prometheus.yml.example +++ b/prometheus/prometheus.yml.example @@ -45,7 +45,12 @@ scrape_configs: - job_name: "validator-client" static_configs: - - targets: ["lodestar:5064","vc-lodestar:5064"] + - targets: + - "lodestar:5064" + - "vc-lodestar:5064" + - "vc-teku:8008" + - "vc-prysm:8081" + - "vc-nimbus:8108" # Debug - job_name: "node-exporter" static_configs: diff --git a/prysm/run.sh b/prysm/run.sh index 22ddac22..be287454 100755 --- a/prysm/run.sh +++ b/prysm/run.sh @@ -55,6 +55,7 @@ exec /app/cmd/validator/validator --wallet-dir="$WALLET_DIR" \ --datadir="/data/vc" \ --wallet-password-file="/wallet-password.txt" \ --enable-beacon-rest-api \ + --monitoring-host=0.0.0.0 \ --beacon-rest-api-provider="${BEACON_NODE_ADDRESS}" \ --beacon-rpc-provider="${BEACON_NODE_ADDRESS}" \ --"${NETWORK}" \ diff --git a/teku/run.sh b/teku/run.sh index 9e9b0736..dc77c0cd 100755 --- a/teku/run.sh +++ b/teku/run.sh @@ -21,4 +21,8 @@ exec /opt/teku/bin/teku validator-client \ --validators-builder-registration-default-enabled "${BUILDER_API_ENABLED}" \ --Xobol-dvt-integration-enabled true \ --Xvalidator-client-beacon-api-executor-threads=50 \ + --metrics-enabled=true \ + --metrics-interface=0.0.0.0 \ + --metrics-port=8008 \ + --metrics-host-allowlist="*" \ "${PROPOSER_CONFIG[@]}" From ec82eae424ca7cc5011388b9159404c2741da7c0 Mon Sep 17 00:00:00 2001 From: kalo <24719519+KaloyanTanev@users.noreply.github.com> Date: Thu, 17 Sep 2026 00:46:58 +0300 Subject: [PATCH 8/9] compose: normalize vc service definitions --- compose-vc.yml | 10 +++++----- nimbus/run.sh | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compose-vc.yml b/compose-vc.yml index 06498be0..bf2c4858 100644 --- a/compose-vc.yml +++ b/compose-vc.yml @@ -15,8 +15,8 @@ services: depends_on: charon: condition: service_healthy - entrypoint: /opt/lodestar/run.sh networks: [dvnode] + entrypoint: /opt/lodestar/run.sh environment: BEACON_NODE_ADDRESS: http://charon:3600 NETWORK: ${NETWORK} @@ -96,15 +96,15 @@ services: vc-teku: profiles: [vc-teku] image: consensys/teku:${VC_TEKU_VERSION:-26.8.0} + depends_on: + charon: + condition: service_healthy + networks: [dvnode] entrypoint: /opt/teku/run.sh environment: BEACON_NODE_ADDRESS: http://charon:3600 NETWORK: ${NETWORK} BUILDER_API_ENABLED: ${BUILDER_API_ENABLED:-true} - depends_on: - charon: - condition: service_healthy - networks: [dvnode] labels: - "alloy-monitored=${VC_TEKU_ALLOY_MONITORED:-true}" volumes: diff --git a/nimbus/run.sh b/nimbus/run.sh index a59e320b..07bec5f8 100755 --- a/nimbus/run.sh +++ b/nimbus/run.sh @@ -60,5 +60,5 @@ exec /home/user/nimbus_validator_client \ --doppelganger-detection=false \ --metrics \ --metrics-address=0.0.0.0 \ - --payload-builder=${BUILDER_API_ENABLED} \ + --payload-builder="${BUILDER_API_ENABLED}" \ --distributed From 0a7fe7537ba208a9b4377eff1878187a93f8697c Mon Sep 17 00:00:00 2001 From: kalo <24719519+KaloyanTanev@users.noreply.github.com> Date: Fri, 18 Sep 2026 18:31:13 +0300 Subject: [PATCH 9/9] vc: render native proposer settings from charon canonical config --- compose-vc.yml | 13 +++++++++++-- lodestar/run.sh | 23 ++++++++++++++++++++--- nimbus/run.sh | 24 ++++++++++++++---------- prysm/Dockerfile | 8 ++++++++ prysm/run.sh | 18 ++++++++++++++++-- teku/Dockerfile | 8 ++++++++ teku/run.sh | 21 +++++++++++++++++---- 7 files changed, 94 insertions(+), 21 deletions(-) create mode 100644 prysm/Dockerfile create mode 100644 teku/Dockerfile diff --git a/compose-vc.yml b/compose-vc.yml index bf2c4858..a86d42b7 100644 --- a/compose-vc.yml +++ b/compose-vc.yml @@ -68,7 +68,11 @@ services: vc-prysm: profiles: [vc-prysm] - image: offchainlabs/prysm-validator:${VC_PRYSM_VERSION:-v7.1.8} + image: "prysm-validator-client:${VC_PRYSM_VERSION:-v7.1.8}" + build: + context: prysm + args: + VERSION: ${VC_PRYSM_VERSION:-v7.1.8} platform: "linux/amd64" depends_on: charon: @@ -78,6 +82,7 @@ services: environment: BEACON_NODE_ADDRESS: http://charon:3600 NETWORK: ${NETWORK} + BUILDER_API_ENABLED: ${BUILDER_API_ENABLED:-true} labels: - "alloy-monitored=${VC_PRYSM_ALLOY_MONITORED:-true}" volumes: @@ -95,7 +100,11 @@ services: vc-teku: profiles: [vc-teku] - image: consensys/teku:${VC_TEKU_VERSION:-26.8.0} + image: "teku-validator-client:${VC_TEKU_VERSION:-26.8.0}" + build: + context: teku + args: + VERSION: ${VC_TEKU_VERSION:-26.8.0} depends_on: charon: condition: service_healthy diff --git a/lodestar/run.sh b/lodestar/run.sh index fc4c6776..b230db0e 100755 --- a/lodestar/run.sh +++ b/lodestar/run.sh @@ -40,11 +40,28 @@ done echo "Processed all keys imported=${IMPORTED_COUNT}, existing=${EXISTING_COUNT}, total=$(ls /home/charon/validator_keys/keystore-*.json | wc -l)" +# Render Lodestar's proposer settings from the charon-generated canonical config when +# available: entries only carry fields diverging from default_config, absent fields +# fall back to it. Lodestar only accepts yml/yaml file extensions; JSON is valid YAML. PROPOSER_SETTINGS="" if [ -f /home/charon/vc-config/proposer-config.json ]; then - echo "proposer-config.json found, applying proposer settings" - # Lodestar only accepts yml/yaml file extensions; JSON is valid YAML. - cp /home/charon/vc-config/proposer-config.json /tmp/proposer-config.yml + echo "proposer-config.json found, rendering lodestar proposer settings" + node -e ' + const fs = require("fs"); + const src = JSON.parse(fs.readFileSync(process.argv[1], "utf8")); + const d = src.default_config; + const out = { + proposer_config: {}, + default_config: {fee_recipient: d.fee_recipient, builder: {gas_limit: d.gas_limit}}, + }; + for (const [pubkey, entry] of Object.entries(src.proposer_config || {})) { + out.proposer_config[pubkey] = { + fee_recipient: entry.fee_recipient ?? d.fee_recipient, + builder: {gas_limit: entry.gas_limit ?? d.gas_limit}, + }; + } + fs.writeFileSync(process.argv[2], JSON.stringify(out)); + ' /home/charon/vc-config/proposer-config.json /tmp/proposer-config.yml PROPOSER_SETTINGS="--proposerSettingsFile=/tmp/proposer-config.yml" else echo "proposer-config.json not found, running without proposer settings" diff --git a/nimbus/run.sh b/nimbus/run.sh index 07bec5f8..b77c6875 100755 --- a/nimbus/run.sh +++ b/nimbus/run.sh @@ -38,17 +38,21 @@ echo "Imported all keys" if [[ -f /home/charon/vc-config/proposer-config.json ]]; then echo "proposer-config.json found, rendering per-validator proposer settings" - # Emit " " per validator. - jq -r '.proposer_config | to_entries[] | "\(.key) \(.value.fee_recipient) \(.value.builder.gas_limit)"' \ - /home/charon/vc-config/proposer-config.json | - while read -r pubkey fee_recipient gas_limit; do - for dir in "/home/user/data/validators/${pubkey}" "/home/user/data/validators/${pubkey#0x}"; do - if [[ -d "${dir}" ]]; then - echo "${fee_recipient}" >"${dir}/suggested_fee_recipient.hex" - echo "${gas_limit}" >"${dir}/suggested_gas_limit.json" - fi - done + # Resolve each imported validator's settings: proposer_config entries only carry + # fields diverging from default_config, absent fields fall back to it. + config=/home/charon/vc-config/proposer-config.json + for f in /home/validator_keys/keystore-*.json; do + pubkey="0x$(jq -r .pubkey "${f}")" + fee_recipient=$(jq -r --arg pk "${pubkey}" '.proposer_config[$pk].fee_recipient // .default_config.fee_recipient' "${config}") + gas_limit=$(jq -r --arg pk "${pubkey}" '.proposer_config[$pk].gas_limit // .default_config.gas_limit' "${config}") + + for dir in "/home/user/data/validators/${pubkey}" "/home/user/data/validators/${pubkey#0x}"; do + if [[ -d "${dir}" ]]; then + echo "${fee_recipient}" >"${dir}/suggested_fee_recipient.hex" + echo "${gas_limit}" >"${dir}/suggested_gas_limit.json" + fi done + done else echo "proposer-config.json not found, running without proposer settings" fi diff --git a/prysm/Dockerfile b/prysm/Dockerfile new file mode 100644 index 00000000..973787de --- /dev/null +++ b/prysm/Dockerfile @@ -0,0 +1,8 @@ +ARG VERSION + +FROM ghcr.io/jqlang/jq:1.8.0 AS jq + +FROM offchainlabs/prysm-validator:${VERSION} + +# jq is used by run.sh to render Prysm's proposer settings from the charon-generated config. +COPY --from=jq /jq /usr/local/bin/jq diff --git a/prysm/run.sh b/prysm/run.sh index be287454..c937c7e0 100755 --- a/prysm/run.sh +++ b/prysm/run.sh @@ -41,10 +41,24 @@ rm -r ${tmpkeys} echo "Imported all keys" +# Render Prysm's proposer settings from the charon-generated canonical config when available: +# entries only carry fields diverging from default_config, absent fields fall back to it. PROPOSER_SETTINGS=() if [[ -f /home/charon/vc-config/proposer-config.json ]]; then - echo "proposer-config.json found, applying proposer settings" - PROPOSER_SETTINGS+=(--proposer-settings-file="/home/charon/vc-config/proposer-config.json") + echo "proposer-config.json found, rendering prysm proposer settings" + jq --argjson enabled "${BUILDER_API_ENABLED}" ' + .default_config as $d | + { + proposer_config: (.proposer_config | map_values({ + fee_recipient: (.fee_recipient // $d.fee_recipient), + builder: {enabled: $enabled, gas_limit: (.gas_limit // $d.gas_limit)} + })), + default_config: { + fee_recipient: $d.fee_recipient, + builder: {enabled: $enabled, gas_limit: $d.gas_limit} + } + }' /home/charon/vc-config/proposer-config.json >/tmp/prysm-proposer-settings.json + PROPOSER_SETTINGS+=(--proposer-settings-file="/tmp/prysm-proposer-settings.json") else echo "proposer-config.json not found, running without proposer settings" fi diff --git a/teku/Dockerfile b/teku/Dockerfile new file mode 100644 index 00000000..2b09b72f --- /dev/null +++ b/teku/Dockerfile @@ -0,0 +1,8 @@ +ARG VERSION + +FROM ghcr.io/jqlang/jq:1.8.0 AS jq + +FROM consensys/teku:${VERSION} + +# jq is used by run.sh to render Teku's proposer config from the charon-generated one. +COPY --from=jq /jq /usr/local/bin/jq diff --git a/teku/run.sh b/teku/run.sh index dc77c0cd..1758824a 100755 --- a/teku/run.sh +++ b/teku/run.sh @@ -1,11 +1,24 @@ #!/bin/bash -# Use the charon-generated proposer config when available, otherwise fall back to a -# zero default fee recipient, which charon overrides pre-gloas. +# Render Teku's proposer config from the charon-generated canonical config when available: +# entries only carry fields diverging from default_config, absent fields fall back to it. +# Otherwise fall back to a zero default fee recipient, which charon overrides pre-gloas. PROPOSER_CONFIG=() if [[ -f /opt/charon/vc-config/proposer-config.json ]]; then - echo "proposer-config.json found, applying proposer settings" - PROPOSER_CONFIG+=(--validators-proposer-config="/opt/charon/vc-config/proposer-config.json") + echo "proposer-config.json found, rendering teku proposer config" + jq --argjson enabled "${BUILDER_API_ENABLED}" ' + .default_config as $d | + { + proposer_config: (.proposer_config | map_values({ + fee_recipient: (.fee_recipient // $d.fee_recipient), + builder: {enabled: $enabled, gas_limit: (.gas_limit // $d.gas_limit)} + })), + default_config: { + fee_recipient: $d.fee_recipient, + builder: {enabled: $enabled, gas_limit: $d.gas_limit} + } + }' /opt/charon/vc-config/proposer-config.json >/tmp/teku-proposer-config.json + PROPOSER_CONFIG+=(--validators-proposer-config="/tmp/teku-proposer-config.json") else echo "proposer-config.json not found, running with zero default fee recipient" PROPOSER_CONFIG+=(--validators-proposer-default-fee-recipient="0x0000000000000000000000000000000000000000")