diff --git a/README.md b/README.md index 118a821..dace634 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,44 @@ Grafana is started with the two pre-provisioned dashboards from [leanMetrics](ht - On Ctrl+C cleanup, the metrics stack is stopped automatically Note: Client metrics endpoints are always enabled regardless of this flag. +12. `--checkpoint-sync-url` specifies the URL to fetch finalized checkpoint state from for checkpoint sync. Default: `https://leanpoint.leanroadmap.org/lean/v0/states/finalized`. Only used when `--restart-client` is specified. +13. `--restart-client` comma-separated list of client node names (e.g., `zeam_0,ream_0`). When specified, those clients are stopped, their data cleared, and restarted using checkpoint sync. Genesis is skipped. Use with `--checkpoint-sync-url` to override the default URL. + +### Checkpoint sync + +Checkpoint sync lets you restart clients by syncing from a remote checkpoint instead of from genesis. This is useful for joining an existing network (e.g., leanpoint mainnet) without replaying the full chain. + +**Basic usage:** + +```sh +# Restart zeam_0 using the default checkpoint URL +NETWORK_DIR=local-devnet ./spin-node.sh --restart-client zeam_0 + +# Restart multiple clients +NETWORK_DIR=local-devnet ./spin-node.sh --restart-client zeam_0,ream_0 +``` + +**Custom checkpoint URL:** + +```sh +NETWORK_DIR=local-devnet ./spin-node.sh --restart-client zeam_0 \ + --checkpoint-sync-url https://leanpoint.leanroadmap.org/lean/v0/states/finalized +``` + +**Default checkpoint URL:** `https://leanpoint.leanroadmap.org/lean/v0/states/finalized` + +**What happens:** +1. Existing containers for the specified clients are stopped (no error if already stopped) +2. Data directories are cleared +3. Clients are started with `--checkpoint-sync-url` so they sync from the remote checkpoint instead of genesis + +**Deployment modes:** +- **Local** (`NETWORK_DIR=local-devnet`): Uses Docker directly +- **Ansible** (`NETWORK_DIR=ansible-devnet`): Uses Ansible to deploy to remote hosts + +**Supported clients:** zeam, ream, qlean, lantern, lighthouse, grandine, ethlambda + +> **Note:** All clients accept `--checkpoint-sync-url`. Client implementations may use different parameter names internally; update client-cmd scripts if parameters change. ### Clients supported diff --git a/ansible-devnet/genesis/validator-config.yaml b/ansible-devnet/genesis/validator-config.yaml index 81e80f5..091275a 100644 --- a/ansible-devnet/genesis/validator-config.yaml +++ b/ansible-devnet/genesis/validator-config.yaml @@ -14,6 +14,7 @@ validators: ip: "46.224.123.223" quic: 9001 metricsPort: 9095 + isAggregator: false count: 1 # number of indices for this node - name: "ream_0" @@ -25,6 +26,7 @@ validators: ip: "77.42.27.219" quic: 9001 metricsPort: 9095 + isAggregator: false devnet: 1 count: 1 @@ -36,6 +38,7 @@ validators: ip: "46.224.123.220" quic: 9001 metricsPort: 9095 + isAggregator: false count: 1 - name: "lantern_0" @@ -47,6 +50,7 @@ validators: ip: "46.224.135.177" quic: 9001 metricsPort: 9095 + isAggregator: false count: 1 - name: "lighthouse_0" @@ -58,6 +62,7 @@ validators: ip: "46.224.135.169" quic: 9001 metricsPort: 9095 + isAggregator: false count: 1 - name: "grandine_0" @@ -66,6 +71,7 @@ validators: ip: "37.27.250.20" quic: 9001 metricsPort: 9095 + isAggregator: false count: 1 - name: "ethlambda_0" @@ -74,4 +80,5 @@ validators: ip: "78.47.44.215" quic: 9001 metricsPort: 9095 + isAggregator: false count: 1 \ No newline at end of file diff --git a/ansible/playbooks/site.yml b/ansible/playbooks/site.yml index fea64cc..52dbbac 100644 --- a/ansible/playbooks/site.yml +++ b/ansible/playbooks/site.yml @@ -22,7 +22,6 @@ import_playbook: clean-node-data.yml vars: genesis_dir: "{{ network_dir }}/genesis" - node_names: "{{ node_names }}" when: clean_data | default(false) | bool - name: Generate Genesis Files @@ -40,5 +39,4 @@ - name: Deploy Nodes import_playbook: deploy-nodes.yml vars: - node_names: "{{ node_names }}" skip_role_cleaning: "{{ clean_data | default(false) | bool }}" diff --git a/client-cmds/ethlambda-cmd.sh b/client-cmds/ethlambda-cmd.sh index 50bd63c..a71ac71 100644 --- a/client-cmds/ethlambda-cmd.sh +++ b/client-cmds/ethlambda-cmd.sh @@ -4,6 +4,18 @@ binary_path="$scriptDir/../ethlambda/target/release/ethlambda" +# Set aggregator flag based on isAggregator value +aggregator_flag="" +if [ "$isAggregator" == "true" ]; then + aggregator_flag="--is-aggregator" +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 + # Command when running as binary node_binary="$binary_path \ --custom-network-config-dir $configDir \ @@ -11,7 +23,9 @@ node_binary="$binary_path \ --node-id $item \ --node-key $configDir/$item.key \ --metrics-address 0.0.0.0 \ - --metrics-port $metricsPort" + --metrics-port $metricsPort \ + $aggregator_flag \ + $checkpoint_sync_flag" # Command when running as docker container node_docker="ghcr.io/lambdaclass/ethlambda:devnet2 \ @@ -20,6 +34,8 @@ node_docker="ghcr.io/lambdaclass/ethlambda:devnet2 \ --node-id $item \ --node-key /config/$item.key \ --metrics-address 0.0.0.0 \ - --metrics-port $metricsPort" + --metrics-port $metricsPort \ + $aggregator_flag \ + $checkpoint_sync_flag" node_setup="docker" diff --git a/client-cmds/grandine-cmd.sh b/client-cmds/grandine-cmd.sh index cd92472..d1d550a 100644 --- a/client-cmds/grandine-cmd.sh +++ b/client-cmds/grandine-cmd.sh @@ -1,5 +1,17 @@ #!/bin/bash +# Set aggregator flag based on isAggregator value +aggregator_flag="" +if [ "$isAggregator" == "true" ]; then + aggregator_flag="--is-aggregator" +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 + node_binary="$grandine_bin \ --genesis $configDir/config.yaml \ --validator-registry-path $configDir/validators.yaml \ @@ -11,7 +23,9 @@ node_binary="$grandine_bin \ --metrics \ --http-address 0.0.0.0 \ --http-port $metricsPort \ - --hash-sig-key-dir $configDir/hash-sig-keys" + --hash-sig-key-dir $configDir/hash-sig-keys \ + $aggregator_flag \ + $checkpoint_sync_flag" node_docker="sifrai/lean:devnet-2 \ --genesis /config/config.yaml \ @@ -24,7 +38,9 @@ node_docker="sifrai/lean:devnet-2 \ --metrics \ --http-address 0.0.0.0 \ --http-port $metricsPort \ - --hash-sig-key-dir /config/hash-sig-keys" + --hash-sig-key-dir /config/hash-sig-keys \ + $aggregator_flag \ + $checkpoint_sync_flag" # choose either binary or docker node_setup="docker" diff --git a/client-cmds/lantern-cmd.sh b/client-cmds/lantern-cmd.sh index b918355..7d22960 100755 --- a/client-cmds/lantern-cmd.sh +++ b/client-cmds/lantern-cmd.sh @@ -8,6 +8,18 @@ if [ -n "$devnet" ]; then devnet_flag="--devnet $devnet" fi +# Set aggregator flag based on isAggregator value +aggregator_flag="" +if [ "$isAggregator" == "true" ]; then + aggregator_flag="--is-aggregator" +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 + # Lantern's repo: https://github.com/Pier-Two/lantern node_binary="$scriptDir/lantern/build/lantern_cli \ --data-dir $dataDir/$item \ @@ -22,7 +34,9 @@ node_binary="$scriptDir/lantern/build/lantern_cli \ --metrics-port $metricsPort \ --http-port 5055 \ --log-level debug \ - --hash-sig-key-dir $configDir/hash-sig-keys" + --hash-sig-key-dir $configDir/hash-sig-keys \ + $aggregator_flag \ + $checkpoint_sync_flag" node_docker="$LANTERN_IMAGE --data-dir /data \ --genesis-config /config/config.yaml \ @@ -36,7 +50,9 @@ node_docker="$LANTERN_IMAGE --data-dir /data \ --metrics-port $metricsPort \ --http-port 5055 \ --log-level debug \ - --hash-sig-key-dir /config/hash-sig-keys" + --hash-sig-key-dir /config/hash-sig-keys \ + $aggregator_flag \ + $checkpoint_sync_flag" # choose either binary or docker node_setup="docker" diff --git a/client-cmds/lighthouse-cmd.sh b/client-cmds/lighthouse-cmd.sh index 1e129c2..030b79c 100644 --- a/client-cmds/lighthouse-cmd.sh +++ b/client-cmds/lighthouse-cmd.sh @@ -3,6 +3,18 @@ # Metrics enabled by default metrics_flag="--metrics" +# Set aggregator flag based on isAggregator value +aggregator_flag="" +if [ "$isAggregator" == "true" ]; then + aggregator_flag="--is-aggregator" +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 + node_binary="$lighthouse_bin lean_node \ --datadir \"$dataDir/$item\" \ --config \"$configDir/config.yaml\" \ @@ -14,7 +26,9 @@ node_binary="$lighthouse_bin lean_node \ --socket-port $quicPort\ $metrics_flag \ --metrics-address 0.0.0.0 \ - --metrics-port $metricsPort" + --metrics-port $metricsPort \ + $aggregator_flag \ + $checkpoint_sync_flag" node_docker="hopinheimer/lighthouse:latest lighthouse lean_node \ --datadir /data \ @@ -27,6 +41,8 @@ node_docker="hopinheimer/lighthouse:latest lighthouse lean_node \ --socket-port $quicPort\ $metrics_flag \ --metrics-address 0.0.0.0 \ - --metrics-port $metricsPort" + --metrics-port $metricsPort \ + $aggregator_flag \ + $checkpoint_sync_flag" node_setup="docker" diff --git a/client-cmds/qlean-cmd.sh b/client-cmds/qlean-cmd.sh index 28de40b..0df9e18 100644 --- a/client-cmds/qlean-cmd.sh +++ b/client-cmds/qlean-cmd.sh @@ -3,6 +3,19 @@ #-----------------------qlean setup---------------------- # expects "qlean" submodule or symlink inside "lean-quickstart" root directory # https://github.com/qdrvm/qlean-mini + +# Set aggregator flag based on isAggregator value +aggregator_flag="" +if [ "$isAggregator" == "true" ]; then + aggregator_flag="--is-aggregator" +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 + node_binary="$scriptDir/qlean/build/src/executable/qlean \ --modules-dir $scriptDir/qlean/build/src/modules \ --genesis $configDir/config.yaml \ @@ -15,6 +28,8 @@ node_binary="$scriptDir/qlean/build/src/executable/qlean \ --node-id $item --node-key $configDir/$privKeyPath \ --listen-addr /ip4/0.0.0.0/udp/$quicPort/quic-v1 \ --prometheus-port $metricsPort \ + $aggregator_flag \ + $checkpoint_sync_flag \ -ldebug \ -ltrace" @@ -29,6 +44,8 @@ node_docker="qdrvm/qlean-mini:devnet-2 \ --node-id $item --node-key /config/$privKeyPath \ --listen-addr /ip4/0.0.0.0/udp/$quicPort/quic-v1 \ --prometheus-port $metricsPort \ + $aggregator_flag \ + $checkpoint_sync_flag \ -ldebug \ -ltrace" diff --git a/client-cmds/ream-cmd.sh b/client-cmds/ream-cmd.sh index 9985c92..3585f59 100755 --- a/client-cmds/ream-cmd.sh +++ b/client-cmds/ream-cmd.sh @@ -4,6 +4,18 @@ # Metrics enabled by default metrics_flag="--metrics" +# Set aggregator flag based on isAggregator value +aggregator_flag="" +if [ "$isAggregator" == "true" ]; then + aggregator_flag="--is-aggregator" +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 + # modify the path to the ream binary as per your system node_binary="$scriptDir/../ream/target/release/ream --data-dir $dataDir/$item \ lean_node \ @@ -15,7 +27,9 @@ node_binary="$scriptDir/../ream/target/release/ream --data-dir $dataDir/$item \ $metrics_flag \ --metrics-address 0.0.0.0 \ --metrics-port $metricsPort \ - --http-address 0.0.0.0" + --http-address 0.0.0.0 \ + $aggregator_flag \ + $checkpoint_sync_flag" node_docker="ghcr.io/reamlabs/ream:latest-devnet2 --data-dir /data \ lean_node \ @@ -27,7 +41,9 @@ node_docker="ghcr.io/reamlabs/ream:latest-devnet2 --data-dir /data \ $metrics_flag \ --metrics-address 0.0.0.0 \ --metrics-port $metricsPort \ - --http-address 0.0.0.0" + --http-address 0.0.0.0 \ + $aggregator_flag \ + $checkpoint_sync_flag" # choose either binary or docker node_setup="docker" diff --git a/client-cmds/zeam-cmd.sh b/client-cmds/zeam-cmd.sh index 4b56d7a..6f693d4 100644 --- a/client-cmds/zeam-cmd.sh +++ b/client-cmds/zeam-cmd.sh @@ -6,13 +6,27 @@ # Metrics enabled by default metrics_flag="--metrics_enable" +# Set aggregator flag based on isAggregator value +aggregator_flag="" +if [ "$isAggregator" == "true" ]; then + aggregator_flag="--is-aggregator" +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 + node_binary="$scriptDir/../zig-out/bin/zeam node \ --custom_genesis $configDir \ --validator_config $validatorConfig \ --data-dir $dataDir/$item \ --node-id $item --node-key $configDir/$item.key \ $metrics_flag \ - --api-port $metricsPort" + --api-port $metricsPort \ + $aggregator_flag \ + $checkpoint_sync_flag" node_docker="--security-opt seccomp=unconfined blockblaz/zeam:devnet2 node \ --custom_genesis /config \ @@ -20,7 +34,9 @@ node_docker="--security-opt seccomp=unconfined blockblaz/zeam:devnet2 node \ --data-dir /data \ --node-id $item --node-key /config/$item.key \ $metrics_flag \ - --api-port $metricsPort" + --api-port $metricsPort \ + $aggregator_flag \ + $checkpoint_sync_flag" # choose either binary or docker node_setup="docker" \ No newline at end of file diff --git a/local-devnet/genesis/validator-config.yaml b/local-devnet/genesis/validator-config.yaml index 7f99d48..72d3ad3 100644 --- a/local-devnet/genesis/validator-config.yaml +++ b/local-devnet/genesis/validator-config.yaml @@ -14,6 +14,7 @@ validators: ip: "127.0.0.1" quic: 9001 metricsPort: 8081 + isAggregator: false count: 1 # number of indices for this node - name: "ream_0" @@ -25,6 +26,7 @@ validators: ip: "127.0.0.1" quic: 9002 metricsPort: 8082 + isAggregator: false devnet: 1 count: 1 @@ -36,6 +38,7 @@ validators: ip: "127.0.0.1" quic: 9003 metricsPort: 8083 + isAggregator: false count: 1 - name: "lantern_0" @@ -47,6 +50,7 @@ validators: ip: "127.0.0.1" quic: 9004 metricsPort: 8084 + isAggregator: false count: 1 - name: "lighthouse_0" @@ -58,6 +62,7 @@ validators: ip: "127.0.0.1" quic: 9005 metricsPort: 8085 + isAggregator: false count: 1 - name: "grandine_0" @@ -66,6 +71,7 @@ validators: ip: "127.0.0.1" quic: 9006 metricsPort: 8086 + isAggregator: false count: 1 - name: "ethlambda_0" @@ -77,4 +83,5 @@ validators: ip: "127.0.0.1" quic: 9007 metricsPort: 8087 + isAggregator: false count: 1 diff --git a/parse-env.sh b/parse-env.sh index 84db521..c3b1028 100755 --- a/parse-env.sh +++ b/parse-env.sh @@ -80,6 +80,16 @@ while [[ $# -gt 0 ]]; do stopNodes=true shift ;; + --checkpoint-sync-url) + checkpointSyncUrl="$2" + shift + shift + ;; + --restart-client) + restartClient="$2" + shift + shift + ;; --coreDumps) coreDumps="$2" shift # past argument @@ -91,13 +101,18 @@ while [[ $# -gt 0 ]]; do esac done -# if no node has been assigned assume all nodes to be started -if [[ ! -n "$node" ]]; +# if no node and no restart-client specified, exit +if [[ ! -n "$node" ]] && [[ ! -n "$restartClient" ]]; then - echo "no node specified, exiting..." + echo "no node or restart-client specified, exiting..." exit fi; +# When using --restart-client with checkpoint sync, set default checkpoint URL if not provided +if [[ -n "$restartClient" ]] && [[ ! -n "$checkpointSyncUrl" ]]; then + checkpointSyncUrl="https://leanpoint.leanroadmap.org/lean/v0/states/finalized" +fi; + if [ ! -n "$validatorConfig" ] then echo "no external validator config provided, assuming genesis bootnode" @@ -116,3 +131,5 @@ echo "popupTerminal = $popupTerminal" echo "dockerTag = ${dockerTag:-latest}" echo "enableMetrics = $enableMetrics" echo "coreDumps = ${coreDumps:-disabled}" +echo "checkpointSyncUrl = ${checkpointSyncUrl:-}" +echo "restartClient = ${restartClient:-}" diff --git a/parse-vc.sh b/parse-vc.sh index 8b50e82..629f4e1 100644 --- a/parse-vc.sh +++ b/parse-vc.sh @@ -51,6 +51,12 @@ if [ -z "$devnet" ] || [ "$devnet" == "null" ]; then devnet="" fi +# Automatically extract isAggregator flag using yq (defaults to false if not set) +isAggregator=$(yq eval ".validators[] | select(.name == \"$item\") | .isAggregator // false" "$validator_config_file") +if [ -z "$isAggregator" ] || [ "$isAggregator" == "null" ]; then + isAggregator="false" +fi + # Automatically extract private key using yq privKey=$(yq eval ".validators[] | select(.name == \"$item\") | .privkey" "$validator_config_file") @@ -99,10 +105,12 @@ if [ "$keyType" == "hash-sig" ] && [ "$hashSigKeyIndex" != "null" ] && [ -n "$ha echo "Hash-Sig Key Index: $hashSigKeyIndex" echo "Hash-Sig Public Key: $hashSigPkPath" echo "Hash-Sig Secret Key: $hashSigSkPath" + echo "Is Aggregator: $isAggregator" else echo "Node: $item" echo "QUIC Port: $quicPort" echo "Metrics Port: $metricsPort" echo "Devnet: ${devnet:-}" echo "Private Key File: $privKeyPath" + echo "Is Aggregator: $isAggregator" fi diff --git a/run-ansible.sh b/run-ansible.sh index 3afd48c..1d82736 100755 --- a/run-ansible.sh +++ b/run-ansible.sh @@ -27,6 +27,7 @@ sshKeyFile="$6" useRoot="$7" # Flag to use root user (defaults to current user) action="$8" # Action: "stop" to stop nodes, otherwise deploy coreDumps="$9" # Core dump configuration: "all", node names, or client types +skipGenesis="${10}" # Set to "true" to skip genesis generation (e.g. when restarting with checkpoint sync) # Determine SSH user: use root if --useRoot flag is set, otherwise use current user if [ "$useRoot" == "true" ]; then @@ -112,6 +113,10 @@ if [ -n "$coreDumps" ]; then EXTRA_VARS="$EXTRA_VARS enable_core_dumps=$coreDumps" fi +if [ "$skipGenesis" == "true" ]; then + EXTRA_VARS="$EXTRA_VARS skip_genesis=true" +fi + # Determine deployment mode (docker/binary) - read default from group_vars/all.yml # Default to 'docker' if not specified in group_vars GROUP_VARS_FILE="$ANSIBLE_DIR/inventory/group_vars/all.yml" diff --git a/spin-node.sh b/spin-node.sh index fd61447..920c29e 100755 --- a/spin-node.sh +++ b/spin-node.sh @@ -97,9 +97,37 @@ fi echo "Detected nodes: ${nodes[@]}" # nodes=("zeam_0" "ream_0" "qlean_0") spin_nodes=() - +restart_with_checkpoint_sync=false + +# When --restart-client is specified, use it as the node list and enable checkpoint sync mode +if [[ -n "$restartClient" ]]; then + echo "Note: --restart-client is only used with --checkpoint-sync-url (default: https://leanpoint.leanroadmap.org/lean/v0/states/finalized)" + restart_with_checkpoint_sync=true + # Skip genesis when restarting with checkpoint sync (we're syncing from remote) + generateGenesis=false + # Parse comma-separated client names + IFS=',' read -r -a requested_nodes <<< "$restartClient" + for requested_node in "${requested_nodes[@]}"; do + requested_node=$(echo "$requested_node" | xargs) # trim whitespace + node_found=false + for available_node in "${nodes[@]}"; do + if [[ "$requested_node" == "$available_node" ]]; then + spin_nodes+=("$available_node") + node_found=true + break + fi + done + if [[ "$node_found" == false ]]; then + echo "Error: Node '$requested_node' not found in validator config" + echo "Available nodes: ${nodes[@]}" + exit 1 + fi + done + echo "Restarting with checkpoint sync: ${spin_nodes[*]} from $checkpointSyncUrl" + cleanData=true # Clear data when restarting with checkpoint sync + node_present=true # Parse comma-separated or space-separated node names or handle single node/all -if [[ "$node" == "all" ]]; then +elif [[ "$node" == "all" ]]; then # Spin all nodes spin_nodes=("${nodes[@]}") node_present=true @@ -159,10 +187,21 @@ if [ "$deployment_mode" == "ansible" ]; then echo "✅ Ansible prerequisites validated" + # Determine node list for Ansible: use restartClient/spin_nodes when restarting, else $node + if [[ "$restart_with_checkpoint_sync" == "true" ]]; then + ansible_node_arg=$(IFS=','; echo "${spin_nodes[*]}") + else + ansible_node_arg="$node" + fi + + # Determine skip_genesis for Ansible (true when restarting with checkpoint sync) + ansible_skip_genesis="false" + [[ "$restart_with_checkpoint_sync" == "true" ]] && ansible_skip_genesis="true" + # Handle stop action if [ -n "$stopNodes" ] && [ "$stopNodes" == "true" ]; then echo "Stopping nodes via Ansible..." - if ! "$scriptDir/run-ansible.sh" "$configDir" "$node" "$cleanData" "$validatorConfig" "$validator_config_file" "$sshKeyFile" "$useRoot" "stop" "$coreDumps"; then + if ! "$scriptDir/run-ansible.sh" "$configDir" "$ansible_node_arg" "$cleanData" "$validatorConfig" "$validator_config_file" "$sshKeyFile" "$useRoot" "stop" "$coreDumps" "$ansible_skip_genesis"; then echo "❌ Ansible stop operation failed. Exiting." exit 1 fi @@ -171,7 +210,7 @@ if [ "$deployment_mode" == "ansible" ]; then # Call separate Ansible execution script # If Ansible deployment fails, exit immediately (don't fall through to local deployment) - if ! "$scriptDir/run-ansible.sh" "$configDir" "$node" "$cleanData" "$validatorConfig" "$validator_config_file" "$sshKeyFile" "$useRoot" "" "$coreDumps"; then + if ! "$scriptDir/run-ansible.sh" "$configDir" "$ansible_node_arg" "$cleanData" "$validatorConfig" "$validator_config_file" "$sshKeyFile" "$useRoot" "" "$coreDumps" "$ansible_skip_genesis"; then echo "❌ Ansible deployment failed. Exiting." exit 1 fi @@ -262,6 +301,16 @@ for item in "${spin_nodes[@]}"; do printf '%*s' $(tput cols) | tr ' ' '-' echo + # When restarting with checkpoint sync, stop existing container first + if [[ "$restart_with_checkpoint_sync" == "true" ]]; then + echo "Stopping existing container $item..." + if [ -n "$dockerWithSudo" ]; then + sudo docker rm -f "$item" 2>/dev/null || true + else + docker rm -f "$item" 2>/dev/null || true + fi + fi + # create and/or cleanup datadirs itemDataDir="$dataDir/$item" mkdir -p $itemDataDir @@ -277,6 +326,13 @@ for item in "${spin_nodes[@]}"; do # parse validator-config.yaml for $item to load args values source parse-vc.sh + # export checkpoint_sync_url for client-cmd scripts when restarting with checkpoint sync + if [[ "$restart_with_checkpoint_sync" == "true" ]] && [[ -n "$checkpointSyncUrl" ]]; then + export checkpoint_sync_url="$checkpointSyncUrl" + else + unset checkpoint_sync_url 2>/dev/null || true + fi + # extract client config IFS='_' read -r -a elements <<< "$item" client="${elements[0]}"