diff --git a/default.env b/default.env index 9d3ed324..e611f86d 100644 --- a/default.env +++ b/default.env @@ -244,6 +244,8 @@ CONTRIBUTOOR_EXTRAS= MEV_EXTRAS= # Additional parameters for a verified RPC proxy PROXY_EXTRAS= +# Additional parameters for zkboost +ZKBOOST_EXTRAS= # Heap for Besu and Teku, both written in Java. Sets JAVA_OPTS to this value, for example TEKU_HEAP=-Xmx12g to set it # to 12g. If left empty, the defaults in besu.yml and teku.yml are used @@ -316,6 +318,9 @@ CL_ALIAS=${NETWORK}-consensus EL_ALIAS=${NETWORK}-execution MEV_ALIAS=${NETWORK}-mev RPC_PROXY_ALIAS=${NETWORK}-rpc-proxy +ZKBOOST_ALIAS=${NETWORK}-zkboost +# zkboost address +ZKBOOST_NODE=http://${ZKBOOST_ALIAS}:3000 # MEV-boost address. This would only be changed for Vouch setups MEV_NODE=http://${MEV_ALIAS}:18550 # Web3signer address - match service name or alias, or it can be remote @@ -377,6 +382,16 @@ MEV_DOCKER_REPO=flashbots/mev-boost # Whether to use a Docker image or build from source MEV_DOCKERFILE=Dockerfile.binary +# zkboost +# SRC build target can be a tag, a branch, or a pr as "pr-ID" +ZKBOOST_SRC_BUILD_TARGET=master +ZKBOOST_SRC_REPO=https://github.com/eth-act/zkboost +# Docker image and repo +ZKBOOST_DOCKER_TAG= +ZKBOOST_DOCKER_REPO= +# Whether to use a Docker image or build from source +ZKBOOST_DOCKERFILE=Dockerfile.source + # Nimbus # SRC build target can be a tag, a branch, or a pr as "pr-ID" NIM_SRC_BUILD_TARGET=stable @@ -582,4 +597,4 @@ DOCKER_SOCK=/var/run/docker.sock ALLOY_PROJECT_NAME= # Used by ethd update - please do not adjust -ENV_VERSION=64 +ENV_VERSION=65 diff --git a/ethd b/ethd index 1401e7d7..ff4cce04 100755 --- a/ethd +++ b/ethd @@ -770,6 +770,7 @@ __prep_conffiles() { [./ssv-config/dkg-config.yaml]="./ssv-config/dkg-config.yaml.sample" [./commit-boost/cb-config.toml]="./commit-boost/cb-config.toml.sample" [./tempo/tempo.yaml]="./tempo/tempo.yaml.sample" + [./zkboost/config.toml]="./zkboost/config.toml.sample" [./.motd]="./.motd.sample" ) local -A chmod_dirs=( @@ -780,6 +781,7 @@ __prep_conffiles() { [./.eth/dkg_output]="*" [./commit-boost]="cb-config.toml" [./tempo]="*.yaml" + [./zkboost]="config.toml" [./loki]="*.yml" [./siren]="*.sh" ) @@ -1526,6 +1528,15 @@ __source_build() { fi ;; esac + case "${COMPOSE_FILE}" in + *zkboost.yml*) + var="ZKBOOST_DOCKERFILE" + __get_value_from_env "${var}" "${__env_file}" "__value" + if [[ "${__value}" = "Dockerfile.source" ]]; then + __docompose build --pull --no-cache zkboost + fi + ;; + esac } diff --git a/lighthouse-cl-only.yml b/lighthouse-cl-only.yml index 664062bf..cecd90a2 100644 --- a/lighthouse-cl-only.yml +++ b/lighthouse-cl-only.yml @@ -44,6 +44,7 @@ services: - CL_QUIC_PORT=${CL_QUIC_PORT:-9001} - NETWORK=${NETWORK} - COMPOSE_FILE=${COMPOSE_FILE} + - ZKBOOST_NODE=${ZKBOOST_NODE} ports: - ${HOST_IP:-}:${CL_P2P_PORT:-9000}:${CL_P2P_PORT:-9000}/tcp - ${HOST_IP:-}:${CL_P2P_PORT:-9000}:${CL_P2P_PORT:-9000}/udp diff --git a/lighthouse.yml b/lighthouse.yml index 3f524008..aeb2d346 100644 --- a/lighthouse.yml +++ b/lighthouse.yml @@ -53,6 +53,7 @@ services: - CL_QUIC_PORT=${CL_QUIC_PORT:-9001} - NETWORK=${NETWORK} - COMPOSE_FILE=${COMPOSE_FILE} + - ZKBOOST_NODE=${ZKBOOST_NODE} ports: - ${HOST_IP:-}:${CL_P2P_PORT:-9000}:${CL_P2P_PORT:-9000}/tcp - ${HOST_IP:-}:${CL_P2P_PORT:-9000}:${CL_P2P_PORT:-9000}/udp diff --git a/lighthouse/docker-entrypoint.sh b/lighthouse/docker-entrypoint.sh index ff6b660f..1fa47afa 100755 --- a/lighthouse/docker-entrypoint.sh +++ b/lighthouse/docker-entrypoint.sh @@ -72,28 +72,35 @@ case "${NODE_TYPE}" in ;; esac -# Assume we're not zk-enabled +# Assume we're running an EL __engine="--execution-endpoint ${EL_NODE} --execution-jwt /var/lib/lighthouse/beacon/ee-secret/jwtsecret" +if [[ "${COMPOSE_FILE}" =~ zkboost\.yml ]]; then + echo "Lighthouse node with zkproofs. HIGHLY experimental." + echo "Please make sure that you have edited \".env\" and changed:" + echo "LH_SRC_BUILD_TARGET=optional-proofs" + echo "LH_SRC_REPO=https://github.com/eth-act/lighthouse" + echo "LH_DOCKERFILE=Dockerfile.source" + echo "And have source-built Lighthouse with \"./ethd update\"" + __zkboost="--proof-engine-endpoint ${ZKBOOST_NODE}" +else + __zkboost="" +fi + if [[ "${EL_NODE_TYPE}" = "use-cl-zkproofs" ]]; then - if [[ ! "${NETWORK}" = "mainnet" ]]; then - echo "Lighthouse with zkProof verification only works on mainnet, as far as Eth Docker is aware." - echo "Aborting." + if [[ ! "${COMPOSE_FILE}" =~ zkboost\.yml ]]; then + echo "Lighthouse requires zkboost.yml to run without an EL. Please adjust your configuration in \".env\"" + echo "Aborting" sleep 30 exit 1 fi - echo "Lighthouse node with zkProof verification. HIGHLY experimental." + echo + echo "Lighthouse node without EL node. EXTREMELY experimental." echo "Please make sure that you have edited \".env\" and changed:" - echo "CL_EXTRAS=--boot-nodes enr:-Oy4QJgMz9S1Eb7s13nKIbulKC0nvnt7AEqbmwxnTdwzptxNCGWjc9ipteUaCwqlu2bZDoNz361vGC_IY4fbdkR1K9iCDeuHYXR0bmV0c4gAAAAAAAAABoNjZ2MEhmNsaWVudNGKTGlnaHRob3VzZYU4LjAuMYRldGgykK1TLOsGAAAAAEcGAAAAAACCaWSCdjSCaXCEisV68INuZmSEzCxc24RxdWljgiMpiXNlY3AyNTZrMaEDEIWq41UTcFUgL8LRletpbIwrrpxznIMN_F5jRgatngmIc3luY25ldHMAg3RjcIIjKIR6a3ZtAQ" - echo "LH_SRC_BUILD_TARGET=ethproofs/zkattester-demo" - echo "LH_SRC_REPO=https://github.com/ethproofs/lighthouse" - echo "LH_DOCKERFILE=Dockerfile.source" echo "MEV_BOOST=true" echo "MEV_BUILD_FACTOR=100" - echo "And have source-built Lighthouse with \"./ethd update\"" - echo "A PBS sidecar needs to be in COMPOSE_FILE, and MEV relays need to be configured" - echo "Note the bootnodes ENR may have changed, check on the zkEVM attesting Telegram group!" - __engine="--execution-proofs" + echo "A PBS sidecar needs to be in CORE_FILES or CUSTOM_FILES, and MEV relays need to be configured" + __engine="" fi # Check whether we should rapid sync @@ -177,5 +184,5 @@ if [[ -f /var/lib/lighthouse/beacon/prune-marker ]]; then else # Word splitting is desired for the command line parameters # shellcheck disable=SC2086 - exec "$@" ${__network} ${__mev_boost} ${__checkpoint_sync} ${__engine} ${__prune} ${__beacon_stats} ${__trace} ${__ipv6} ${CL_EXTRAS} + exec "$@" ${__network} ${__mev_boost} ${__checkpoint_sync} ${__engine} ${__zkboost} ${__prune} ${__beacon_stats} ${__trace} ${__ipv6} ${CL_EXTRAS} fi diff --git a/zkboost.yml b/zkboost.yml new file mode 100644 index 00000000..9f38f4f8 --- /dev/null +++ b/zkboost.yml @@ -0,0 +1,55 @@ +x-logging: &logging + logging: + driver: ${LOG_DRIVER} + options: + max-size: ${LOG_MAX_SIZE} + max-file: ${LOG_MAX_FILE} + tag: ${LOG_TAG} + +services: + zkboost: + restart: "unless-stopped" + build: + context: ./zkboost + dockerfile: ${ZKBOOST_DOCKERFILE} + args: + - BUILD_TARGET=${ZKBOOST_SRC_BUILD_TARGET:-master} + - SRC_REPO=${ZKBOOST_SRC_REPO:-https://github.com/eth-act/zkboost} + - DOCKER_TAG=${ZKBOOST_DOCKER_TAG} + - DOCKER_REPO=${ZKBOOST_DOCKER_REPO} + image: zkboost:local + pull_policy: never + networks: + default: + aliases: + # This allows multiple Eth Docker stacks all connected to the same bridge network + - ${ZKBOOST_ALIAS:-default-zkboost} + volumes: + - ./zkboost/config.toml:/app/config.toml:ro + - zkboost-data:/var/lib/zkboost + - /etc/localtime:/etc/localtime:ro + environment: + - RUST_LOG=${LOG_LEVEL},zkboost=debug + - ZKBOOST_EXTRAS=${ZKBOOST_EXTRAS:-} + - NETWORK=${NETWORK} + - COMPOSE_FILE=${COMPOSE_FILE} + <<: *logging + entrypoint: + - docker-entrypoint.sh + - zkboost + - --config + - /app/config.toml + labels: + - metrics.scrape=true + - metrics.path=/metrics + - metrics.port=3000 + - metrics.instance=zkboost + - metrics.network=${NETWORK} + - logs.collect=true + +volumes: + zkboost-data: + +networks: + default: + enable_ipv6: ${IPV6:-false} diff --git a/zkboost/.gitignore b/zkboost/.gitignore new file mode 100644 index 00000000..5b6c0960 --- /dev/null +++ b/zkboost/.gitignore @@ -0,0 +1 @@ +config.toml diff --git a/zkboost/Dockerfile.source b/zkboost/Dockerfile.source new file mode 100644 index 00000000..e729db64 --- /dev/null +++ b/zkboost/Dockerfile.source @@ -0,0 +1,81 @@ +# hadolint global ignore=DL3007,DL3008,DL3059,DL4006 +# Build zkboost in a stock Rust build container +FROM rust:trixie AS builder + +# Unused, this is here to avoid build time complaints +ARG DOCKER_TAG +ARG DOCKER_REPO + +ARG BUILD_TARGET +ARG SRC_REPO + +RUN apt-get update && apt-get install -y --no-install-recommends \ + clang \ + libclang-dev \ + protobuf-compiler \ + libprotobuf-dev \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +WORKDIR /app + +ARG SRC_DIR=zkboost +ENV CC=clang +ENV CXX=clang++ +RUN --mount=type=cache,sharing=locked,id=zkboost-target,target=/app/target/ \ + --mount=type=cache,sharing=locked,target=/usr/local/cargo/git/db \ + --mount=type=cache,sharing=locked,target=/usr/local/cargo/registry/ \ + bash <<'EOF' +set -Eeuo pipefail +git clone "$SRC_REPO" "$SRC_DIR" +cd "$SRC_DIR" +git config advice.detachedHead false +git fetch --all --tags +CLEANED=$(echo "$BUILD_TARGET" | sed 's/\$\$(/$(/g') +TARGET=$(eval echo "$CLEANED") +if [[ "$TARGET" =~ ^pr-[1-9][0-9]*$ ]]; then + git fetch origin pull/${TARGET#pr-}/head:build-pr + git checkout build-pr +else + git checkout "$TARGET" +fi +CARGO_TARGET_DIR=/app/target cargo build --release --features otel --bin zkboost +mkdir -p /app/bin +cp /app/target/release/zkboost /app/bin/ +EOF + +# Pull all binaries into a second stage deploy container +FROM debian:trixie-slim + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + tzdata \ + adduser \ + libssl3 \ + bash \ + git \ + git-lfs \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +ARG USER=zkboost +ARG UID=10667 + +# See https://stackoverflow.com/a/55757473/12429735RUN +RUN adduser \ + --disabled-password \ + --gecos "" \ + --shell "/sbin/nologin" \ + --uid "${UID}" \ + "${USER}" + +RUN mkdir -p /app && chown -R ${USER}:${USER} /app +RUN mkdir -p /var/lib/zkboost && chown -R ${USER}:${USER} /var/lib/zkboost && chmod -R 700 /var/lib/zkboost + +# Cannot assume buildkit, hence no chmod +COPY --from=builder --chown=${USER}:${USER} /app/bin/zkboost /usr/local/bin/ +COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ +# Belt and suspenders +RUN chmod -R 755 /usr/local/bin/* + +USER ${USER} + +ENTRYPOINT ["zkboost"] diff --git a/zkboost/config.toml.sample b/zkboost/config.toml.sample new file mode 100644 index 00000000..b180f88f --- /dev/null +++ b/zkboost/config.toml.sample @@ -0,0 +1,36 @@ +port = 3000 +# Dummy to satisfy config requirements - if this is a Geth or Reth instead with debug_ namespace, +# zkboost will read debug_chainConfig +el_endpoint = "http://localhost:1" +# Chain config downloaded by entrypoint, means el_endpoint won't be used at startup +chain_config_path = "/var/lib/zkboost/network/config/genesis.json" + +[[zkvm]] +kind = "verifier" +proof_type = "ethrex-openvm" +program_vk_url = "https://github.com/eth-act/ere-guests/releases/download/v0.13.0/stateless-validator-ethrex-openvm.vk" + +[[zkvm]] +kind = "verifier" +proof_type = "ethrex-sp1" +program_vk_url = "https://github.com/eth-act/ere-guests/releases/download/v0.13.0/stateless-validator-ethrex-sp1.vk" + +[[zkvm]] +kind = "verifier" +proof_type = "ethrex-zisk" +program_vk_url = "https://github.com/eth-act/ere-guests/releases/download/v0.13.0/stateless-validator-ethrex-zisk.vk" + +[[zkvm]] +kind = "verifier" +proof_type = "reth-openvm" +program_vk_url = "https://github.com/eth-act/ere-guests/releases/download/v0.13.0/stateless-validator-reth-openvm.vk" + +[[zkvm]] +kind = "verifier" +proof_type = "reth-sp1" +program_vk_url = "https://github.com/eth-act/ere-guests/releases/download/v0.13.0/stateless-validator-reth-sp1.vk" + +[[zkvm]] +kind = "verifier" +proof_type = "reth-zisk" +program_vk_url = "https://github.com/eth-act/ere-guests/releases/download/v0.13.0/stateless-validator-reth-zisk.vk" diff --git a/zkboost/docker-entrypoint.sh b/zkboost/docker-entrypoint.sh new file mode 100755 index 00000000..248eba44 --- /dev/null +++ b/zkboost/docker-entrypoint.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +case "${NETWORK}" in + mainnet) + NETWORK="https://github.com/eth-clients/mainnet/tree/main/metadata" + ;; + sepolia) + NETWORK="https://github.com/eth-clients/sepolia/tree/main/metadata" + ;; + hoodi) + NETWORK="https://github.com/eth-clients/hoodi/tree/main/metadata" + ;; + https://*|http://*) + ;; + *) + echo "Unknown named network ${NETWORK}. Please supply a URL to its github metadata instead" + echo "Cannot start" + sleep 30 + exit 1 +esac + +if [[ "${NETWORK}" =~ ^https?:// ]]; then + echo "Network config at ${NETWORK}" + repo=$(awk -F'/tree/' '{print $1}' <<< "${NETWORK}") + branch=$(awk -F'/tree/' '{print $2}' <<< "${NETWORK}" | cut -d'/' -f1) + config_dir=$(awk -F'/tree/' '{print $2}' <<< "${NETWORK}" | cut -d'/' -f2-) + echo "This appears to be the ${repo} repo, branch ${branch} and config directory ${config_dir}." + rm -rf /var/lib/zkboost/network # Recreate on every run, so the network can be changed + mkdir -p /var/lib/zkboost/network + cd /var/lib/zkboost/network + git init --initial-branch="${branch}" + git remote add origin "${repo}" + git config core.sparseCheckout true + echo "${config_dir}" > .git/info/sparse-checkout + git pull origin "${branch}" + mv "${config_dir}" config +fi + +# Traces +if [[ "${COMPOSE_FILE}" =~ (grafana\.yml|grafana-rootless\.yml) ]]; then +# These may become default in future. Here so zkboost doesn't murder itself in the meantime + export OTEL_TRACES_SAMPLER=parentbased_traceidratio + export OTEL_TRACES_SAMPLER_ARG=0.01 + export OTEL_EXPORTER_OTLP_INSECURE=true + export OTEL_EXPORTER_OTLP_PROTOCOL=grpc + export OTEL_EXPORTER_OTLP_ENDPOINT=http://tempo:4317 + export OTEL_SERVICE_NAME=zkboost +fi + +# Word splitting is desired for the command line parameters +# shellcheck disable=SC2086 +exec "$@" ${ZKBOOST_EXTRAS}