From ef7cf34af04a787160a6ab439b50d2f45ab4fd24 Mon Sep 17 00:00:00 2001 From: march-fatcat Date: Wed, 18 Mar 2026 19:26:23 +0800 Subject: [PATCH 1/2] feat: add nlean consensus client support --- client-cmds/nlean-cmd.sh | 123 ++++++++++++++++++ .../genesis/validator-config.yaml | 44 +++++++ 2 files changed, 167 insertions(+) create mode 100755 client-cmds/nlean-cmd.sh create mode 100644 local-devnet-nlean/genesis/validator-config.yaml diff --git a/client-cmds/nlean-cmd.sh b/client-cmds/nlean-cmd.sh new file mode 100755 index 0000000..46fbca7 --- /dev/null +++ b/client-cmds/nlean-cmd.sh @@ -0,0 +1,123 @@ +#!/bin/bash + +#-----------------------nlean setup---------------------- +# This script follows lean-quickstart's client-cmd contract: +# it must populate node_binary / node_docker / node_setup. +# NLEAN_REPO should point to this repository when lean-quickstart is outside this workspace. +# Default assumes sibling checkouts: /nlean and /lean-quickstart. +nlean_repo="${NLEAN_REPO:-$scriptDir/../nlean}" +nlean_docker_image="${NLEAN_DOCKER_IMAGE:-nlean-local:devnet3}" +nlean_network_name="${NLEAN_NETWORK_NAME:-devnet0}" +log_level="${NLEAN_LOG_LEVEL:-}" +enable_metrics="${enableMetrics:-false}" + +enable_metrics=$(echo "$enable_metrics" | tr '[:upper:]' '[:lower:]') +if [[ "$enable_metrics" != "true" && "$enable_metrics" != "false" ]]; then + enable_metrics="false" +fi + +if [[ -z "${nlean_network_name// }" ]]; then + nlean_network_name="devnet0" +fi + +log_level="${log_level#${log_level%%[![:space:]]*}}" +log_level="${log_level%${log_level##*[![:space:]]}}" +log_level_arg="" +if [[ -n "$log_level" ]]; then + log_level_arg="--log ${log_level}" +fi + +node_private_key_path="${privKeyPath:-${item}.key}" + +# Set aggregator flag based on isAggregator value (from parse-vc.sh) +aggregator_flag="" +if [[ "${isAggregator:-false}" == "true" ]]; then + aggregator_flag="--is-aggregator" +fi + +# Set attestation committee count flag if explicitly configured +attestation_committee_flag="" +if [[ -n "${attestationCommitteeCount:-}" ]]; then + attestation_committee_flag="--attestation-committee-count $attestationCommitteeCount" +fi + +# Set checkpoint sync URL when restarting with checkpoint sync +checkpoint_sync_flag="" +if [[ -n "${checkpoint_sync_url:-}" ]]; then + checkpoint_sync_flag="--checkpoint-sync-url $checkpoint_sync_url" +fi + +# Set API port flag if explicitly configured +api_port_flag="" +nlean_api_port="${NLEAN_API_PORT:-${httpPort:-}}" +if [[ -n "$nlean_api_port" ]]; then + api_port_flag="--api-port $nlean_api_port" +fi + +# Resolve the binary path +binary_path="$nlean_repo/artifacts/lean-client/Lean.Client" + +mkdir -p "$dataDir/$item" + +node_binary="$binary_path \ + --validator-config $configDir/validator-config.yaml \ + --node $item \ + --data-dir $dataDir/$item \ + --network $nlean_network_name \ + --node-key $configDir/$node_private_key_path \ + --socket-port $quicPort \ + --metrics $enable_metrics \ + --metrics-port $metricsPort \ + --metrics-address 0.0.0.0 \ + --hash-sig-key-dir $configDir/hash-sig-keys \ + $api_port_flag \ + $attestation_committee_flag \ + $aggregator_flag \ + $checkpoint_sync_flag \ + $log_level_arg" + +nlean_docker_extra_env="" +if [[ -n "${NLEAN_DEBUG_DUMP_ATTESTATIONS:-}" ]]; then + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_ATTESTATIONS=${NLEAN_DEBUG_DUMP_ATTESTATIONS}" +fi +if [[ -n "${NLEAN_DEBUG_DUMP_DIR:-}" ]]; then + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_DIR=${NLEAN_DEBUG_DUMP_DIR}" +fi +if [[ -n "${NLEAN_DEBUG_DUMP_BLOCKS:-}" ]]; then + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_BLOCKS=${NLEAN_DEBUG_DUMP_BLOCKS}" +fi +if [[ -n "${NLEAN_DEBUG_DUMP_BLOCK_DIR:-}" ]]; then + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_BLOCK_DIR=${NLEAN_DEBUG_DUMP_BLOCK_DIR}" +fi +if [[ -n "${NLEAN_DEBUG_DUMP_OBSERVED_PROOFS:-}" ]]; then + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_OBSERVED_PROOFS=${NLEAN_DEBUG_DUMP_OBSERVED_PROOFS}" +fi +if [[ -n "${NLEAN_DEBUG_DUMP_OBSERVED_PROOFS_DIR:-}" ]]; then + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_OBSERVED_PROOFS_DIR=${NLEAN_DEBUG_DUMP_OBSERVED_PROOFS_DIR}" +fi +if [[ -n "${NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS:-}" ]]; then + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS=${NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS}" +fi +if [[ -n "${NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS_DIR:-}" ]]; then + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS_DIR=${NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS_DIR}" +fi + +node_docker="${nlean_docker_extra_env} ${nlean_docker_image} \ + --validator-config /config/validator-config.yaml \ + --node $item \ + --data-dir /data \ + --network $nlean_network_name \ + --node-key /config/$node_private_key_path \ + --socket-port $quicPort \ + --metrics $enable_metrics \ + --metrics-port $metricsPort \ + --metrics-address 0.0.0.0 \ + --hash-sig-key-dir /config/hash-sig-keys \ + $api_port_flag \ + $attestation_committee_flag \ + $aggregator_flag \ + $checkpoint_sync_flag \ + $log_level_arg" + +# choose either binary or docker +node_setup="${NLEAN_QUICKSTART_SETUP:-binary}" diff --git a/local-devnet-nlean/genesis/validator-config.yaml b/local-devnet-nlean/genesis/validator-config.yaml new file mode 100644 index 0000000..8b43b9a --- /dev/null +++ b/local-devnet-nlean/genesis/validator-config.yaml @@ -0,0 +1,44 @@ +# Quickstart validator template used by nlean interop scripts. +# Keep node names and ports aligned with the target interop topology. +shuffle: roundrobin +deployment_mode: local +config: + activeEpoch: 18 + keyType: "hash-sig" +validators: + - name: "nlean_0" + privkey: "2e9be3f1b0d32ca3a4d62017fbfafe3950b7e90fed6802ff8bd2e0f8c4e2ca91" + enrFields: + ip: "127.0.0.1" + quic: 9101 + metricsPort: 18081 + httpPort: 5052 + count: 1 + isAggregator: true + - name: "nlean_1" + privkey: "bdf953adc161873ba026330c56450453f582e3c4ee6cb713644794bcfdd85fe5" + enrFields: + ip: "127.0.0.1" + quic: 9102 + metricsPort: 18082 + httpPort: 5053 + count: 1 + isAggregator: false + - name: "nlean_2" + privkey: "299550529a79bc2dce003747c52fb0639465c893e00b0440ac66144d625e066a" + enrFields: + ip: "127.0.0.1" + quic: 9103 + metricsPort: 18083 + httpPort: 5054 + count: 1 + isAggregator: false + - name: "nlean_3" + privkey: "c4f5a6b7d8e9012345abcdef6789012345abcdef6789012345abcdef67890123" + enrFields: + ip: "127.0.0.1" + quic: 9104 + metricsPort: 18084 + httpPort: 5055 + count: 1 + isAggregator: false From 6c1e88a73105e9844f9ed9334ab8b808b77e9bc1 Mon Sep 17 00:00:00 2001 From: Chen Kai <281165273grape@gmail.com> Date: Thu, 19 Mar 2026 20:10:02 +0800 Subject: [PATCH 2/2] fix: address PR #137 review comments - Add apiPort to validator-config.yaml for leanpoint health-check URLs - Use apiPort instead of httpPort for --api-port flag in nlean-cmd.sh - Use Docker -e VAR (inherit) instead of -e VAR=value to avoid colon-breaking issues --- client-cmds/nlean-cmd.sh | 20 +++++++++---------- .../genesis/validator-config.yaml | 12 +++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/client-cmds/nlean-cmd.sh b/client-cmds/nlean-cmd.sh index 46fbca7..2f7fe0a 100755 --- a/client-cmds/nlean-cmd.sh +++ b/client-cmds/nlean-cmd.sh @@ -49,7 +49,7 @@ fi # Set API port flag if explicitly configured api_port_flag="" -nlean_api_port="${NLEAN_API_PORT:-${httpPort:-}}" +nlean_api_port="${NLEAN_API_PORT:-${apiPort:-}}" if [[ -n "$nlean_api_port" ]]; then api_port_flag="--api-port $nlean_api_port" fi @@ -78,28 +78,28 @@ node_binary="$binary_path \ nlean_docker_extra_env="" if [[ -n "${NLEAN_DEBUG_DUMP_ATTESTATIONS:-}" ]]; then - nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_ATTESTATIONS=${NLEAN_DEBUG_DUMP_ATTESTATIONS}" + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_ATTESTATIONS=$NLEAN_DEBUG_DUMP_ATTESTATIONS" fi if [[ -n "${NLEAN_DEBUG_DUMP_DIR:-}" ]]; then - nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_DIR=${NLEAN_DEBUG_DUMP_DIR}" + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_DIR=$NLEAN_DEBUG_DUMP_DIR" fi if [[ -n "${NLEAN_DEBUG_DUMP_BLOCKS:-}" ]]; then - nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_BLOCKS=${NLEAN_DEBUG_DUMP_BLOCKS}" + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_BLOCKS=$NLEAN_DEBUG_DUMP_BLOCKS" fi if [[ -n "${NLEAN_DEBUG_DUMP_BLOCK_DIR:-}" ]]; then - nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_BLOCK_DIR=${NLEAN_DEBUG_DUMP_BLOCK_DIR}" + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_BLOCK_DIR=$NLEAN_DEBUG_DUMP_BLOCK_DIR" fi if [[ -n "${NLEAN_DEBUG_DUMP_OBSERVED_PROOFS:-}" ]]; then - nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_OBSERVED_PROOFS=${NLEAN_DEBUG_DUMP_OBSERVED_PROOFS}" + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_OBSERVED_PROOFS=$NLEAN_DEBUG_DUMP_OBSERVED_PROOFS" fi if [[ -n "${NLEAN_DEBUG_DUMP_OBSERVED_PROOFS_DIR:-}" ]]; then - nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_OBSERVED_PROOFS_DIR=${NLEAN_DEBUG_DUMP_OBSERVED_PROOFS_DIR}" + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_OBSERVED_PROOFS_DIR=$NLEAN_DEBUG_DUMP_OBSERVED_PROOFS_DIR" fi if [[ -n "${NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS:-}" ]]; then - nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS=${NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS}" + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS=$NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS" fi if [[ -n "${NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS_DIR:-}" ]]; then - nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS_DIR=${NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS_DIR}" + nlean_docker_extra_env+=" -e NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS_DIR=$NLEAN_DEBUG_DUMP_OBSERVED_BLOCKS_DIR" fi node_docker="${nlean_docker_extra_env} ${nlean_docker_image} \ @@ -120,4 +120,4 @@ node_docker="${nlean_docker_extra_env} ${nlean_docker_image} \ $log_level_arg" # choose either binary or docker -node_setup="${NLEAN_QUICKSTART_SETUP:-binary}" +node_setup="${NLEAN_QUICKSTART_SETUP:-docker}" diff --git a/local-devnet-nlean/genesis/validator-config.yaml b/local-devnet-nlean/genesis/validator-config.yaml index 8b43b9a..eada187 100644 --- a/local-devnet-nlean/genesis/validator-config.yaml +++ b/local-devnet-nlean/genesis/validator-config.yaml @@ -12,25 +12,25 @@ validators: ip: "127.0.0.1" quic: 9101 metricsPort: 18081 - httpPort: 5052 + apiPort: 5052 count: 1 - isAggregator: true + isAggregator: false - name: "nlean_1" privkey: "bdf953adc161873ba026330c56450453f582e3c4ee6cb713644794bcfdd85fe5" enrFields: ip: "127.0.0.1" quic: 9102 metricsPort: 18082 - httpPort: 5053 + apiPort: 5053 count: 1 - isAggregator: false + isAggregator: true - name: "nlean_2" privkey: "299550529a79bc2dce003747c52fb0639465c893e00b0440ac66144d625e066a" enrFields: ip: "127.0.0.1" quic: 9103 metricsPort: 18083 - httpPort: 5054 + apiPort: 5054 count: 1 isAggregator: false - name: "nlean_3" @@ -39,6 +39,6 @@ validators: ip: "127.0.0.1" quic: 9104 metricsPort: 18084 - httpPort: 5055 + apiPort: 5055 count: 1 isAggregator: false