Compare commits

..

28 Commits

Author SHA1 Message Date
defc60469b arc: add snapshot-init wrapper for testnet pruned bootstrap
Shell entrypoint wraps arc-snapshots so compose can optionally override EL/CL
snapshot URLs via ARC_SNAPSHOT_* env vars while defaulting to latest from
snapshots.arc.network on fresh volumes.
2026-07-04 05:51:19 +00:00
921fec2e86 deploy: regenerate compose from vibe-node main 1195854e5e9a 2026-07-04 00:34:32 +00:00
70b8cce5af cronos: wire init.sh to context.yml bootstrap env vars
Read chain_id, genesis_url, seeds, and app.toml json-rpc/evm tunables from
environment (set by the generator from context.yml). Fix seed wiring to use
ct_merge_seeds instead of ct_set_persistent_peers.
2026-07-03 22:08:10 +00:00
d94213fd5c fix(jovay/aldaba): replace VERSION subpath mount with startup cp
Docker 28.5.x fails container create when a volume subpath targets a
path that exists as a file in the image. Copy VERSION from the conf
volume mount instead of subpath-mounting onto /opt/l2_deploy/bin/VERSION.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 12:23:13 +00:00
fcf747c6ee taiko: use --chain=mainnet for alethia-reth v1.1.0
The alethia-reth binary expects --chain=mainnet, not --chain=alethia.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 12:19:04 +00:00
e56976adeb taiko: pass BUILD_ALETHIA_RETH=true for alethia-reth compose builds
Without this build arg reth.Dockerfile builds upstream reth and cargo fails
on asm-keccak/jemalloc features missing from the alethia-reth fork.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 10:19:06 +00:00
9d9da8342c ethereum: bump nimbus multiarch-v26.6.0 -> multiarch-v26.6.2
Regenerated compose defaults for all statusim/nimbus-eth2 profiles.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 08:08:12 +00:00
99867025db deploy: regenerate compose from vibe-node main 67e5a65a31a1 2026-07-03 07:56:35 +00:00
bf508e8b07 deploy: regenerate compose from vibe-node main 0e76246fb875 2026-07-03 07:05:14 +00:00
052e74a00d bitcoin-cash: bump bitcoind client_version to 0.33.7
Update mainnet and testnet compose defaults to bitcoinabc/bitcoin-abc:0.33.7.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 06:43:46 +00:00
88bedb0956 fix(stop/start): scope compose to base.yml + node yml
stop.sh and start.sh previously relied on ambient COMPOSE_FILE, so
backup fencing left orchestration unable to stop or restart the target
node. Pass -f base.yml and the node yml explicitly and fail loudly.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 04:53:28 +00:00
e571efbea1 fix(backup): read remote backup list from stdin in selector
select_newest_remote_backup_from_list was sorting an empty process
substitution instead of the piped list-backups.sh output.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 04:38:31 +00:00
58adc446e2 backup: harden lifecycle fencing and skip near-empty archives
backup-node.sh now stops services, fences COMPOSE_FILE during backup, and
restores via EXIT trap; consumers skip <1MB .tar.zst artifacts so purged-
volume junk cannot shadow real backups.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 04:38:00 +00:00
6c0df2bce5 restore-volumes: add /slowdisk absolute floor gate for static offload
Skip static-file offload when projected /slowdisk free space after restore
would fall below SLOWDISK_FLOOR_GB (default 150 GB); warn after extract if
the floor is breached. Restore never aborts — falls back to primary extract.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 03:59:41 +00:00
8f57c8af68 jovay: tail aldaba/cubenet logs to docker logs via tini+bash wrapper
The aldaba_light binary writes sync and p2p logs only to rotating files
under /opt/l2_deploy/light/log/; wrap entry.sh so tail -n0 -F streams new
lines to stdout while preserving file logging and tini PID-1 semantics.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 03:37:22 +00:00
f8915ed59f catchup: per-protocol dispatch for bitcoin, cosmos, and ripple
Extend catchup.sh with protocol-aware branches (bitcoin height-gain,
cosmos CometBFT timestamp via timestamp.sh, ripple validated-ledger
seq) and explicit degradation for closed RPC / unsupported protocols.
Reuse sync-status/check-health idioms for protocol resolution and parsing.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 03:10:24 +00:00
a98ced8af1 jovay: wire aldaba P2P advertise IP/port and host port mapping
Set ADVERTISE_NODE_IP=${IP} and ADVERTISE_NODE_PORT to the salted host
port; map client_port:19000 so inbound cubenet peering is dialable.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 02:47:54 +00:00
1c65fdb26f fix(check-health): retry on unreachable reference endpoint
When multicurl fails to reach the reference RPC (timeout/unreachable),
clean up the temp file, retry up to MAX_RETRIES, then exit with
'unverified (reference unreachable)' instead of falling through as success.

Also add Robinhood mainnet official RPC to reference-rpc-endpoint.json.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 01:36:42 +00:00
sebastian
2fbf996857 Merge pull request 'tac/tacchaind: add Polkachu seeds and statesync RPC config' (#26) from issue-734 into main
Reviewed-on: #26
2026-07-02 23:40:43 +00:00
sebastian
3c8623531f Merge pull request 'op/katana: add Prague/Osaka fork timestamps to genesis' (#27) from issue-739 into main
Reviewed-on: #27
2026-07-02 23:39:23 +00:00
27f10b29d3 babylon: pass --no-bls-password on babylond start
babylond v4.3.0 prompts for a BLS key password on every start when
bls_key.json exists unless start gets --no-bls-password; without it RPC
replicas crash-loop with "failed to get BLS password: EOF".

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-02 18:53:45 +00:00
23e9a5dcd5 katana mainnet: fix genesis.json — preserve alloc, add fork times only
Restore full genesis alloc section; add pragueTime (1746806401) and
osakaTime (1773066601) without truncating predeploy entries.
2026-07-02 16:38:27 +00:00
14b115b7bd katana mainnet: add pragueTime and osakaTime fork activations
op-reth requires pragueTime equal to isthmusTime for custom-genesis OP
chains per OP Upgrade 15; osakaTime added for upcoming Jovian fork.
2026-07-02 16:37:35 +00:00
cb7bb80490 fix: bitcoin rpcallowip IPv4, babylon BLS pre-create, tac peers+cosmos RPC
- Add -rpcallowip=0.0.0.0/0 family-wide via bitcoind template regen
- Pre-create empty-password BLS key in babylon init.sh (v4.3.0 EOF fix)
- TAC: seeds+persistent_peers, CometBFT :26657 traefik, protocol cosmos

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-02 16:04:01 +00:00
eda1068f45 tac mainnet: merge Polkachu seeds in init.sh for peer discovery
Call ct_merge_seeds() so SEEDS env populates config.toml; default
STATESYNC_RPC to tacchain-rpc.polkachu.com for statesync bootstrap.
2026-07-02 14:41:07 +00:00
75b931461d deploy: regenerate compose from vibe-node main de67ec1de6be 2026-07-02 14:08:34 +00:00
rob
4d5d8f4be1 Merge pull request 'katana-mainnet genesis: add isthmusTime + jovianTime (unblock op-reth) [issue-501]' (#25) from issue-501-katana-jovian into main
Reviewed-on: #25
2026-07-02 14:05:25 +00:00
58d45c8576 katana mainnet: add isthmusTime/jovianTime to genesis for op-reth
op-reth reads OP-stack fork schedule from genesis.json; without
isthmusTime/jovianTime it rejects post-Jovian payloads (MinBaseFeeNotAllowedBeforeJovian).
2026-07-02 11:37:11 +00:00
58 changed files with 1116 additions and 138 deletions

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
plume-mainnet-archive: plume-mainnet-archive:
image: ${PLUME_NITRO_IMAGE:-offchainlabs/nitro-node}:${PLUME_MAINNET_NITRO_VERSION:-v3.11.0-a618155} image: ${PLUME_NITRO_IMAGE:-offchainlabs/nitro-node}:${PLUME_MAINNET_NITRO_VERSION:-v3.11.1-8512b8c}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
plume-mainnet-archive: plume-mainnet-archive:
image: ${PLUME_NITRO_IMAGE:-offchainlabs/nitro-node}:${PLUME_MAINNET_NITRO_VERSION:-v3.11.0-a618155} image: ${PLUME_NITRO_IMAGE:-offchainlabs/nitro-node}:${PLUME_MAINNET_NITRO_VERSION:-v3.11.1-8512b8c}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
plume-mainnet: plume-mainnet:
image: ${PLUME_NITRO_IMAGE:-offchainlabs/nitro-node}:${PLUME_MAINNET_NITRO_VERSION:-v3.11.0-a618155} image: ${PLUME_NITRO_IMAGE:-offchainlabs/nitro-node}:${PLUME_MAINNET_NITRO_VERSION:-v3.11.1-8512b8c}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
plume-mainnet: plume-mainnet:
image: ${PLUME_NITRO_IMAGE:-offchainlabs/nitro-node}:${PLUME_MAINNET_NITRO_VERSION:-v3.11.0-a618155} image: ${PLUME_NITRO_IMAGE:-offchainlabs/nitro-node}:${PLUME_MAINNET_NITRO_VERSION:-v3.11.1-8512b8c}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -0,0 +1,12 @@
# One-shot Arc snapshot downloader for compose init containers.
# Wraps arc-snapshots with a shell entrypoint so operators can optionally
# override EL/CL snapshot URLs via environment variables.
ARG ARC_EXECUTION_IMAGE=docker.cloudsmith.io/circle/arc-network/arc-execution:0.7.2
FROM ${ARC_EXECUTION_IMAGE} AS arc-bin
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates libssl3 zlib1g \
&& rm -rf /var/lib/apt/lists/*
COPY --from=arc-bin /usr/local/bin/arc-snapshots /usr/local/bin/arc-snapshots
COPY scripts/snapshot-init.sh /usr/local/bin/snapshot-init.sh
RUN chmod +x /usr/local/bin/snapshot-init.sh
ENTRYPOINT ["/usr/local/bin/snapshot-init.sh"]

23
arc/scripts/snapshot-init.sh Executable file
View File

@@ -0,0 +1,23 @@
#!/bin/sh
set -eu
CHAIN="${ARC_SNAPSHOT_CHAIN:-arc-testnet}"
EXEC_PATH="${ARC_SNAPSHOT_EXECUTION_PATH:-/data/execution}"
CONS_PATH="${ARC_SNAPSHOT_CONSENSUS_PATH:-/data/consensus}"
if [ -n "${ARC_SNAPSHOT_EXECUTION_URL:-}" ] && [ -n "${ARC_SNAPSHOT_CONSENSUS_URL:-}" ]; then
exec /usr/local/bin/arc-snapshots download \
--chain="${CHAIN}" \
--execution-path="${EXEC_PATH}" \
--consensus-path="${CONS_PATH}" \
--execution-url="${ARC_SNAPSHOT_EXECUTION_URL}" \
--consensus-url="${ARC_SNAPSHOT_CONSENSUS_URL}"
elif [ -n "${ARC_SNAPSHOT_EXECUTION_URL:-}" ] || [ -n "${ARC_SNAPSHOT_CONSENSUS_URL:-}" ]; then
echo "Both ARC_SNAPSHOT_EXECUTION_URL and ARC_SNAPSHOT_CONSENSUS_URL must be set together" >&2
exit 1
else
exec /usr/local/bin/arc-snapshots download \
--chain="${CHAIN}" \
--execution-path="${EXEC_PATH}" \
--consensus-path="${CONS_PATH}"
fi

View File

@@ -25,6 +25,13 @@ else
ct_log "already initialized, continuing" ct_log "already initialized, continuing"
fi fi
# v4.x start prompts for a BLS password if no key exists; RPC replicas never sign
# checkpoints, so pre-create an empty-password key before the first start.
if [ ! -f "$CONFIG_DIR/bls_key.json" ]; then
ct_log "pre-creating BLS key (no password — RPC replica)"
babylond create-bls-key --home "$HOME_DIR" --no-bls-password
fi
# Serve RPC on all interfaces (dshackle/traefik upstream); default is 127.0.0.1. # Serve RPC on all interfaces (dshackle/traefik upstream); default is 127.0.0.1.
sed -i '/^\[rpc\]/,/^\[/{s|^laddr = .*|laddr = "tcp://0.0.0.0:26657"|}' "$CONFIG_DIR/config.toml" sed -i '/^\[rpc\]/,/^\[/{s|^laddr = .*|laddr = "tcp://0.0.0.0:26657"|}' "$CONFIG_DIR/config.toml"
@@ -45,4 +52,4 @@ ct_configure_statesync "$CONFIG_DIR/config.toml" "$STATESYNC_RPC"
ct_ensure_wasm "$HOME_DIR" "$WASM_SNAPSHOT_URL" ct_ensure_wasm "$HOME_DIR" "$WASM_SNAPSHOT_URL"
ct_seed_priv_validator_state "$HOME_DIR" ct_seed_priv_validator_state "$HOME_DIR"
exec babylond start --home "$HOME_DIR" --minimum-gas-prices "$MIN_GAS" "$@" exec babylond start --home "$HOME_DIR" --minimum-gas-prices "$MIN_GAS" --no-bls-password "$@"

View File

@@ -1,10 +1,73 @@
#!/bin/bash #!/bin/bash
#
# Backup persistent compose volumes to /backup or WebDAV.
#
# Usage:
# ./backup-node.sh [--hot] [--force] <compose-name> [webdav-url]
#
# Lifecycle (default, omitted with --hot):
# stop services -> fence compose out of COMPOSE_FILE -> tar+zstd -> unfence+start (EXIT trap).
# Hot backups skip stop/fence; leveldb/pebble live tars are NOT restore-trustworthy.
#
# --force Allow backing up an existing but very small datadir (<1GB reported size).
# Does NOT bypass a missing volume path (always fatal).
BASEPATH="$(dirname "$0")" BASEPATH="$(dirname "$0")"
source "$BASEPATH/volume-utils.sh" source "$BASEPATH/volume-utils.sh"
backup_dir="/backup" backup_dir="/backup"
remote_target="$2" HOT_BACKUP=false
FORCE_SMALL=false
_pos=()
for _a in "$@"; do
case "$_a" in
--hot) HOT_BACKUP=true ;;
--force) FORCE_SMALL=true ;;
*) _pos+=("$_a") ;;
esac
done
set -- "${_pos[@]}"
if [ -z "${1:-}" ] || [ ! -f "/root/rpc/$1.yml" ]; then
echo "Error: Either no argument provided or /root/rpc/$1.yml does not exist."
exit 1
fi
compose_name="$1"
remote_target="${2:-}"
lifecycle_active=false
fenced=false
stopped=false
backup_lifecycle_cleanup() {
local rc=$?
if [[ "$lifecycle_active" != true ]]; then
exit "$rc"
fi
if [[ "$fenced" == true ]]; then
unfence_compose_in_env "$compose_name" || true
fenced=false
fi
if [[ "$stopped" == true ]]; then
"$BASEPATH/start.sh" "$compose_name" || true
stopped=false
fi
exit "$rc"
}
if [[ "$HOT_BACKUP" == true ]]; then
echo "WARNING: --hot backup skips stop/fence; live leveldb/pebble archives may not restore cleanly"
else
trap backup_lifecycle_cleanup EXIT
lifecycle_active=true
echo "Stopping services for $compose_name before backup..."
"$BASEPATH/stop.sh" "$compose_name"
stopped=true
if fence_compose_in_env "$compose_name"; then
fenced=true
fi
fi
if [[ -n "$remote_target" ]] && is_local_backup_url "$remote_target"; then if [[ -n "$remote_target" ]] && is_local_backup_url "$remote_target"; then
echo "Target URL points to this server, using local /backup instead of $remote_target" echo "Target URL points to this server, using local /backup instead of $remote_target"
remote_target="" remote_target=""
@@ -62,13 +125,19 @@ generate_volume_metadata() {
} }
# Read the JSON input and extract the list of keys # Read the JSON input and extract the list of keys
keys=$(get_persistent_volume_keys "/root/rpc/$1.yml") keys=$(get_persistent_volume_keys "/root/rpc/$compose_name.yml")
# Iterate over the list of keys # Iterate over the list of keys
for key in $keys; do for key in $keys; do
echo "Executing command with key: /var/lib/docker/volumes/rpc_$key/_data" echo "Executing command with key: /var/lib/docker/volumes/rpc_$key/_data"
source_folder="/var/lib/docker/volumes/rpc_$key/_data" source_folder="/var/lib/docker/volumes/rpc_$key/_data"
if [[ ! -d "$source_folder" ]]; then
echo "FATAL: volume data directory missing, refusing backup: $source_folder" >&2
exit 1
fi
folder_size=$(du -shL "$source_folder" | awk '{ folder_size=$(du -shL "$source_folder" | awk '{
size = $1 size = $1
sub(/[Kk]$/, "", size) # Remove 'K' suffix if present sub(/[Kk]$/, "", size) # Remove 'K' suffix if present
@@ -86,6 +155,11 @@ for key in $keys; do
}') }')
folder_size_gb=$(printf "%.0f" "$folder_size") folder_size_gb=$(printf "%.0f" "$folder_size")
if (( folder_size_gb < 1 )) && [[ "$FORCE_SMALL" != true ]]; then
echo "FATAL: existing datadir too small for backup (${folder_size_gb}G at $source_folder); use --force if intentional" >&2
exit 1
fi
timestamp=$(date +'%Y-%m-%d-%H-%M-%S') timestamp=$(date +'%Y-%m-%d-%H-%M-%S')
target_file="rpc_$key-${timestamp}-${folder_size_gb}G.tar.zst" target_file="rpc_$key-${timestamp}-${folder_size_gb}G.tar.zst"
@@ -119,5 +193,5 @@ done
echo "" echo ""
echo "=== Overall Size Summary ===" echo "=== Overall Size Summary ==="
if [[ -f "$BASEPATH/show-size.sh" ]]; then if [[ -f "$BASEPATH/show-size.sh" ]]; then
"$BASEPATH/show-size.sh" "$1" 2>&1 "$BASEPATH/show-size.sh" "$compose_name" 2>&1
fi fi

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
bitcoin-cash-mainnet: bitcoin-cash-mainnet:
image: ${BITCOIN_CASH_BITCOIND_IMAGE:-bitcoinabc/bitcoin-abc}:${BITCOIN_CASH_MAINNET_BITCOIND_VERSION:-0.33.6} image: ${BITCOIN_CASH_BITCOIND_IMAGE:-bitcoinabc/bitcoin-abc}:${BITCOIN_CASH_MAINNET_BITCOIND_VERSION:-0.33.7}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -60,6 +60,7 @@ services:
- -externalip=${IP} - -externalip=${IP}
- -port=10863 - -port=10863
- -printtoconsole - -printtoconsole
- -rpcallowip=0.0.0.0/0
- -rpcallowip=::/0 - -rpcallowip=::/0
- -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7 - -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7
- -rpcbind=0.0.0.0 - -rpcbind=0.0.0.0

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
bitcoin-cash-testnet: bitcoin-cash-testnet:
image: ${BITCOIN_CASH_BITCOIND_IMAGE:-bitcoinabc/bitcoin-abc}:${BITCOIN_CASH_TESTNET_BITCOIND_VERSION:-0.33.6} image: ${BITCOIN_CASH_BITCOIND_IMAGE:-bitcoinabc/bitcoin-abc}:${BITCOIN_CASH_TESTNET_BITCOIND_VERSION:-0.33.7}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -60,6 +60,7 @@ services:
- -externalip=${IP} - -externalip=${IP}
- -port=14363 - -port=14363
- -printtoconsole - -printtoconsole
- -rpcallowip=0.0.0.0/0
- -rpcallowip=::/0 - -rpcallowip=::/0
- -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7 - -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7
- -rpcbind=0.0.0.0 - -rpcbind=0.0.0.0

View File

@@ -63,6 +63,7 @@ services:
- -maxconnections=64 - -maxconnections=64
- -port=12518 - -port=12518
- -printtoconsole - -printtoconsole
- -rpcallowip=0.0.0.0/0
- -rpcallowip=::/0 - -rpcallowip=::/0
- -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7 - -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7
- -rpcbind=0.0.0.0 - -rpcbind=0.0.0.0

View File

@@ -63,6 +63,7 @@ services:
- -maxconnections=64 - -maxconnections=64
- -port=13668 - -port=13668
- -printtoconsole - -printtoconsole
- -rpcallowip=0.0.0.0/0
- -rpcallowip=::/0 - -rpcallowip=::/0
- -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7 - -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7
- -rpcbind=0.0.0.0 - -rpcbind=0.0.0.0

View File

@@ -25,13 +25,502 @@ s_to_human_readable() {
seconds=$((seconds % 3600)) seconds=$((seconds % 3600))
local minutes=$((seconds / 60)) local minutes=$((seconds / 60))
seconds=$((seconds % 60)) seconds=$((seconds % 60))
printf "%d days, %02d hours, %02d minutes, %02d seconds\n" $days $hours $minutes $seconds printf "%d days, %02d hours, %02d minutes, %02d seconds\n" $days $hours $minutes $seconds
} }
BASEPATH="$(dirname "$0")" BASEPATH="$(dirname "$0")"
source $BASEPATH/.env 2>/dev/null || true source $BASEPATH/.env 2>/dev/null || true
compose_base="$1"
seconds_to_measure=${2:-10}
if [ -z "$compose_base" ]; then
echo -e "${RED}Error: compose file path (sans .yml) required${NC}"
exit 1
fi
compose_yml="$BASEPATH/${compose_base}.yml"
if [ ! -f "$compose_yml" ]; then
echo -e "${RED}Error: compose file not found: $compose_yml${NC}"
exit 1
fi
if [ -n "$NO_SSL" ]; then
PROTO="http"
DOMAIN="${DOMAIN:-0.0.0.0}"
else
PROTO="https"
fi
# Resolve traefik RPC path from compose labels (first non-blacklisted path).
compose_rpc_path() {
local pathlist path
pathlist=$(grep -oP "stripprefix\.prefixes.*?/\K[^\"]+" "$compose_yml" 2>/dev/null)
for path in $pathlist; do
echo "$path"
return 0
done
return 1
}
compose_rpc_url() {
local path
path=$(compose_rpc_path) || return 1
echo "$PROTO://$DOMAIN/$path"
}
compose_chain_slug() {
grep -oP '^\s*chain:\s*\K\S+' "$compose_yml" 2>/dev/null | head -1
}
# Registry protocol via x-upstreams chain label; path-substring fallback for legacy composes.
resolve_protocol() {
local chain_slug protocol path
chain_slug=$(compose_chain_slug)
protocol=""
if [ -n "$chain_slug" ]; then
protocol=$($BASEPATH/reference-rpc-endpoint.sh --protocol "$chain_slug" 2>/dev/null) || protocol=""
fi
if [ -z "$protocol" ]; then
path=$(compose_rpc_path 2>/dev/null) || path=""
if echo "$path" | grep -qi "starknet"; then
protocol="starknet"
elif echo "$path" | grep -qi "aztec"; then
protocol="aztec"
elif echo "$path" | grep -qiE "bitcoin|digibyte|dogecoin|dash"; then
protocol="bitcoin"
elif echo "$path" | grep -qi "ripple"; then
protocol="ripple"
elif echo "$path" | grep -qiE "cosmos|babylon|haqq|gaiad|tac"; then
protocol="cosmos"
else
protocol="eth"
fi
fi
echo "$protocol"
}
# Bitcoin-family RPC URL (traefik path) and basic-auth from x-upstreams (fallback username:password).
bitcoin_rpc_url() {
compose_rpc_url
}
bitcoin_rpc_auth() {
# Prefer creds from compose x-upstreams basic-auth; per-chain rpcauth may differ on-host.
local user pass
user=$(grep -A5 'basic-auth:' "$compose_yml" 2>/dev/null | grep -oP '^\s*username:\s*\K\S+' | head -1)
pass=$(grep -A5 'basic-auth:' "$compose_yml" 2>/dev/null | grep -oP '^\s*password:\s*\K\S+' | head -1)
[ -z "$user" ] && user="username"
[ -z "$pass" ] && pass="password"
echo "${user}:${pass}"
}
bitcoin_rpc_call() {
local method="$1"
local params="${2:-[]}"
local url auth
url=$(bitcoin_rpc_url) || return 1
auth=$(bitcoin_rpc_auth)
curl -L --ipv4 -m 5 -s -u "$auth" -X POST -H "Content-Type: application/json" \
--data "{\"jsonrpc\":\"1.0\",\"id\":1,\"method\":\"$method\",\"params\":$params}" "$url"
}
bitcoin_parse_blocks_headers() {
local info="$1"
local blocks headers
blocks=$(echo "$info" | jq -r '.result.blocks // empty' 2>/dev/null)
headers=$(echo "$info" | jq -r '.result.headers // empty' 2>/dev/null)
if [[ ! "$blocks" =~ ^[0-9]+$ ]] || [[ ! "$headers" =~ ^[0-9]+$ ]]; then
return 1
fi
echo "$blocks $headers"
}
bitcoin_reference_height() {
local chain_slug="$1"
local ref_urls ref_url resp height
ref_urls=$($BASEPATH/reference-rpc-endpoint.sh --chain "$chain_slug" 2>/dev/null) || return 1
ref_url=$(echo "$ref_urls" | awk '{print $1}')
[ -z "$ref_url" ] && return 1
resp=$(curl -L --ipv4 -m 5 -s -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"1.0","id":1,"method":"getblockcount","params":[]}' "$ref_url")
if [ -z "$resp" ] || echo "$resp" | grep -qi 'Unknown network'; then
return 2
fi
height=$(echo "$resp" | jq -r '.result // empty' 2>/dev/null)
if [[ ! "$height" =~ ^[0-9]+$ ]]; then
return 2
fi
echo "$height"
}
bitcoin_pick_seed_peer() {
local chain_slug="$1" path
path=$(compose_rpc_path 2>/dev/null) || path=""
if echo "$chain_slug $path" | grep -qi "digibyte"; then
echo "seed.digibyte.co:12024"
return 0
fi
if echo "$chain_slug $path" | grep -qi "dogecoin"; then
# TODO: dogecoin wire seeds
return 1
fi
if echo "$chain_slug $path" | grep -qi "dash"; then
# TODO: dash wire seeds
return 1
fi
# Bitcoin mainnet / testnet / cash family default
echo "seed.bitcoin.sipa.be:8333"
}
bitcoin_try_addnode() {
local chain_slug="$1" peer resp
peer=""
local ref_urls ref_url pinfo
ref_urls=$($BASEPATH/reference-rpc-endpoint.sh --chain "$chain_slug" 2>/dev/null) || ref_urls=""
ref_url=$(echo "$ref_urls" | awk '{print $1}')
if [ -n "$ref_url" ]; then
pinfo=$(curl -L --ipv4 -m 5 -s -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"1.0","id":1,"method":"getpeerinfo","params":[]}' "$ref_url" 2>/dev/null)
peer=$(echo "$pinfo" | jq -r '.result[0].addr // empty' 2>/dev/null)
fi
if [ -z "$peer" ] || [ "$peer" = "null" ]; then
peer=$(bitcoin_pick_seed_peer "$chain_slug") || return 0
fi
resp=$(bitcoin_rpc_call "addnode" "[\"$peer\", \"onetry\"]")
if echo "$resp" | jq -e '.error == null' >/dev/null 2>&1; then
echo "Issued harmless addnode onetry to $peer"
fi
}
report_block_catchup_rate() {
local gap_change="$1"
local interval="$2"
local block_time_ms="$3"
local gap_remaining="$4"
local label="${5:-blocks}"
local block_time_sec realtime_units effective catchup_rate
block_time_sec=$(echo "scale=6; $block_time_ms / 1000" | bc)
realtime_units=$(echo "scale=6; $interval / $block_time_sec" | bc)
effective=$(echo "scale=6; $realtime_units - $gap_change" | bc)
catchup_rate=$(echo "scale=3; $effective / $realtime_units" | bc)
echo "First measurement: $label behind = $((gap_remaining - gap_change)) $label"
echo "Second measurement: $label behind = $gap_remaining $label"
echo "Gap change in $interval seconds: $gap_change $label"
echo "Calculated catchup rate: ${catchup_rate}x realtime"
if (( $(echo "$catchup_rate < 0" | bc -l) )); then
local falling_behind_rate
falling_behind_rate=$(echo "scale=2; -1 * $catchup_rate" | bc)
echo -e "${RED}Node is FALLING BEHIND by ${falling_behind_rate}x realtime${NC}"
echo -e "${RED}The gap increased by $gap_change $label over $interval seconds${NC}"
return 1
elif (( $(echo "$catchup_rate < 1" | bc -l) )); then
echo -e "${YELLOW}WARNING: Node is processing at ${catchup_rate}x realtime${NC}"
echo -e "${YELLOW}This is too slow - node will never catch up to chain head${NC}"
return 2
else
echo -e "${GREEN}Node is processing at ${catchup_rate}x realtime${NC}"
local time_to_catchup
time_to_catchup=$(echo "scale=0; $gap_remaining * $block_time_sec / ($catchup_rate - 1)" | bc)
echo -e "${GREEN}Estimated time until synced:${NC}"
s_to_human_readable "$time_to_catchup"
return 0
fi
}
bitcoin_catchup() {
local chain_slug="$1"
local interval="$2"
local block_time_ms info1 info2 blocks1 headers1 blocks2 headers2
local ref1 ref2 use_pseudo=false gap1 gap2 gap_change
block_time_ms=$($BASEPATH/reference-rpc-endpoint.sh --block-time-ms "$chain_slug" 2>/dev/null) || block_time_ms="600000"
echo "Checking sync status for $compose_base (bitcoin-family)..."
info1=$(bitcoin_rpc_call "getblockchaininfo")
if [ -z "$info1" ]; then
echo -e "${RED}rpc-not-open (expected mid-sync for stage-sync/bootstrap clients — avalanchego, erigon/reth stage-sync, statesync bootstraps); re-run at chainhead${NC}"
exit 1
fi
read -r blocks1 headers1 < <(bitcoin_parse_blocks_headers "$info1") || {
echo -e "${RED}rpc-not-open (expected mid-sync for stage-sync/bootstrap clients — avalanchego, erigon/reth stage-sync, statesync bootstraps); re-run at chainhead${NC}"
exit 1
}
ref1=$(bitcoin_reference_height "$chain_slug")
local ref_rc1=$?
if [ "$ref_rc1" -eq 2 ]; then
use_pseudo=true
ref1=$headers1
echo "Reference RPC unavailable (Unknown network) — using local headers as pseudo-reference"
elif [ "$ref_rc1" -ne 0 ]; then
use_pseudo=true
ref1=$headers1
echo "Reference RPC unavailable — using local headers as pseudo-reference"
fi
gap1=$((ref1 - blocks1))
echo "Current chain head is $gap1 blocks behind reference"
s_to_human_readable $(echo "scale=0; $gap1 * $block_time_ms / 1000" | bc)
echo "Measuring progress over $interval seconds..."
sleep "$interval"
info2=$(bitcoin_rpc_call "getblockchaininfo")
if [ -z "$info2" ]; then
echo -e "${RED}rpc-not-open (expected mid-sync for stage-sync/bootstrap clients — avalanchego, erigon/reth stage-sync, statesync bootstraps); re-run at chainhead${NC}"
exit 1
fi
read -r blocks2 headers2 < <(bitcoin_parse_blocks_headers "$info2") || {
echo -e "${RED}rpc-not-open (expected mid-sync for stage-sync/bootstrap clients — avalanchego, erigon/reth stage-sync, statesync bootstraps); re-run at chainhead${NC}"
exit 1
}
if $use_pseudo; then
ref2=$headers2
else
ref2=$(bitcoin_reference_height "$chain_slug")
local ref_rc2=$?
if [ "$ref_rc2" -ne 0 ]; then
ref2=$headers2
use_pseudo=true
fi
fi
gap2=$((ref2 - blocks2))
gap_change=$((gap2 - gap1))
report_block_catchup_rate "$gap_change" "$interval" "$block_time_ms" "$gap2" "blocks"
local rc=$?
if [ "$rc" -eq 1 ] && [ -n "$chain_slug" ]; then
bitcoin_try_addnode "$chain_slug"
fi
exit "$rc"
}
ripple_rpc_call() {
local url
url=$(compose_rpc_url) || return 1
curl -L --ipv4 -m 5 -s -X POST -H "Content-Type: application/json" \
--data '{"method":"server_info"}' "$url"
}
ripple_validated_seq() {
local resp="$1" seq
seq=$(echo "$resp" | jq -r '.result.info.validated_ledger.seq // .info.validated_ledger.seq // empty' 2>/dev/null)
if [[ ! "$seq" =~ ^[0-9]+$ ]]; then
return 1
fi
echo "$seq"
}
ripple_reference_seq() {
local chain_slug="$1" ref_urls ref_url resp
ref_urls=$($BASEPATH/reference-rpc-endpoint.sh --chain "$chain_slug" 2>/dev/null) || return 1
ref_url=$(echo "$ref_urls" | awk '{print $1}')
[ -z "$ref_url" ] && return 1
resp=$(curl -L --ipv4 -m 5 -s -X POST -H "Content-Type: application/json" \
--data '{"method":"server_info"}' "$ref_url")
ripple_validated_seq "$resp"
}
ripple_catchup() {
local chain_slug="$1"
local interval="$2"
local block_time_ms resp1 resp2 seq1 seq2 ref1 ref2 gap1 gap2 gap_change
block_time_ms=$($BASEPATH/reference-rpc-endpoint.sh --block-time-ms "$chain_slug" 2>/dev/null) || block_time_ms="4000"
echo "Checking sync status for $compose_base (ripple)..."
resp1=$(ripple_rpc_call)
if [ -z "$resp1" ]; then
echo -e "${RED}rpc-not-open (expected mid-sync for stage-sync/bootstrap clients — avalanchego, erigon/reth stage-sync, statesync bootstraps); re-run at chainhead${NC}"
exit 1
fi
seq1=$(ripple_validated_seq "$resp1") || {
echo -e "${RED}rpc-not-open (expected mid-sync for stage-sync/bootstrap clients — avalanchego, erigon/reth stage-sync, statesync bootstraps); re-run at chainhead${NC}"
exit 1
}
ref1=$(ripple_reference_seq "$chain_slug") || ref1=""
if [ -z "$ref1" ]; then
gap1=0
echo "Reference RPC unavailable — measuring local validated-ledger progress only"
else
gap1=$((ref1 - seq1))
echo "Current chain head is $gap1 ledgers behind reference"
s_to_human_readable $(echo "scale=0; $gap1 * $block_time_ms / 1000" | bc)
fi
echo "Measuring progress over $interval seconds..."
sleep "$interval"
resp2=$(ripple_rpc_call)
if [ -z "$resp2" ]; then
echo -e "${RED}rpc-not-open (expected mid-sync for stage-sync/bootstrap clients — avalanchego, erigon/reth stage-sync, statesync bootstraps); re-run at chainhead${NC}"
exit 1
fi
seq2=$(ripple_validated_seq "$resp2") || {
echo -e "${RED}rpc-not-open (expected mid-sync for stage-sync/bootstrap clients — avalanchego, erigon/reth stage-sync, statesync bootstraps); re-run at chainhead${NC}"
exit 1
}
ref2=$(ripple_reference_seq "$chain_slug") || ref2=""
if [ -z "$ref1" ] || [ -z "$ref2" ]; then
local seq_gain=$((seq2 - seq1))
local realtime_units effective catchup_rate
realtime_units=$(echo "scale=6; $interval * 1000 / $block_time_ms" | bc)
effective=$(echo "scale=6; $seq_gain" | bc)
catchup_rate=$(echo "scale=3; $effective / $realtime_units" | bc)
echo "Validated ledger gain in $interval seconds: $seq_gain ledgers"
echo "Calculated catchup rate: ${catchup_rate}x realtime"
if (( $(echo "$catchup_rate < 1" | bc -l) )); then
if (( $(echo "$catchup_rate < 0" | bc -l) )); then
echo -e "${RED}Node is FALLING BEHIND${NC}"
exit 1
fi
echo -e "${YELLOW}WARNING: Node is processing at ${catchup_rate}x realtime${NC}"
exit 2
fi
echo -e "${GREEN}Node is processing at ${catchup_rate}x realtime${NC}"
exit 0
fi
gap2=$((ref2 - seq2))
gap_change=$((gap2 - gap1))
report_block_catchup_rate "$gap_change" "$interval" "$block_time_ms" "$gap2" "ledgers"
exit $?
}
cosmos_catching_up() {
local url status catching_up
url=$(compose_rpc_url) || return 1
status=$(curl -L --ipv4 -m 5 -s -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","id":1,"method":"status"}' "$url")
catching_up=$(echo "$status" | jq -r '.result.sync_info.catching_up // .sync_info.catching_up // empty' 2>/dev/null)
echo "$catching_up"
}
cosmos_catchup() {
local catching_up
echo "Checking sync status for $compose_base (cosmos/cometbft)..."
catching_up=$(cosmos_catching_up)
if [ "$catching_up" = "true" ]; then
echo "CometBFT reports catching_up=true (node is still syncing)"
elif [ -z "$catching_up" ]; then
echo -e "${RED}rpc-not-open (expected mid-sync for stage-sync/bootstrap clients — avalanchego, erigon/reth stage-sync, statesync bootstraps); re-run at chainhead${NC}"
exit 1
fi
# Standard timestamp-lag algorithm via timestamp.sh (cosmos /status source).
echo "Debug: Running ./timestamp.sh $compose_base"
timestamp_output=$(./timestamp.sh "$compose_base" 2>&1)
timestamp_exit_code=$?
echo "Debug: timestamp.sh output: '$timestamp_output'"
echo "Debug: timestamp.sh exit code: $timestamp_exit_code"
latest_block_timestamp_decimal=$(echo "$timestamp_output" | grep -o '[0-9]\+' | head -1)
if [[ $timestamp_exit_code -ne 0 || -z "$latest_block_timestamp_decimal" ]]; then
echo -e "${RED}rpc-not-open (expected mid-sync for stage-sync/bootstrap clients — avalanchego, erigon/reth stage-sync, statesync bootstraps); re-run at chainhead${NC}"
exit 1
fi
current_time=$(date +%s)
time_difference=$((current_time - latest_block_timestamp_decimal))
echo "Current chain head is $time_difference seconds behind real time"
if [ "$catching_up" = "true" ]; then
echo "(catching_up=true)"
fi
s_to_human_readable $time_difference
echo "Measuring progress over $seconds_to_measure seconds..."
sleep $seconds_to_measure
catching_up=$(cosmos_catching_up)
if [ "$catching_up" = "true" ]; then
echo "CometBFT still reports catching_up=true"
fi
echo "Debug: Running ./timestamp.sh $compose_base (second measurement)"
timestamp_output=$(./timestamp.sh "$compose_base" 2>&1)
timestamp_exit_code=$?
echo "Debug: timestamp.sh output (second): '$timestamp_output'"
echo "Debug: timestamp.sh exit code (second): $timestamp_exit_code"
latest_block_timestamp2=$(echo "$timestamp_output" | grep -o '[0-9]\+' | head -1)
if [[ $timestamp_exit_code -ne 0 || -z "$latest_block_timestamp2" ]]; then
echo -e "${RED}rpc-not-open (expected mid-sync for stage-sync/bootstrap clients — avalanchego, erigon/reth stage-sync, statesync bootstraps); re-run at chainhead${NC}"
exit 1
fi
current_time2=$(date +%s)
time_difference2=$((current_time2 - latest_block_timestamp2))
gap_change=$((time_difference2 - time_difference))
effective_catchup_seconds=$((seconds_to_measure - gap_change))
catchup_rate=$(echo "scale=3; $effective_catchup_seconds / $seconds_to_measure" | bc)
echo "First measurement: Time behind = $time_difference seconds"
echo "Second measurement: Time behind = $time_difference2 seconds"
if [ "$catching_up" = "true" ]; then
echo "(catching_up=true)"
fi
echo "Gap change in $seconds_to_measure seconds: $gap_change seconds"
echo "Calculated catchup rate: $catchup_rate× realtime"
if (( $(echo "$catchup_rate < 0" | bc -l) )); then
falling_behind_rate=$(echo "scale=2; -1 * $catchup_rate" | bc)
echo -e "${RED}Node is FALLING BEHIND by $falling_behind_rate× realtime${NC}"
echo -e "${RED}The gap increased by $gap_change seconds over $seconds_to_measure seconds${NC}"
exit 1
elif (( $(echo "$catchup_rate < 1" | bc -l) )); then
echo -e "${YELLOW}WARNING: Node is processing at $catchup_rate× realtime${NC}"
echo -e "${YELLOW}This is too slow - node will never catch up to chain head${NC}"
exit 2
else
echo -e "${GREEN}Node is processing at $catchup_rate× realtime${NC}"
time_to_catchup=$(echo "scale=0; $time_difference2 / ($catchup_rate - 1)" | bc)
echo -e "${GREEN}Estimated time until synced:${NC}"
s_to_human_readable $time_to_catchup
exit 0
fi
}
protocol=$(resolve_protocol)
chain_slug=$(compose_chain_slug)
case "$protocol" in
bitcoin)
bitcoin_catchup "$chain_slug" "$seconds_to_measure"
;;
ripple)
ripple_catchup "$chain_slug" "$seconds_to_measure"
;;
cosmos)
cosmos_catchup
;;
eth|starknet|aztec)
;;
*)
echo "unsupported protocol $protocol for catchup"
exit 1
;;
esac
# --- eth / starknet / aztec: original timestamp-lag path (unchanged) ---
seconds_to_measure=${2:-10} seconds_to_measure=${2:-10}
# First measurement # First measurement
@@ -55,7 +544,7 @@ fi
current_time=$(date +%s) current_time=$(date +%s)
time_difference=$((current_time - latest_block_timestamp_decimal)) time_difference=$((current_time - latest_block_timestamp_decimal))
# Check for reasonable time difference # Check for reasonable time difference
echo "Current chain head is $time_difference seconds behind real time" echo "Current chain head is $time_difference seconds behind real time"
s_to_human_readable $time_difference s_to_human_readable $time_difference

View File

@@ -380,6 +380,14 @@ if [ $? -eq 0 ]; then
echo "unverified ($http_status_code2)" echo "unverified ($http_status_code2)"
exit 1 exit 1
fi fi
else
rm "$response_file2"
if [ $attempt -lt $MAX_RETRIES ]; then
attempt=$((attempt + 1))
continue
fi
echo "unverified (reference unreachable)"
exit 1
fi fi
done done

View File

@@ -14,6 +14,8 @@
set -euo pipefail set -euo pipefail
BASEPATH="$(cd "$(dirname "$0")" && pwd)" BASEPATH="$(cd "$(dirname "$0")" && pwd)"
# shellcheck source=volume-utils.sh
source "$BASEPATH/volume-utils.sh"
BACKUP_DIR="${BACKUP_DIR:-/backup}" BACKUP_DIR="${BACKUP_DIR:-/backup}"
TRASH_DIR="${TRASH_DIR:-$BACKUP_DIR/trash}" TRASH_DIR="${TRASH_DIR:-$BACKUP_DIR/trash}"
KEEP_COUNT="${KEEP_COUNT:-3}" KEEP_COUNT="${KEEP_COUNT:-3}"
@@ -163,6 +165,20 @@ cleanup_volume_backups() {
continue continue
fi fi
if ! is_restorable_backup_archive "$file"; then
local near_size
near_size=$(backup_archive_size_bytes "$file")
local near_meta
near_meta=$(metadata_for_archive "$file")
add_trashed_bytes "$file"
trash_file "$file" "near-empty artifact (${near_size} bytes, excluded from KEEP_COUNT)"
if [[ -f "$near_meta" ]]; then
add_trashed_bytes "$near_meta"
trash_file "$near_meta" "metadata for near-empty artifact"
fi
continue
fi
volume_files["$volume_key"]+="$file"$'\n' volume_files["$volume_key"]+="$file"$'\n'
done < <(find "$BACKUP_DIR" -maxdepth 1 -type f -name 'rpc_*-*.tar.zst' -print0 2>/dev/null) done < <(find "$BACKUP_DIR" -maxdepth 1 -type f -name 'rpc_*-*.tar.zst' -print0 2>/dev/null)

View File

@@ -294,11 +294,12 @@ transfer_backup() {
local key=$1 local key=$1
local volume_name="rpc_$key" local volume_name="rpc_$key"
# Find the newest backup file # Find the newest restorable backup file (skip near-empty artifacts)
local backup_file=$(ls -1 "$backup_dir"/"${volume_name}"-[0-9]*G.tar.zst 2>/dev/null | sort | tail -n 1) local backup_file
backup_file=$(select_newest_local_backup "$backup_dir" "$volume_name")
if [[ -z "$backup_file" ]] || [[ ! -f "$backup_file" ]]; then if [[ -z "$backup_file" ]] || [[ ! -f "$backup_file" ]]; then
echo "Warning: No backup file found for $volume_name, skipping" echo "Warning: No restorable backup file found for $volume_name, skipping"
return 1 return 1
fi fi
@@ -482,11 +483,12 @@ transfer_backup_ssh() {
local key=$1 local key=$1
local volume_name="rpc_$key" local volume_name="rpc_$key"
# Find the newest backup file # Find the newest restorable backup file (skip near-empty artifacts)
local backup_file=$(ls -1 "$backup_dir"/"${volume_name}"-[0-9]*G.tar.zst 2>/dev/null | sort | tail -n 1) local backup_file
backup_file=$(select_newest_local_backup "$backup_dir" "$volume_name")
if [[ -z "$backup_file" ]] || [[ ! -f "$backup_file" ]]; then if [[ -z "$backup_file" ]] || [[ ! -f "$backup_file" ]]; then
echo "Warning: No backup file found for $volume_name, skipping" echo "Warning: No restorable backup file found for $volume_name, skipping"
return 1 return 1
fi fi

View File

@@ -61,10 +61,18 @@ services:
environment: environment:
- API=eth,txpool,net,debug,web3 - API=eth,txpool,net,debug,web3
- CHAINID=cronosmainnet_25-1 - CHAINID=cronosmainnet_25-1
- CHAINNAME=mainnet - EVM_MAX_TX_GAS_WANTED=500000
- GENESIS_URL=https://raw.githubusercontent.com/crypto-org-chain/cronos-mainnet/master/cronosmainnet_25-1/genesis.json
- IP=${IP} - IP=${IP}
- JSON_RPC_BLOCK_RANGE_CAP=10000
- JSON_RPC_ENABLE=true
- JSON_RPC_ENABLE_INDEXER=true
- JSON_RPC_FEEHISTORY_CAP=100
- JSON_RPC_HTTP_TIMEOUT=30s
- JSON_RPC_LOGS_CAP=10000
- MONIKER=d${DOMAIN:-local} - MONIKER=d${DOMAIN:-local}
- P2P_PORT=10521 - P2P_PORT=10521
- SEEDS=0d5cf1394a1cfde28dc8f023567222abc0f47534@seed-0.cronos.com:26656,3032073adc06d710dd512240281637c1bd0c8a7b@seed-1.cronos.com:26656,04f43116b4c6c70054d9c2b7485383df5b1ed1da@seed-2.cronos.com:26656,337377dcda43d79c537d2c4d93ad3b698ce9452e@bd-cronos-mainnet-seed-node-01.bdnodes.net:26656
restart: unless-stopped restart: unless-stopped
stop_grace_period: 5m stop_grace_period: 5m
networks: networks:

View File

@@ -1,69 +1,53 @@
#!/bin/sh #!/bin/sh
# cronosd entrypoint — Cronos (Cosmos-SDK + embedded EVM). EVM JSON-RPC :8545 / WS :8546
set -e # Exit on failure # are the dshackle/traefik upstream; CometBFT :26657 stays internal. Bootstrap params
# (chain_id, genesis_url, seeds, app.toml tunables) come from context.yml via env.
echo "MONIKER: $MONIKER" set -e
CHAINID=${CHAINID:-cronosmainnet_25-1}
CHAINNAME=${CHAINNAME:-mainnet}
API=${API:-eth,txpool,net,debug,web3}
CONFIG_DIR="/root/.cronos/config"
# Create config directory
mkdir -p "$CONFIG_DIR"
P2P_STRING="tcp:\/\/0\.0\.0\.0\:${P2P_PORT:-10521}"
NAT_STRING="${IP}:${P2P_PORT:-10521}"
env
# this goes first because it won't overwrite shit
apk add curl jq
if [ $? -ne 0 ]; then exit 1; fi
# Source the shared CometBFT helpers
. /usr/local/bin/cometbft-common.sh . /usr/local/bin/cometbft-common.sh
if cronosd init ${MONIKER} --chain-id ${CHAINID} --home /root/.cronos/; then HOME_DIR="/root/.cronos"
# Define variables CONFIG_DIR="$HOME_DIR/config"
GENESIS_URL="https://raw.githubusercontent.com/crypto-org-chain/cronos-mainnet/master/cronosmainnet_25-1/genesis.json" CHAINID="${CHAINID:-cronosmainnet_25-1}"
SEEDS="0d5cf1394a1cfde28dc8f023567222abc0f47534@cronos-seed-0.crypto.org:26656,3032073adc06d710dd512240281637c1bd0c8a7b@cronos-seed-1.crypto.org:26656,04f43116b4c6c70054d9c2b7485383df5b1ed1da@cronos-seed-2.crypto.org:26656" API="${API:-eth,txpool,net,debug,web3}"
GENESIS_URL="${GENESIS_URL:-https://raw.githubusercontent.com/crypto-org-chain/cronos-mainnet/master/cronosmainnet_25-1/genesis.json}"
# Download config files SEEDS="${SEEDS:-0d5cf1394a1cfde28dc8f023567222abc0f47534@seed-0.cronos.com:26656,3032073adc06d710dd512240281637c1bd0c8a7b@seed-1.cronos.com:26656,04f43116b4c6c70054d9c2b7485383df5b1ed1da@seed-2.cronos.com:26656,337377dcda43d79c537d2c4d93ad3b698ce9452e@bd-cronos-mainnet-seed-node-01.bdnodes.net:26656}"
curl -sL "$GENESIS_URL" -o "$CONFIG_DIR/genesis.json" JSON_RPC_ENABLE="${JSON_RPC_ENABLE:-true}"
JSON_RPC_ENABLE_INDEXER="${JSON_RPC_ENABLE_INDEXER:-true}"
# somehow it's better to make home static to /root JSON_RPC_FEEHISTORY_CAP="${JSON_RPC_FEEHISTORY_CAP:-100}"
sed -i 's|~/|/root/|g' "$CONFIG_DIR/config.toml" JSON_RPC_LOGS_CAP="${JSON_RPC_LOGS_CAP:-10000}"
sed -i 's|~/|/root/|g' "$CONFIG_DIR/app.toml" JSON_RPC_BLOCK_RANGE_CAP="${JSON_RPC_BLOCK_RANGE_CAP:-10000}"
JSON_RPC_HTTP_TIMEOUT="${JSON_RPC_HTTP_TIMEOUT:-30s}"
EVM_MAX_TX_GAS_WANTED="${EVM_MAX_TX_GAS_WANTED:-500000}"
ct_apk curl jq
if cronosd init "${MONIKER:-rpc-node}" --chain-id "$CHAINID" --home "$HOME_DIR" >/dev/null 2>&1; then
ct_log "fresh init; fetching genesis"
ct_fetch "$GENESIS_URL" "$CONFIG_DIR/genesis.json" required
ct_localize_home "$CONFIG_DIR"
else else
echo "Already initialized, continuing!" >&2 ct_log "already initialized, continuing"
fi fi
# Localize home directory paths sed -i -e "s/^pruning *=.*/pruning = \"custom\"/" "$CONFIG_DIR/app.toml"
ct_localize_home /root/.cronos/config sed -i -e "s/^pruning-keep-recent *=.*/pruning-keep-recent = \"100\"/" "$CONFIG_DIR/app.toml"
sed -i -e "s/^pruning-interval *=.*/pruning-interval = \"19\"/" "$CONFIG_DIR/app.toml"
# apply a port change to the config sed -i -e "s/^indexer *=.*/indexer = \"null\"/" "$CONFIG_DIR/config.toml"
ct_patch_p2p "$CONFIG_DIR/config.toml" "$IP" "${P2P_PORT:-10521}"
sed -i -e "s/^pruning *=.*/pruning = \"custom\"/" $CONFIG_DIR/app.toml
sed -i -e "s/^pruning-keep-recent *=.*/pruning-keep-recent = \"100\"/" $CONFIG_DIR/app.toml
sed -i -e "s/^pruning-interval *=.*/pruning-interval = \"19\"/" $CONFIG_DIR/app.toml
sed -i -e "s/^indexer *=.*/indexer = \"null\"/" $CONFIG_DIR/config.toml
sed -i "/^\[json-rpc\]/,/^\[/{s|^address = .*|address = \"0.0.0.0:8545\"|}" "$CONFIG_DIR/app.toml" sed -i "/^\[json-rpc\]/,/^\[/{s|^address = .*|address = \"0.0.0.0:8545\"|}" "$CONFIG_DIR/app.toml"
sed -i "/^\[json-rpc\]/,/^\[/{s|^ws-address = .*|ws-address = \"0.0.0.0:8546\"|}" "$CONFIG_DIR/app.toml" sed -i "/^\[json-rpc\]/,/^\[/{s|^ws-address = .*|ws-address = \"0.0.0.0:8546\"|}" "$CONFIG_DIR/app.toml"
sed -i "/^\[json-rpc\]/,/^\[/{s|^api = .*|api = \"$API\"|}" "$CONFIG_DIR/app.toml" sed -i "/^\[json-rpc\]/,/^\[/{s|^api = .*|api = \"$API\"|}" "$CONFIG_DIR/app.toml"
sed -i "/^\[json-rpc\]/,/^\[/{s|^enable = .*|enable = $JSON_RPC_ENABLE|}" "$CONFIG_DIR/app.toml"
sed -i "/^\[json-rpc\]/,/^\[/{s|^enable-indexer = .*|enable-indexer = $JSON_RPC_ENABLE_INDEXER|}" "$CONFIG_DIR/app.toml"
sed -i "/^\[json-rpc\]/,/^\[/{s|^feehistory-cap = .*|feehistory-cap = $JSON_RPC_FEEHISTORY_CAP|}" "$CONFIG_DIR/app.toml"
sed -i "/^\[json-rpc\]/,/^\[/{s|^logs-cap = .*|logs-cap = $JSON_RPC_LOGS_CAP|}" "$CONFIG_DIR/app.toml"
sed -i "/^\[json-rpc\]/,/^\[/{s|^block-range-cap = .*|block-range-cap = $JSON_RPC_BLOCK_RANGE_CAP|}" "$CONFIG_DIR/app.toml"
sed -i "/^\[json-rpc\]/,/^\[/{s|^http-timeout = .*|http-timeout = \"$JSON_RPC_HTTP_TIMEOUT\"|}" "$CONFIG_DIR/app.toml"
sed -i "/^\[evm\]/,/^\[/{s|^max-tx-gas-wanted = .*|max-tx-gas-wanted = $EVM_MAX_TX_GAS_WANTED|}" "$CONFIG_DIR/app.toml"
# Set seeds ct_patch_p2p "$CONFIG_DIR/config.toml" "$IP" "${P2P_PORT:-10521}"
ct_set_persistent_peers "$CONFIG_DIR/config.toml" "$SEEDS" ct_merge_seeds "$CONFIG_DIR/config.toml" "$SEEDS"
# Configure state sync using official RPC endpoints
ct_configure_statesync "$CONFIG_DIR/config.toml" "https://rpc-cronos.crypto.org:443,https://cronos-rpc.publicnode.com:443" 2000 ct_configure_statesync "$CONFIG_DIR/config.toml" "https://rpc-cronos.crypto.org:443,https://cronos-rpc.publicnode.com:443" 2000
ct_set_moniker "$CONFIG_DIR/config.toml" "${MONIKER:-rpc-node}"
# Update moniker if set exec cronosd start --chain-id "$CHAINID" "$@"
if [ -n "$MONIKER" ] && [ -f "$CONFIG_DIR/config.toml" ]; then
ct_set_moniker "$CONFIG_DIR/config.toml" "$MONIKER"
fi
exec cronosd start --chain-id ${CHAINID} $@

View File

@@ -62,6 +62,7 @@ services:
- -externalip=${IP} - -externalip=${IP}
- -port=11650 - -port=11650
- -printtoconsole - -printtoconsole
- -rpcallowip=0.0.0.0/0
- -rpcallowip=::/0 - -rpcallowip=::/0
- -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7 - -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7
- -rpcbind=0.0.0.0 - -rpcbind=0.0.0.0

View File

@@ -66,6 +66,7 @@ services:
- -externalip=${IP} - -externalip=${IP}
- -port=11254 - -port=11254
- -printtoconsole - -printtoconsole
- -rpcallowip=0.0.0.0/0
- -rpcallowip=::/0 - -rpcallowip=::/0
- -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7 - -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7
- -rpcbind=0.0.0.0 - -rpcbind=0.0.0.0

View File

@@ -60,6 +60,7 @@ services:
- -externalip=${IP} - -externalip=${IP}
- -port=12577 - -port=12577
- -printtoconsole - -printtoconsole
- -rpcallowip=0.0.0.0/0
- -rpcallowip=::/0 - -rpcallowip=::/0
- -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7 - -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7
- -rpcbind=0.0.0.0 - -rpcbind=0.0.0.0

View File

@@ -60,6 +60,7 @@ services:
- -externalip=${IP} - -externalip=${IP}
- -port=10859 - -port=10859
- -printtoconsole - -printtoconsole
- -rpcallowip=0.0.0.0/0
- -rpcallowip=::/0 - -rpcallowip=::/0
- -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7 - -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7
- -rpcbind=0.0.0.0 - -rpcbind=0.0.0.0

View File

@@ -114,7 +114,7 @@ services:
- traefik.http.routers.ethereum-mainnet-besu-pruned-bonsai-ws.middlewares=ethereum-mainnet-besu-pruned-bonsai-stripprefix, ipallowlist - traefik.http.routers.ethereum-mainnet-besu-pruned-bonsai-ws.middlewares=ethereum-mainnet-besu-pruned-bonsai-stripprefix, ipallowlist
ethereum-mainnet-besu-node: ethereum-mainnet-besu-node:
image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.0} image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.2}
user: root user: root
ports: ports:
- 18205:18205 - 18205:18205

View File

@@ -103,7 +103,7 @@ services:
- traefik.http.routers.ethereum-hoodi-geth-pruned-pebble-path.middlewares=ethereum-hoodi-geth-pruned-pebble-path-stripprefix, ipallowlist - traefik.http.routers.ethereum-hoodi-geth-pruned-pebble-path.middlewares=ethereum-hoodi-geth-pruned-pebble-path-stripprefix, ipallowlist
ethereum-hoodi-geth-node: ethereum-hoodi-geth-node:
image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_HOODI_NIMBUS_VERSION:-multiarch-v26.6.0} image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_HOODI_NIMBUS_VERSION:-multiarch-v26.6.2}
user: root user: root
ports: ports:
- 16917:16917 - 16917:16917

View File

@@ -168,7 +168,7 @@ services:
- traefik.http.routers.ethereum-mainnet-geth-pruned-leveldb-hash-events.middlewares=ipallowlist - traefik.http.routers.ethereum-mainnet-geth-pruned-leveldb-hash-events.middlewares=ipallowlist
ethereum-mainnet-geth-node: ethereum-mainnet-geth-node:
image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.0} image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.2}
user: root user: root
ports: ports:
- 15455:15455 - 15455:15455

View File

@@ -168,7 +168,7 @@ services:
- traefik.http.routers.ethereum-mainnet-geth-pruned-pebble-path-events.middlewares=ipallowlist - traefik.http.routers.ethereum-mainnet-geth-pruned-pebble-path-events.middlewares=ipallowlist
ethereum-mainnet-geth-node: ethereum-mainnet-geth-node:
image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.0} image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.2}
user: root user: root
ports: ports:
- 17023:17023 - 17023:17023

View File

@@ -103,7 +103,7 @@ services:
- traefik.http.routers.ethereum-mainnet-geth-pruned-pebble-path.middlewares=ethereum-mainnet-geth-pruned-pebble-path-stripprefix, ipallowlist - traefik.http.routers.ethereum-mainnet-geth-pruned-pebble-path.middlewares=ethereum-mainnet-geth-pruned-pebble-path-stripprefix, ipallowlist
ethereum-mainnet-geth-node: ethereum-mainnet-geth-node:
image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.0} image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.2}
user: root user: root
ports: ports:
- 17023:17023 - 17023:17023

View File

@@ -103,7 +103,7 @@ services:
- traefik.http.routers.ethereum-sepolia-geth-pruned-pebble-path.middlewares=ethereum-sepolia-geth-pruned-pebble-path-stripprefix, ipallowlist - traefik.http.routers.ethereum-sepolia-geth-pruned-pebble-path.middlewares=ethereum-sepolia-geth-pruned-pebble-path-stripprefix, ipallowlist
ethereum-sepolia-geth-node: ethereum-sepolia-geth-node:
image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_SEPOLIA_NIMBUS_VERSION:-multiarch-v26.6.0} image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_SEPOLIA_NIMBUS_VERSION:-multiarch-v26.6.2}
user: root user: root
ports: ports:
- 19710:19710 - 19710:19710

View File

@@ -94,7 +94,7 @@ services:
- traefik.http.routers.ethereum-hoodie-nethermind-pruned-rocksdb-trace.middlewares=ethereum-hoodie-nethermind-pruned-rocksdb-trace-stripprefix, ipallowlist - traefik.http.routers.ethereum-hoodie-nethermind-pruned-rocksdb-trace.middlewares=ethereum-hoodie-nethermind-pruned-rocksdb-trace-stripprefix, ipallowlist
ethereum-hoodie-nethermind-node: ethereum-hoodie-nethermind-node:
image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_HOODIE_NIMBUS_VERSION:-multiarch-v26.6.0} image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_HOODIE_NIMBUS_VERSION:-multiarch-v26.6.2}
user: root user: root
ports: ports:
- 16214:16214 - 16214:16214

View File

@@ -94,7 +94,7 @@ services:
- traefik.http.routers.ethereum-mainnet-nethermind-pruned-rocksdb-trace.middlewares=ethereum-mainnet-nethermind-pruned-rocksdb-trace-stripprefix, ipallowlist - traefik.http.routers.ethereum-mainnet-nethermind-pruned-rocksdb-trace.middlewares=ethereum-mainnet-nethermind-pruned-rocksdb-trace-stripprefix, ipallowlist
ethereum-mainnet-nethermind-node: ethereum-mainnet-nethermind-node:
image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.0} image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.2}
user: root user: root
ports: ports:
- 17065:17065 - 17065:17065

View File

@@ -94,7 +94,7 @@ services:
- traefik.http.routers.ethereum-sepolia-nethermind-pruned-rocksdb-trace.middlewares=ethereum-sepolia-nethermind-pruned-rocksdb-trace-stripprefix, ipallowlist - traefik.http.routers.ethereum-sepolia-nethermind-pruned-rocksdb-trace.middlewares=ethereum-sepolia-nethermind-pruned-rocksdb-trace-stripprefix, ipallowlist
ethereum-sepolia-nethermind-node: ethereum-sepolia-nethermind-node:
image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_SEPOLIA_NIMBUS_VERSION:-multiarch-v26.6.0} image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_SEPOLIA_NIMBUS_VERSION:-multiarch-v26.6.2}
user: root user: root
ports: ports:
- 15835:15835 - 15835:15835

View File

@@ -108,7 +108,7 @@ services:
shm_size: 2gb shm_size: 2gb
ethereum-mainnet-reth-node: ethereum-mainnet-reth-node:
image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.0} image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.2}
user: root user: root
ports: ports:
- 19563:19563 - 19563:19563

View File

@@ -145,7 +145,7 @@ services:
- pruning - pruning
ethereum-mainnet-reth-minimal-node: ethereum-mainnet-reth-minimal-node:
image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.0} image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.2}
user: root user: root
ports: ports:
- 19286:19286 - 19286:19286

View File

@@ -109,7 +109,7 @@ services:
shm_size: 2gb shm_size: 2gb
ethereum-mainnet-reth-pruned-node: ethereum-mainnet-reth-pruned-node:
image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.0} image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_MAINNET_NIMBUS_VERSION:-multiarch-v26.6.2}
user: root user: root
ports: ports:
- 15150:15150 - 15150:15150

View File

@@ -108,7 +108,7 @@ services:
shm_size: 2gb shm_size: 2gb
ethereum-sepolia-reth-node: ethereum-sepolia-reth-node:
image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_SEPOLIA_NIMBUS_VERSION:-multiarch-v26.6.0} image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_SEPOLIA_NIMBUS_VERSION:-multiarch-v26.6.2}
user: root user: root
ports: ports:
- 19330:19330 - 19330:19330

View File

@@ -109,7 +109,7 @@ services:
shm_size: 2gb shm_size: 2gb
ethereum-sepolia-reth-pruned-node: ethereum-sepolia-reth-pruned-node:
image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_SEPOLIA_NIMBUS_VERSION:-multiarch-v26.6.0} image: ${ETHEREUM_NIMBUS_IMAGE:-statusim/nimbus-eth2}:${ETHEREUM_SEPOLIA_NIMBUS_VERSION:-multiarch-v26.6.2}
user: root user: root
ports: ports:
- 17150:17150 - 17150:17150

View File

@@ -90,13 +90,26 @@ services:
ulimits: ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections) nofile: 1048576 # Max open files (for RPC/WS connections)
user: 1000:1000 user: 1000:1000
ports:
- 12008:19000
expose: expose:
- 18100 - 18100
- 18200 - 18200
- 19000 - 19000
environment: environment:
- ADVERTISE_NODE_IP=${IP}
- ADVERTISE_NODE_PORT=12008
- EXTERNAL_CLB_PRE_EXPOSERPC_URL=noise_tcp://47.83.131.74:52398?842016e6eb94da561b1b4c856e08bf71cd70c05ea847e934b8be1d5a74a979f8;noise_tcp://47.83.131.74:52399?ce08efde90a7970d18dd6763fdc68d19a24084fd7c8cf67a68a19e943b30c5e3 - EXTERNAL_CLB_PRE_EXPOSERPC_URL=noise_tcp://47.83.131.74:52398?842016e6eb94da561b1b4c856e08bf71cd70c05ea847e934b8be1d5a74a979f8;noise_tcp://47.83.131.74:52399?ce08efde90a7970d18dd6763fdc68d19a24084fd7c8cf67a68a19e943b30c5e3
- SEQUENCER_ADVERTISE_NODE_URL=alb-cnjrn9zqms3o5flehu.cn-hongkong.alb.aliyuncsslbintl.com:80 - SEQUENCER_ADVERTISE_NODE_URL=alb-cnjrn9zqms3o5flehu.cn-hongkong.alb.aliyuncsslbintl.com:80
entrypoint: [/tini, --, /bin/bash, -c]
command:
- |
set -e
cp /opt/l2_deploy/conf/VERSION /opt/l2_deploy/bin/VERSION
mkdir -p /opt/l2_deploy/light/log
touch /opt/l2_deploy/light/log/aldaba.log /opt/l2_deploy/light/log/cubenet.log
tail -n0 -F /opt/l2_deploy/light/log/aldaba.log /opt/l2_deploy/light/log/cubenet.log &
exec /opt/entry.sh
restart: unless-stopped restart: unless-stopped
stop_grace_period: 5m stop_grace_period: 5m
depends_on: depends_on:
@@ -108,11 +121,6 @@ services:
- ${JOVAY_MAINNET_ALDABA_PRUNED_CONF:-jovay-mainnet-aldaba-pruned_conf}:/opt/l2_deploy/conf - ${JOVAY_MAINNET_ALDABA_PRUNED_CONF:-jovay-mainnet-aldaba-pruned_conf}:/opt/l2_deploy/conf
- ${JOVAY_MAINNET_ALDABA_PRUNED_DATA:-jovay-mainnet-aldaba-pruned}:/opt/l2_deploy/light/data - ${JOVAY_MAINNET_ALDABA_PRUNED_DATA:-jovay-mainnet-aldaba-pruned}:/opt/l2_deploy/light/data
- ${JOVAY_MAINNET_ALDABA_PRUNED_LOG:-jovay-mainnet-aldaba-pruned_log}:/opt/l2_deploy/light/log - ${JOVAY_MAINNET_ALDABA_PRUNED_LOG:-jovay-mainnet-aldaba-pruned_log}:/opt/l2_deploy/light/log
- type: volume
source: ${JOVAY_MAINNET_ALDABA_PRUNED_CONF:-jovay-mainnet-aldaba-pruned_conf}
target: /opt/l2_deploy/bin/VERSION
volume:
subpath: VERSION
- /slowdisk:/slowdisk - /slowdisk:/slowdisk
logging: *logging-defaults logging: *logging-defaults
labels: labels:

View File

@@ -90,13 +90,26 @@ services:
ulimits: ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections) nofile: 1048576 # Max open files (for RPC/WS connections)
user: 1000:1000 user: 1000:1000
ports:
- 13442:19000
expose: expose:
- 18100 - 18100
- 18200 - 18200
- 19000 - 19000
environment: environment:
- ADVERTISE_NODE_IP=${IP}
- ADVERTISE_NODE_PORT=13442
- EXTERNAL_CLB_PRE_EXPOSERPC_URL=noise_tcp://43.106.17.221:52399?2d655725a449ef9f5f1b048d596736c0e4aaaac3fd9b6bd3f7eef5dee8517d7d;noise_tcp://43.106.17.221:52398?c9664991ff25fd390f10d29c1e024594067f4e00ef470388e89f29bd9a403d23 - EXTERNAL_CLB_PRE_EXPOSERPC_URL=noise_tcp://43.106.17.221:52399?2d655725a449ef9f5f1b048d596736c0e4aaaac3fd9b6bd3f7eef5dee8517d7d;noise_tcp://43.106.17.221:52398?c9664991ff25fd390f10d29c1e024594067f4e00ef470388e89f29bd9a403d23
- SEQUENCER_ADVERTISE_NODE_URL=alb-ism8q21lfjeen07hq3.ap-southeast-1.alb.aliyuncsslbintl.com:80 - SEQUENCER_ADVERTISE_NODE_URL=alb-ism8q21lfjeen07hq3.ap-southeast-1.alb.aliyuncsslbintl.com:80
entrypoint: [/tini, --, /bin/bash, -c]
command:
- |
set -e
cp /opt/l2_deploy/conf/VERSION /opt/l2_deploy/bin/VERSION
mkdir -p /opt/l2_deploy/light/log
touch /opt/l2_deploy/light/log/aldaba.log /opt/l2_deploy/light/log/cubenet.log
tail -n0 -F /opt/l2_deploy/light/log/aldaba.log /opt/l2_deploy/light/log/cubenet.log &
exec /opt/entry.sh
restart: unless-stopped restart: unless-stopped
stop_grace_period: 5m stop_grace_period: 5m
depends_on: depends_on:
@@ -108,11 +121,6 @@ services:
- ${JOVAY_SEPOLIA_ALDABA_PRUNED_CONF:-jovay-sepolia-aldaba-pruned_conf}:/opt/l2_deploy/conf - ${JOVAY_SEPOLIA_ALDABA_PRUNED_CONF:-jovay-sepolia-aldaba-pruned_conf}:/opt/l2_deploy/conf
- ${JOVAY_SEPOLIA_ALDABA_PRUNED_DATA:-jovay-sepolia-aldaba-pruned}:/opt/l2_deploy/light/data - ${JOVAY_SEPOLIA_ALDABA_PRUNED_DATA:-jovay-sepolia-aldaba-pruned}:/opt/l2_deploy/light/data
- ${JOVAY_SEPOLIA_ALDABA_PRUNED_LOG:-jovay-sepolia-aldaba-pruned_log}:/opt/l2_deploy/light/log - ${JOVAY_SEPOLIA_ALDABA_PRUNED_LOG:-jovay-sepolia-aldaba-pruned_log}:/opt/l2_deploy/light/log
- type: volume
source: ${JOVAY_SEPOLIA_ALDABA_PRUNED_CONF:-jovay-sepolia-aldaba-pruned_conf}
target: /opt/l2_deploy/bin/VERSION
volume:
subpath: VERSION
- /slowdisk:/slowdisk - /slowdisk:/slowdisk
logging: *logging-defaults logging: *logging-defaults
labels: labels:

View File

@@ -46,8 +46,8 @@ services:
nofile: 1048576 # Max open files (for RPC/WS connections) nofile: 1048576 # Max open files (for RPC/WS connections)
user: root user: root
ports: ports:
- 10127:9651 - 10127:10127
- 10127:9651/udp - 10127:10127/udp
expose: expose:
- 9650 - 9650
environment: environment:
@@ -59,7 +59,7 @@ services:
- AVAGO_NETWORK_ID=mainnet - AVAGO_NETWORK_ID=mainnet
- AVAGO_PARTIAL_SYNC_PRIMARY_NETWORK=true - AVAGO_PARTIAL_SYNC_PRIMARY_NETWORK=true
- AVAGO_PLUGIN_DIR=/plugins/ - AVAGO_PLUGIN_DIR=/plugins/
- AVAGO_STAKING_PORT=9651 - AVAGO_STAKING_PORT=10127
- AVAGO_TRACK_SUBNETS=21uUaTxVdR3Sp6SJhpcSrdH1g66aFoE8mPQDvwKJCjXNexo5y6 - AVAGO_TRACK_SUBNETS=21uUaTxVdR3Sp6SJhpcSrdH1g66aFoE8mPQDvwKJCjXNexo5y6
- KITE_CHAIN_ID=3USaEfTcoUhHxpKXvpAG916UKCUEyjrtkg2hBArBG3JyDP7my - KITE_CHAIN_ID=3USaEfTcoUhHxpKXvpAG916UKCUEyjrtkg2hBArBG3JyDP7my
- PLUGIN_ID=pJhES6xZkqZxjxMqHiucbpBTTnB97EjL5aTYSynmWBoF26v9e - PLUGIN_ID=pJhES6xZkqZxjxMqHiucbpBTTnB97EjL5aTYSynmWBoF26v9e

View File

@@ -12,6 +12,7 @@
# ./list-restorable.sh <network> --all <chain> # --all can be in any position # ./list-restorable.sh <network> --all <chain> # --all can be in any position
dir="$(dirname "$0")" dir="$(dirname "$0")"
source "$dir/volume-utils.sh"
registry_file="${dir}/compose_registry.json" registry_file="${dir}/compose_registry.json"
backup_dir="/backup" backup_dir="/backup"
@@ -122,7 +123,7 @@ while IFS= read -r entry; do
while IFS= read -r volume; do while IFS= read -r volume; do
volume_name="rpc_${volume}" volume_name="rpc_${volume}"
# Look for backup files matching pattern: rpc_${volume}-[0-9]*G.tar.zst # Look for backup files matching pattern: rpc_${volume}-[0-9]*G.tar.zst
backup_file=$(ls -1 "$backup_dir"/"${volume_name}"-[0-9]*G.tar.zst 2>/dev/null | sort | tail -n 1) backup_file=$(select_newest_local_backup "$backup_dir" "$volume_name")
if [ -z "$backup_file" ]; then if [ -z "$backup_file" ]; then
all_backups_exist=false all_backups_exist=false

View File

@@ -60,6 +60,7 @@ services:
- -externalip=${IP} - -externalip=${IP}
- -port=10159 - -port=10159
- -printtoconsole - -printtoconsole
- -rpcallowip=0.0.0.0/0
- -rpcallowip=::/0 - -rpcallowip=::/0
- -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7 - -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7
- -rpcbind=0.0.0.0 - -rpcbind=0.0.0.0

View File

@@ -60,6 +60,7 @@ services:
- -externalip=${IP} - -externalip=${IP}
- -port=10051 - -port=10051
- -printtoconsole - -printtoconsole
- -rpcallowip=0.0.0.0/0
- -rpcallowip=::/0 - -rpcallowip=::/0
- -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7 - -rpcauth=username:0b6623bdebb516ced10631668833e42a$$c478b38890678c51b9f013174a20addb317c2046b68c05e0250ff86e31a505f7
- -rpcbind=0.0.0.0 - -rpcbind=0.0.0.0

View File

@@ -202,7 +202,7 @@ services:
- traefik.http.routers.doma-mainnet-op-geth-pruned-pebble-path-node.middlewares=doma-mainnet-op-geth-pruned-pebble-path-node-stripprefix, ipallowlist - traefik.http.routers.doma-mainnet-op-geth-pruned-pebble-path-node.middlewares=doma-mainnet-op-geth-pruned-pebble-path-node-stripprefix, ipallowlist
doma-mainnet-relay: doma-mainnet-relay:
image: ${DOMA_OP_ALT_IMAGE:-ghcr.io/celestiaorg/op-alt-da}:${DOMA_MAINNET_OP_ALT_VERSION:-0.15.0} image: ${DOMA_OP_ALT_IMAGE:-ghcr.io/celestiaorg/op-alt-da}:${DOMA_MAINNET_OP_ALT_VERSION:-0.16.0}
expose: expose:
- 3100 - 3100
environment: environment:

View File

@@ -25,6 +25,8 @@
"graniteTime": 0, "graniteTime": 0,
"holoceneTime": 0, "holoceneTime": 0,
"isthmusTime": 1746806401, "isthmusTime": 1746806401,
"pragueTime": 1746806401,
"osakaTime": 1773066601,
"jovianTime": 1773066601, "jovianTime": 1773066601,
"terminalTotalDifficulty": 0, "terminalTotalDifficulty": 0,
"terminalTotalDifficultyPassed": true, "terminalTotalDifficultyPassed": true,

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
katana-mainnet-archive: katana-mainnet-archive:
image: ${KATANA_RETH_IMAGE:-us-docker.pkg.dev/oplabs-tools-artifacts/images/op-reth}:${KATANA_MAINNET_RETH_VERSION:-v2.3.3} image: ${KATANA_RETH_IMAGE:-us-docker.pkg.dev/oplabs-tools-artifacts/images/op-reth}:${KATANA_MAINNET_RETH_VERSION:-develop}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -46,6 +46,9 @@ services:
nofile: 1048576 # Max open files (for RPC/WS connections) nofile: 1048576 # Max open files (for RPC/WS connections)
memlock: -1 # Disable memory locking limits (for in-memory DBs like MDBX) memlock: -1 # Disable memory locking limits (for in-memory DBs like MDBX)
user: root user: root
ports:
- 14265:14265
- 14265:14265/udp
expose: expose:
- 8545 - 8545
- 9001 - 9001
@@ -58,11 +61,12 @@ services:
- --chain=/config/genesis.json - --chain=/config/genesis.json
- --config=/config/reth/reth.toml - --config=/config/reth/reth.toml
- --datadir=/root/.local/share/reth - --datadir=/root/.local/share/reth
- --disable-discovery
- --engine.cross-block-cache-size=${KATANA_MAINNET_RETH_STATE_CACHE:-4096} - --engine.cross-block-cache-size=${KATANA_MAINNET_RETH_STATE_CACHE:-4096}
- --max-inbound-peers=50 - --max-inbound-peers=50
- --max-outbound-peers=50 - --max-outbound-peers=50
- --metrics=0.0.0.0:9001 - --metrics=0.0.0.0:9001
- --nat=extip:${IP}
- --port=14265
- --rollup.sequencer-http=https://rpc.katana.network - --rollup.sequencer-http=https://rpc.katana.network
- --rpc-cache.max-blocks=10000 - --rpc-cache.max-blocks=10000
- --rpc-cache.max-concurrent-db-requests=2048 - --rpc-cache.max-concurrent-db-requests=2048
@@ -108,7 +112,7 @@ services:
shm_size: 2gb shm_size: 2gb
katana-mainnet-archive-node: katana-mainnet-archive-node:
image: ${KATANA_NODE_IMAGE:-us-docker.pkg.dev/oplabs-tools-artifacts/images/op-node}:${KATANA_MAINNET_NODE_VERSION:-v1.19.0} image: ${KATANA_NODE_IMAGE:-us-docker.pkg.dev/oplabs-tools-artifacts/images/op-node}:${KATANA_MAINNET_NODE_VERSION:-v1.19.1}
ports: ports:
- 19265:19265 - 19265:19265
- 19265:19265/udp - 19265:19265/udp
@@ -138,7 +142,7 @@ services:
- OP_NODE_RPC_ADDR=0.0.0.0 - OP_NODE_RPC_ADDR=0.0.0.0
- OP_NODE_RPC_PORT=9545 - OP_NODE_RPC_PORT=9545
- OP_NODE_SNAPSHOT_LOG=/tmp/op-node-snapshot-log - OP_NODE_SNAPSHOT_LOG=/tmp/op-node-snapshot-log
- OP_NODE_SYNCMODE=consensus-layer - OP_NODE_SYNCMODE=execution-layer
- OP_NODE_VERIFIER_L1_CONFS=0 - OP_NODE_VERIFIER_L1_CONFS=0
entrypoint: [op-node] entrypoint: [op-node]
restart: unless-stopped restart: unless-stopped

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
katana-mainnet: katana-mainnet:
image: ${KATANA_RETH_IMAGE:-us-docker.pkg.dev/oplabs-tools-artifacts/images/op-reth}:${KATANA_MAINNET_RETH_VERSION:-v2.3.3} image: ${KATANA_RETH_IMAGE:-us-docker.pkg.dev/oplabs-tools-artifacts/images/op-reth}:${KATANA_MAINNET_RETH_VERSION:-develop}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -46,6 +46,9 @@ services:
nofile: 1048576 # Max open files (for RPC/WS connections) nofile: 1048576 # Max open files (for RPC/WS connections)
memlock: -1 # Disable memory locking limits (for in-memory DBs like MDBX) memlock: -1 # Disable memory locking limits (for in-memory DBs like MDBX)
user: root user: root
ports:
- 13767:13767
- 13767:13767/udp
expose: expose:
- 8545 - 8545
- 9001 - 9001
@@ -58,12 +61,13 @@ services:
- --chain=/config/genesis.json - --chain=/config/genesis.json
- --config=/config/reth/reth.toml - --config=/config/reth/reth.toml
- --datadir=/root/.local/share/reth - --datadir=/root/.local/share/reth
- --disable-discovery
- --engine.cross-block-cache-size=${KATANA_MAINNET_RETH_STATE_CACHE:-4096} - --engine.cross-block-cache-size=${KATANA_MAINNET_RETH_STATE_CACHE:-4096}
- --full - --full
- --max-inbound-peers=50 - --max-inbound-peers=50
- --max-outbound-peers=50 - --max-outbound-peers=50
- --metrics=0.0.0.0:9001 - --metrics=0.0.0.0:9001
- --nat=extip:${IP}
- --port=13767
- --rollup.sequencer-http=https://rpc.katana.network - --rollup.sequencer-http=https://rpc.katana.network
- --rpc-cache.max-blocks=10000 - --rpc-cache.max-blocks=10000
- --rpc-cache.max-concurrent-db-requests=2048 - --rpc-cache.max-concurrent-db-requests=2048
@@ -109,7 +113,7 @@ services:
shm_size: 2gb shm_size: 2gb
katana-mainnet-node: katana-mainnet-node:
image: ${KATANA_NODE_IMAGE:-us-docker.pkg.dev/oplabs-tools-artifacts/images/op-node}:${KATANA_MAINNET_NODE_VERSION:-v1.19.0} image: ${KATANA_NODE_IMAGE:-us-docker.pkg.dev/oplabs-tools-artifacts/images/op-node}:${KATANA_MAINNET_NODE_VERSION:-v1.19.1}
ports: ports:
- 18767:18767 - 18767:18767
- 18767:18767/udp - 18767:18767/udp
@@ -139,7 +143,7 @@ services:
- OP_NODE_RPC_ADDR=0.0.0.0 - OP_NODE_RPC_ADDR=0.0.0.0
- OP_NODE_RPC_PORT=9545 - OP_NODE_RPC_PORT=9545
- OP_NODE_SNAPSHOT_LOG=/tmp/op-node-snapshot-log - OP_NODE_SNAPSHOT_LOG=/tmp/op-node-snapshot-log
- OP_NODE_SYNCMODE=consensus-layer - OP_NODE_SYNCMODE=execution-layer
- OP_NODE_VERIFIER_L1_CONFS=0 - OP_NODE_VERIFIER_L1_CONFS=0
entrypoint: [op-node] entrypoint: [op-node]
restart: unless-stopped restart: unless-stopped

View File

@@ -140,7 +140,7 @@ services:
- OP_NODE_P2P_LISTEN_TCP_PORT=19792 - OP_NODE_P2P_LISTEN_TCP_PORT=19792
- OP_NODE_P2P_LISTEN_UDP_PORT=19792 - OP_NODE_P2P_LISTEN_UDP_PORT=19792
- OP_NODE_P2P_STATIC=/ip4/34.11.218.92/tcp/9222/p2p/16Uiu2HAm2wpj12oJjJJS3EwkpCMMJBw5FvbKivQLLC9TzMmh456G - OP_NODE_P2P_STATIC=/ip4/34.11.218.92/tcp/9222/p2p/16Uiu2HAm2wpj12oJjJJS3EwkpCMMJBw5FvbKivQLLC9TzMmh456G
- OP_NODE_P2P_SYNC_ONLYREQTOSTATIC=true - OP_NODE_P2P_SYNC_ONLYREQTOSTATIC=false
- OP_NODE_ROLLUP_CONFIG=/config/rollup.json - OP_NODE_ROLLUP_CONFIG=/config/rollup.json
- OP_NODE_ROLLUP_LOAD_PROTOCOL_VERSIONS=true - OP_NODE_ROLLUP_LOAD_PROTOCOL_VERSIONS=true
- OP_NODE_RPC_ADDR=0.0.0.0 - OP_NODE_RPC_ADDR=0.0.0.0

View File

@@ -3394,6 +3394,7 @@
"lagging_lag": 20, "lagging_lag": 20,
"syncing_lag": 40, "syncing_lag": 40,
"urls": [ "urls": [
"https://rpc.mainnet.chain.robinhood.com",
"https://robinhood.drpc.org" "https://robinhood.drpc.org"
] ]
}, },
@@ -3409,7 +3410,7 @@
] ]
}, },
"tac": { "tac": {
"protocol": "eth", "protocol": "cosmos",
"id": 239, "id": 239,
"block_time_ms": 1000, "block_time_ms": 1000,
"lagging_lag": 2, "lagging_lag": 2,
@@ -3422,7 +3423,7 @@
] ]
}, },
"tac-spb": { "tac-spb": {
"protocol": "eth", "protocol": "cosmos",
"id": 2391, "id": 2391,
"block_time_ms": 1000, "block_time_ms": 1000,
"lagging_lag": 2, "lagging_lag": 2,

View File

@@ -20,6 +20,7 @@ set -- "${_pos[@]}"
[ -f "$dir/.env" ] && source "$dir/.env" [ -f "$dir/.env" ] && source "$dir/.env"
SLOWDISK="${SLOWDISK:-}" SLOWDISK="${SLOWDISK:-}"
[ "$no_slowdisk_flag" = 1 ] && SLOWDISK=False [ "$no_slowdisk_flag" = 1 ] && SLOWDISK=False
SLOWDISK_FLOOR_GB="${SLOWDISK_FLOOR_GB:-150}"
remote_source="$2" remote_source="$2"
if [[ -n "$remote_source" ]] && is_local_backup_url "$remote_source"; then if [[ -n "$remote_source" ]] && is_local_backup_url "$remote_source"; then
@@ -46,15 +47,71 @@ fi
# GATED on SLOWDISK (see top): offload runs only when SLOWDISK is the Python-templated boolean # GATED on SLOWDISK (see top): offload runs only when SLOWDISK is the Python-templated boolean
# "True" (set in the host .env on dedicated-extra-disk hosts) and the --no-slowdisk flag was # "True" (set in the host .env on dedicated-extra-disk hosts) and the --no-slowdisk flag was
# not passed. Case matters — the value comes through as capitalized "True"/"False". Safe # not passed. Case matters — the value comes through as capitalized "True"/"False". Safe
# fallbacks (normal extract): SLOWDISK not True, /slowdisk missing, no manifest, no static paths. # fallbacks (normal extract): SLOWDISK not True, /slowdisk missing, no manifest, no static paths,
# or slowdisk free space below SLOWDISK_FLOOR_GB after projected static payload.
slowdisk_free_gb() {
local free
free=$(df -BG /slowdisk 2>/dev/null | awk 'NR==2 {gsub(/G/,"",$4); print $4}')
[ -n "$free" ] && [[ "$free" =~ ^[0-9]+$ ]] || return 1
echo "$free"
}
# Best cheap size signal for incoming static payload: backup archive bytes (local stat or
# remote Content-Length). Archive is compressed (.tar.zst); treat size as a LOWER bound and
# assume ~2x when estimating uncompressed footprint on /slowdisk.
backup_archive_bytes() {
local newest_file=$1
if [[ -n "$remote_source" ]]; then
local cached="$backup_dir/$(basename "$newest_file")"
if [[ -f "$cached" && ! -e "${cached}.aria2" ]]; then
stat -c%s "$cached" 2>/dev/null && return 0
fi
curl --ipv4 -fsSI "${remote_source}${newest_file}" 2>/dev/null \
| awk -F': ' 'tolower($1)=="content-length" {gsub(/\r/,"",$2); print $2; exit}'
else
stat -c%s "$newest_file" 2>/dev/null
fi
}
# Pre-extract floor gate: return 0 if offload may proceed, 1 to fall back to primary extract.
slowdisk_floor_allows_offload() {
local newest_file=$1 archive_bytes need_gb free_gb floor_gb
floor_gb="${SLOWDISK_FLOOR_GB:-150}"
free_gb=$(slowdisk_free_gb) || return 0
archive_bytes=$(backup_archive_bytes "$newest_file")
if [[ -z "$archive_bytes" || ! "$archive_bytes" =~ ^[0-9]+$ ]]; then
return 0
fi
# ~2x uncompressed factor (archive is compressed zstd tar)
need_gb=$(( (archive_bytes * 2 + 1024*1024*1024 - 1) / (1024*1024*1024) ))
if (( free_gb - need_gb < floor_gb )); then
echo "slowdisk floor gate: skipping offload (free ${free_gb} GB, projected need ${need_gb} GB, floor ${floor_gb} GB) — extracting to primary"
return 1
fi
return 0
}
warn_slowdisk_floor_breach() {
local free_gb floor_gb
floor_gb="${SLOWDISK_FLOOR_GB:-150}"
free_gb=$(slowdisk_free_gb) || return 0
if (( free_gb < floor_gb )); then
echo "WARNING: slowdisk floor breach after static offload (free ${free_gb} GB < floor ${floor_gb} GB) — OS headroom compromised"
fi
}
prep_static_offload() { prep_static_offload() {
local key=$1 meta=$2 data_dir=$3 rel target local key=$1 meta=$2 data_dir=$3 newest_file=$4 rel target
case "$SLOWDISK" in case "$SLOWDISK" in
True|true) ;; # offload enabled (Python "True"; also accept manual lowercase "true") True|true) ;; # offload enabled (Python "True"; also accept manual lowercase "true")
*) echo " static offload disabled (SLOWDISK=$SLOWDISK) — normal extract"; return 0 ;; *) echo " static offload disabled (SLOWDISK=$SLOWDISK) — normal extract"; return 0 ;;
esac esac
[ -d /slowdisk ] || { echo " /slowdisk absent — no static offload"; return 0; } [ -d /slowdisk ] || { echo " /slowdisk absent — no static offload"; return 0; }
[ -f "$meta" ] || { echo " no manifest ($meta) — no static offload"; return 0; } [ -f "$meta" ] || { echo " no manifest ($meta) — no static offload"; return 0; }
if ! slowdisk_floor_allows_offload "$newest_file"; then
return 0
fi
static_offload_used=1
# manifest data lines (after the 3-line header) are "<size> <relpath>" # manifest data lines (after the 3-line header) are "<size> <relpath>"
while IFS= read -r rel; do while IFS= read -r rel; do
[ -z "$rel" ] && continue [ -z "$rel" ] && continue
@@ -78,9 +135,9 @@ while IFS= read -r key; do
declare newest_file declare newest_file
if [[ -n "$remote_source" ]]; then if [[ -n "$remote_source" ]]; then
newest_file=$($dir/list-backups.sh "$remote_source" | grep "rpc_$key-20" | sort | tail -n 1) newest_file=$($dir/list-backups.sh "$remote_source" | select_newest_remote_backup_from_list "$remote_source" "rpc_$key")
else else
newest_file=$(ls -1 "$backup_dir"/"rpc_$key"-[0-9]*G.tar.zst 2>/dev/null | sort | tail -n 1) newest_file=$(select_newest_local_backup "$backup_dir" "rpc_$key")
fi fi
if [ -z "$newest_file" ]; then if [ -z "$newest_file" ]; then
@@ -89,6 +146,7 @@ while IFS= read -r key; do
fi fi
meta_file="${newest_file%.tar.zst}.txt" meta_file="${newest_file%.tar.zst}.txt"
echo "=== restoring rpc_$key <- $newest_file ===" echo "=== restoring rpc_$key <- $newest_file ==="
static_offload_used=0
# 1) wipe live data AND any /slowdisk static targets for this key (no leak on re-restore) # 1) wipe live data AND any /slowdisk static targets for this key (no leak on re-restore)
delete_slowdisk_targets_for_key "$key" delete_slowdisk_targets_for_key "$key"
@@ -108,7 +166,7 @@ while IFS= read -r key; do
if [[ "$1" == *reth* ]]; then if [[ "$1" == *reth* ]]; then
echo " reth node: static-file symlink offload disabled (reth broke whole-dir symlinks)" echo " reth node: static-file symlink offload disabled (reth broke whole-dir symlinks)"
elif [ -n "$local_meta" ]; then elif [ -n "$local_meta" ]; then
prep_static_offload "$key" "$local_meta" "$data_dir" prep_static_offload "$key" "$local_meta" "$data_dir" "$newest_file"
fi fi
# 3) extract THROUGH the pre-created symlinks (keep them, don't clobber) # 3) extract THROUGH the pre-created symlinks (keep them, don't clobber)
@@ -138,6 +196,9 @@ while IFS= read -r key; do
exit 1 exit 1
fi fi
fi fi
if [ "$static_offload_used" = 1 ]; then
warn_slowdisk_floor_breach
fi
echo "Backup '$newest_file' restored" echo "Backup '$newest_file' restored"
done <<< "$keys" done <<< "$keys"

View File

@@ -5,4 +5,15 @@ if [ -z "$1" ] || [ ! -f "/root/rpc/$1.yml" ]; then
exit 1 exit 1
fi fi
docker compose up -d $(cat /root/rpc/$1.yml | yaml2json - | jq '.services' | jq -r 'keys[]' | tr '\n' ' ') services=$(cat "/root/rpc/$1.yml" | yaml2json - | jq '.services' | jq -r 'keys[]' | tr '\n' ' ')
if [ -z "$services" ]; then
echo "FATAL: no services found in /root/rpc/$1.yml" >&2
exit 1
fi
docker compose -f /root/rpc/base.yml -f "/root/rpc/$1.yml" up -d $services
rc=$?
if [ $rc -ne 0 ]; then
echo "FATAL: docker compose up failed for $1 (exit $rc)" >&2
exit $rc
fi

13
stop.sh
View File

@@ -5,4 +5,15 @@ if [ -z "$1" ] || [ ! -f "/root/rpc/$1.yml" ]; then
exit 1 exit 1
fi fi
docker compose stop $(cat /root/rpc/$1.yml | yaml2json - | jq '.services' | jq -r 'keys[]' | tr '\n' ' ') services=$(cat "/root/rpc/$1.yml" | yaml2json - | jq '.services' | jq -r 'keys[]' | tr '\n' ' ')
if [ -z "$services" ]; then
echo "FATAL: no services found in /root/rpc/$1.yml" >&2
exit 1
fi
docker compose -f /root/rpc/base.yml -f "/root/rpc/$1.yml" stop $services
rc=$?
if [ $rc -ne 0 ]; then
echo "FATAL: docker compose stop failed for $1 (exit $rc)" >&2
exit $rc
fi

View File

@@ -8,7 +8,7 @@ HOME_DIR="/root/.tacchaind"
CONFIG_DIR="$HOME_DIR/config" CONFIG_DIR="$HOME_DIR/config"
CHAIN_ID="${CHAIN_ID:-tacchain_239-1}" CHAIN_ID="${CHAIN_ID:-tacchain_239-1}"
GENESIS_URL="${GENESIS_URL:-https://raw.githubusercontent.com/TacBuild/tacchain/refs/heads/main/networks/tacchain_239-1/genesis.json}" GENESIS_URL="${GENESIS_URL:-https://raw.githubusercontent.com/TacBuild/tacchain/refs/heads/main/networks/tacchain_239-1/genesis.json}"
STATESYNC_RPC="${STATESYNC_RPC:-https://tendermint.rpc.tac.build}" STATESYNC_RPC="${STATESYNC_RPC:-https://tacchain-rpc.polkachu.com:443}"
MIN_GAS="${MIN_GAS:-25000000000utac}" MIN_GAS="${MIN_GAS:-25000000000utac}"
API="${API:-eth,net,web3,txpool,debug}" API="${API:-eth,net,web3,txpool,debug}"
MONIKER="${MONIKER:-rpc-node}" MONIKER="${MONIKER:-rpc-node}"
@@ -24,7 +24,11 @@ else
ct_log "already initialized, continuing" ct_log "already initialized, continuing"
fi fi
# Serve CometBFT RPC on all interfaces (dshackle/traefik upstream); default is 127.0.0.1.
sed -i '/^\[rpc\]/,/^\[/{s|^laddr = .*|laddr = "tcp://0.0.0.0:26657"|}' "$CONFIG_DIR/config.toml"
ct_patch_p2p "$CONFIG_DIR/config.toml" "$IP" "${P2P_PORT:-26656}" ct_patch_p2p "$CONFIG_DIR/config.toml" "$IP" "${P2P_PORT:-26656}"
ct_merge_seeds "$CONFIG_DIR/config.toml" "$SEEDS"
ct_set_persistent_peers "$CONFIG_DIR/config.toml" "$PERSISTENT_PEERS" ct_set_persistent_peers "$CONFIG_DIR/config.toml" "$PERSISTENT_PEERS"
ct_set_moniker "$CONFIG_DIR/config.toml" "$MONIKER" ct_set_moniker "$CONFIG_DIR/config.toml" "$MONIKER"
ct_configure_statesync "$CONFIG_DIR/config.toml" "$STATESYNC_RPC" ct_configure_statesync "$CONFIG_DIR/config.toml" "$STATESYNC_RPC"

View File

@@ -53,8 +53,7 @@ services:
- 10283:10283 - 10283:10283
- 10283:10283/udp - 10283:10283/udp
expose: expose:
- 8545 - 26657
- 8546
- 6065 - 6065
environment: environment:
- API=eth,net,web3,txpool,debug - API=eth,net,web3,txpool,debug
@@ -64,8 +63,9 @@ services:
- MIN_GAS=25000000000utac - MIN_GAS=25000000000utac
- MONIKER=d${DOMAIN:-local} - MONIKER=d${DOMAIN:-local}
- P2P_PORT=10283 - P2P_PORT=10283
- PERSISTENT_PEERS=d0a80c43a10a6b60475864728db6d9ba4ead42d2@107.6.113.60:58960,10550a03e4f7fa487c78fbd07e0770e2b0f085c7@64.46.115.78:58960,0efae9d157f0ef60ad7d25507d6939799f832e34@173.244.202.99:58960,78079166d06e345dbf4a5c932ee3c69a04148e92@107.6.91.38:58960 - PERSISTENT_PEERS=68b409519dea2a057d93ab6df436f6d519f13cb8@65.109.61.125:32156,186e207d2c95e94a44ff613770aa269dac876013@65.108.201.240:32156,c4410e765acead36188500ed75d5666aa209c93d@65.108.205.121:32156
- STATESYNC_RPC=https://tendermint.rpc.tac.build - SEEDS=68b409519dea2a057d93ab6df436f6d519f13cb8@65.109.61.125:32156
- STATESYNC_RPC=https://tacchain-rpc.polkachu.com:443
restart: unless-stopped restart: unless-stopped
stop_grace_period: 5m stop_grace_period: 5m
networks: networks:
@@ -81,7 +81,7 @@ services:
- prometheus-scrape.path=/metrics - prometheus-scrape.path=/metrics
- traefik.enable=true - traefik.enable=true
- traefik.http.middlewares.tac-mainnet-tacchaind-pruned-stripprefix.stripprefix.prefixes=/tac-mainnet - traefik.http.middlewares.tac-mainnet-tacchaind-pruned-stripprefix.stripprefix.prefixes=/tac-mainnet
- traefik.http.services.tac-mainnet-tacchaind-pruned.loadbalancer.server.port=8545 - traefik.http.services.tac-mainnet-tacchaind-pruned.loadbalancer.server.port=26657
- ${NO_SSL:-traefik.http.routers.tac-mainnet-tacchaind-pruned.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.tac-mainnet-tacchaind-pruned.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.tac-mainnet-tacchaind-pruned.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.tac-mainnet-tacchaind-pruned.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.tac-mainnet-tacchaind-pruned.rule=Host(`$DOMAIN`) && (Path(`/tac-mainnet`) || Path(`/tac-mainnet/`))} - ${NO_SSL:-traefik.http.routers.tac-mainnet-tacchaind-pruned.rule=Host(`$DOMAIN`) && (Path(`/tac-mainnet`) || Path(`/tac-mainnet/`))}
@@ -89,14 +89,15 @@ services:
- traefik.http.routers.tac-mainnet-tacchaind-pruned.middlewares=tac-mainnet-tacchaind-pruned-stripprefix, ipallowlist - traefik.http.routers.tac-mainnet-tacchaind-pruned.middlewares=tac-mainnet-tacchaind-pruned-stripprefix, ipallowlist
- traefik.http.routers.tac-mainnet-tacchaind-pruned.priority=50 # gets any request that is not GET with UPGRADE header - traefik.http.routers.tac-mainnet-tacchaind-pruned.priority=50 # gets any request that is not GET with UPGRADE header
- traefik.http.routers.tac-mainnet-tacchaind-pruned-ws.priority=100 # answers GET requests first - traefik.http.routers.tac-mainnet-tacchaind-pruned-ws.priority=100 # answers GET requests first
- traefik.http.services.tac-mainnet-tacchaind-pruned-ws.loadbalancer.server.port=8546 - traefik.http.middlewares.tac-mainnet-tacchaind-pruned-set-ws-path.replacepath.path=/websocket
- traefik.http.services.tac-mainnet-tacchaind-pruned-ws.loadbalancer.server.port=26657
- traefik.http.routers.tac-mainnet-tacchaind-pruned-ws.service=tac-mainnet-tacchaind-pruned-ws - traefik.http.routers.tac-mainnet-tacchaind-pruned-ws.service=tac-mainnet-tacchaind-pruned-ws
- traefik.http.routers.tac-mainnet-tacchaind-pruned.service=tac-mainnet-tacchaind-pruned - traefik.http.routers.tac-mainnet-tacchaind-pruned.service=tac-mainnet-tacchaind-pruned
- ${NO_SSL:-traefik.http.routers.tac-mainnet-tacchaind-pruned-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.tac-mainnet-tacchaind-pruned-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.tac-mainnet-tacchaind-pruned-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.tac-mainnet-tacchaind-pruned-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.tac-mainnet-tacchaind-pruned-ws.rule=Host(`$DOMAIN`) && (Path(`/tac-mainnet`) || Path(`/tac-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)} - ${NO_SSL:-traefik.http.routers.tac-mainnet-tacchaind-pruned-ws.rule=Host(`$DOMAIN`) && (Path(`/tac-mainnet`) || Path(`/tac-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.tac-mainnet-tacchaind-pruned-ws.rule=(Path(`/tac-mainnet`) || Path(`/tac-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)} - ${NO_SSL:+traefik.http.routers.tac-mainnet-tacchaind-pruned-ws.rule=(Path(`/tac-mainnet`) || Path(`/tac-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.tac-mainnet-tacchaind-pruned-ws.middlewares=tac-mainnet-tacchaind-pruned-stripprefix, ipallowlist - traefik.http.routers.tac-mainnet-tacchaind-pruned-ws.middlewares=tac-mainnet-tacchaind-pruned-stripprefix, tac-mainnet-tacchaind-pruned-set-ws-path, ipallowlist
volumes: volumes:
tac-mainnet-tacchaind-pruned: tac-mainnet-tacchaind-pruned:

View File

@@ -53,8 +53,7 @@ services:
- 14331:14331 - 14331:14331
- 14331:14331/udp - 14331:14331/udp
expose: expose:
- 8545 - 26657
- 8546
- 6065 - 6065
environment: environment:
- API=eth,net,web3,txpool,debug - API=eth,net,web3,txpool,debug
@@ -81,7 +80,7 @@ services:
- prometheus-scrape.path=/metrics - prometheus-scrape.path=/metrics
- traefik.enable=true - traefik.enable=true
- traefik.http.middlewares.tac-spb-tacchaind-pruned-stripprefix.stripprefix.prefixes=/tac-spb - traefik.http.middlewares.tac-spb-tacchaind-pruned-stripprefix.stripprefix.prefixes=/tac-spb
- traefik.http.services.tac-spb-tacchaind-pruned.loadbalancer.server.port=8545 - traefik.http.services.tac-spb-tacchaind-pruned.loadbalancer.server.port=26657
- ${NO_SSL:-traefik.http.routers.tac-spb-tacchaind-pruned.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.tac-spb-tacchaind-pruned.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.tac-spb-tacchaind-pruned.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.tac-spb-tacchaind-pruned.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.tac-spb-tacchaind-pruned.rule=Host(`$DOMAIN`) && (Path(`/tac-spb`) || Path(`/tac-spb/`))} - ${NO_SSL:-traefik.http.routers.tac-spb-tacchaind-pruned.rule=Host(`$DOMAIN`) && (Path(`/tac-spb`) || Path(`/tac-spb/`))}
@@ -89,14 +88,15 @@ services:
- traefik.http.routers.tac-spb-tacchaind-pruned.middlewares=tac-spb-tacchaind-pruned-stripprefix, ipallowlist - traefik.http.routers.tac-spb-tacchaind-pruned.middlewares=tac-spb-tacchaind-pruned-stripprefix, ipallowlist
- traefik.http.routers.tac-spb-tacchaind-pruned.priority=50 # gets any request that is not GET with UPGRADE header - traefik.http.routers.tac-spb-tacchaind-pruned.priority=50 # gets any request that is not GET with UPGRADE header
- traefik.http.routers.tac-spb-tacchaind-pruned-ws.priority=100 # answers GET requests first - traefik.http.routers.tac-spb-tacchaind-pruned-ws.priority=100 # answers GET requests first
- traefik.http.services.tac-spb-tacchaind-pruned-ws.loadbalancer.server.port=8546 - traefik.http.middlewares.tac-spb-tacchaind-pruned-set-ws-path.replacepath.path=/websocket
- traefik.http.services.tac-spb-tacchaind-pruned-ws.loadbalancer.server.port=26657
- traefik.http.routers.tac-spb-tacchaind-pruned-ws.service=tac-spb-tacchaind-pruned-ws - traefik.http.routers.tac-spb-tacchaind-pruned-ws.service=tac-spb-tacchaind-pruned-ws
- traefik.http.routers.tac-spb-tacchaind-pruned.service=tac-spb-tacchaind-pruned - traefik.http.routers.tac-spb-tacchaind-pruned.service=tac-spb-tacchaind-pruned
- ${NO_SSL:-traefik.http.routers.tac-spb-tacchaind-pruned-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.tac-spb-tacchaind-pruned-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.tac-spb-tacchaind-pruned-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.tac-spb-tacchaind-pruned-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.tac-spb-tacchaind-pruned-ws.rule=Host(`$DOMAIN`) && (Path(`/tac-spb`) || Path(`/tac-spb/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)} - ${NO_SSL:-traefik.http.routers.tac-spb-tacchaind-pruned-ws.rule=Host(`$DOMAIN`) && (Path(`/tac-spb`) || Path(`/tac-spb/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.tac-spb-tacchaind-pruned-ws.rule=(Path(`/tac-spb`) || Path(`/tac-spb/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)} - ${NO_SSL:+traefik.http.routers.tac-spb-tacchaind-pruned-ws.rule=(Path(`/tac-spb`) || Path(`/tac-spb/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.tac-spb-tacchaind-pruned-ws.middlewares=tac-spb-tacchaind-pruned-stripprefix, ipallowlist - traefik.http.routers.tac-spb-tacchaind-pruned-ws.middlewares=tac-spb-tacchaind-pruned-stripprefix, tac-spb-tacchaind-pruned-set-ws-path, ipallowlist
volumes: volumes:
tac-spb-tacchaind-pruned: tac-spb-tacchaind-pruned:

View File

@@ -53,6 +53,7 @@ services:
RETH_REPO: ${TAIKO_ALETHIA_RETH_REPO:-https://github.com/taikoxyz/alethia-reth} RETH_REPO: ${TAIKO_ALETHIA_RETH_REPO:-https://github.com/taikoxyz/alethia-reth}
ARCH_TARGET: ${ARCH_TARGET:-native} ARCH_TARGET: ${ARCH_TARGET:-native}
PROFILE: ${RETH_BUILD_PROFILE:-maxperf} PROFILE: ${RETH_BUILD_PROFILE:-maxperf}
BUILD_ALETHIA_RETH: true
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -82,7 +83,7 @@ services:
entrypoint: [reth, node] entrypoint: [reth, node]
command: command:
- --bootnodes=enode://266a8e3b5e44201eca9c368d58aa59a7750295397e77d5b32aea2644f9962cbc4e1cb0543aab0480995a209408174413f65e5ce253d60bb83d22d3b8ab12eb89@34.142.239.251:30303,enode://264a7fc4bd1ee16cfc6eb420c643407bfc61b9c9534c5a39ba6e68c8759beda2fbeccefee8677385e3d99691eeb218da4bce7f5207cf38594ac0f6a53c128b9b@35.247.159.156:30303,enode://2d4e5b7ec0c57f9def6ebe72f9bd1f65c33c87b7dc38875bbb147c10e8ec9a8cd157558b695f9a02ac6ad789f300fab4f1f19d41273956491372e96880a3459f@34.126.90.255:30303,enode://57f4b29cd8b59dc8db74be51eedc6425df2a6265fad680c843be113232bbe632933541678783c2a5759d65eac2e2241c45a34e1c36254bccfe7f72e52707e561@104.197.107.1:30303,enode://87a68eef46cc1fe862becef1185ac969dfbcc050d9304f6be21599bfdcb45a0eb9235d3742776bc4528ac3ab631eba6816e9b47f6ee7a78cc5fcaeb10cd32574@35.232.246.122:30303 - --bootnodes=enode://266a8e3b5e44201eca9c368d58aa59a7750295397e77d5b32aea2644f9962cbc4e1cb0543aab0480995a209408174413f65e5ce253d60bb83d22d3b8ab12eb89@34.142.239.251:30303,enode://264a7fc4bd1ee16cfc6eb420c643407bfc61b9c9534c5a39ba6e68c8759beda2fbeccefee8677385e3d99691eeb218da4bce7f5207cf38594ac0f6a53c128b9b@35.247.159.156:30303,enode://2d4e5b7ec0c57f9def6ebe72f9bd1f65c33c87b7dc38875bbb147c10e8ec9a8cd157558b695f9a02ac6ad789f300fab4f1f19d41273956491372e96880a3459f@34.126.90.255:30303,enode://57f4b29cd8b59dc8db74be51eedc6425df2a6265fad680c843be113232bbe632933541678783c2a5759d65eac2e2241c45a34e1c36254bccfe7f72e52707e561@104.197.107.1:30303,enode://87a68eef46cc1fe862becef1185ac969dfbcc050d9304f6be21599bfdcb45a0eb9235d3742776bc4528ac3ab631eba6816e9b47f6ee7a78cc5fcaeb10cd32574@35.232.246.122:30303
- --chain=alethia - --chain=mainnet
- --datadir=/root/.local/share/reth - --datadir=/root/.local/share/reth
- --discovery.port=11608 - --discovery.port=11608
- --engine.cross-block-cache-size=${TAIKO_ALETHIA_RETH_STATE_CACHE:-4096} - --engine.cross-block-cache-size=${TAIKO_ALETHIA_RETH_STATE_CACHE:-4096}

View File

@@ -53,6 +53,7 @@ services:
RETH_REPO: ${TAIKO_ALETHIA_RETH_REPO:-https://github.com/taikoxyz/alethia-reth} RETH_REPO: ${TAIKO_ALETHIA_RETH_REPO:-https://github.com/taikoxyz/alethia-reth}
ARCH_TARGET: ${ARCH_TARGET:-native} ARCH_TARGET: ${ARCH_TARGET:-native}
PROFILE: ${RETH_BUILD_PROFILE:-maxperf} PROFILE: ${RETH_BUILD_PROFILE:-maxperf}
BUILD_ALETHIA_RETH: true
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -82,7 +83,7 @@ services:
entrypoint: [reth, node] entrypoint: [reth, node]
command: command:
- --bootnodes=enode://266a8e3b5e44201eca9c368d58aa59a7750295397e77d5b32aea2644f9962cbc4e1cb0543aab0480995a209408174413f65e5ce253d60bb83d22d3b8ab12eb89@34.142.239.251:30303,enode://264a7fc4bd1ee16cfc6eb420c643407bfc61b9c9534c5a39ba6e68c8759beda2fbeccefee8677385e3d99691eeb218da4bce7f5207cf38594ac0f6a53c128b9b@35.247.159.156:30303,enode://2d4e5b7ec0c57f9def6ebe72f9bd1f65c33c87b7dc38875bbb147c10e8ec9a8cd157558b695f9a02ac6ad789f300fab4f1f19d41273956491372e96880a3459f@34.126.90.255:30303,enode://57f4b29cd8b59dc8db74be51eedc6425df2a6265fad680c843be113232bbe632933541678783c2a5759d65eac2e2241c45a34e1c36254bccfe7f72e52707e561@104.197.107.1:30303,enode://87a68eef46cc1fe862becef1185ac969dfbcc050d9304f6be21599bfdcb45a0eb9235d3742776bc4528ac3ab631eba6816e9b47f6ee7a78cc5fcaeb10cd32574@35.232.246.122:30303 - --bootnodes=enode://266a8e3b5e44201eca9c368d58aa59a7750295397e77d5b32aea2644f9962cbc4e1cb0543aab0480995a209408174413f65e5ce253d60bb83d22d3b8ab12eb89@34.142.239.251:30303,enode://264a7fc4bd1ee16cfc6eb420c643407bfc61b9c9534c5a39ba6e68c8759beda2fbeccefee8677385e3d99691eeb218da4bce7f5207cf38594ac0f6a53c128b9b@35.247.159.156:30303,enode://2d4e5b7ec0c57f9def6ebe72f9bd1f65c33c87b7dc38875bbb147c10e8ec9a8cd157558b695f9a02ac6ad789f300fab4f1f19d41273956491372e96880a3459f@34.126.90.255:30303,enode://57f4b29cd8b59dc8db74be51eedc6425df2a6265fad680c843be113232bbe632933541678783c2a5759d65eac2e2241c45a34e1c36254bccfe7f72e52707e561@104.197.107.1:30303,enode://87a68eef46cc1fe862becef1185ac969dfbcc050d9304f6be21599bfdcb45a0eb9235d3742776bc4528ac3ab631eba6816e9b47f6ee7a78cc5fcaeb10cd32574@35.232.246.122:30303
- --chain=alethia - --chain=mainnet
- --datadir=/root/.local/share/reth - --datadir=/root/.local/share/reth
- --discovery.port=13559 - --discovery.port=13559
- --engine.cross-block-cache-size=${TAIKO_ALETHIA_RETH_STATE_CACHE:-4096} - --engine.cross-block-cache-size=${TAIKO_ALETHIA_RETH_STATE_CACHE:-4096}

View File

@@ -16,7 +16,15 @@ else
PROTO="https" PROTO="https"
fi fi
pathlist=$(cat $BASEPATH/$1.yml | grep -oP "stripprefix\.prefixes.*?/\K[^\"]+") compose_yml="$BASEPATH/$1.yml"
pathlist=$(cat "$compose_yml" | grep -oP "stripprefix\.prefixes.*?/\K[^\"]+")
# Resolve protocol from x-upstreams chain label (reuse sync-status / catchup idiom).
chain_slug=$(grep -oP '^\s*chain:\s*\K\S+' "$compose_yml" 2>/dev/null | head -1)
protocol=""
if [ -n "$chain_slug" ]; then
protocol=$($BASEPATH/reference-rpc-endpoint.sh --protocol "$chain_slug" 2>/dev/null) || protocol=""
fi
for path in $pathlist; do for path in $pathlist; do
include=true include=true
@@ -30,6 +38,40 @@ for path in $pathlist; do
RPC_URL="$PROTO://$DOMAIN/$path" RPC_URL="$PROTO://$DOMAIN/$path"
response_file=$(mktemp) response_file=$(mktemp)
path_protocol="$protocol"
if [ -z "$path_protocol" ]; then
if echo "$path" | grep -qi "starknet"; then
path_protocol="starknet"
elif echo "$path" | grep -qi "aztec"; then
path_protocol="aztec"
elif echo "$path" | grep -qiE "cosmos|babylon|haqq|gaiad|tac"; then
path_protocol="cosmos"
else
path_protocol="eth"
fi
fi
if [ "$path_protocol" = "cosmos" ]; then
http_status_code=$(curl -L --ipv4 -m 1 -s -X POST -w "%{http_code}" -o "$response_file" \
-H "Content-Type: application/json" --data '{"jsonrpc":"2.0","id":1,"method":"status"}' "$RPC_URL")
if [ $? -eq 0 ] && [[ $http_status_code -eq 200 ]]; then
response=$(cat "$response_file")
latest_block_time=$(echo "$response" | jq -r '.result.sync_info.latest_block_time // .sync_info.latest_block_time' 2>/dev/null)
rm -f "$response_file"
if [ -z "$latest_block_time" ] || [ "$latest_block_time" = "null" ]; then
exit 1
fi
latest_block_timestamp_decimal=$(date -d "$latest_block_time" +%s 2>/dev/null)
if [ -z "$latest_block_timestamp_decimal" ]; then
exit 1
fi
echo "$latest_block_timestamp_decimal"
exit 0
fi
rm -f "$response_file"
exit 1
fi
# Detect Starknet vs Ethereum vs Aztec based on path # Detect Starknet vs Ethereum vs Aztec based on path
if echo "$path" | grep -qi "starknet"; then if echo "$path" | grep -qi "starknet"; then
rpc_method='{"jsonrpc":"2.0","method":"starknet_getBlockWithTxHashes","params":["latest"],"id":1}' rpc_method='{"jsonrpc":"2.0","method":"starknet_getBlockWithTxHashes","params":["latest"],"id":1}'

View File

@@ -3,6 +3,191 @@
# Shared helpers for compose volume operations. # Shared helpers for compose volume operations.
# Ephemeral volumes (init-container config) are excluded from backup/restore/size. # Ephemeral volumes (init-container config) are excluded from backup/restore/size.
# Minimum on-disk bytes for a backup archive to be considered restorable (near-empty
# zstd headers from purged/missing volumes must not win sort|tail newest selection).
MIN_RESTORABLE_BACKUP_BYTES=$((1024 * 1024))
RPC_ENV_FILE="/root/rpc/.env"
backup_archive_size_bytes() {
local file=$1
stat -c%s "$file" 2>/dev/null || echo 0
}
is_restorable_backup_archive() {
local file=$1
local size
[[ -f "$file" ]] || return 1
size=$(backup_archive_size_bytes "$file")
[[ "$size" =~ ^[0-9]+$ ]] && (( size >= MIN_RESTORABLE_BACKUP_BYTES ))
}
# Pick the lexicographically newest backup that is not near-empty (<1MB). Prints one
# skip line per rejected artifact; returns empty when none qualify.
select_newest_local_backup() {
local backup_dir=$1
local volume_name=$2
local pattern="${backup_dir}/${volume_name}"-[0-9]*G.tar.zst
local newest="" f size
shopt -s nullglob
local files=( $pattern )
shopt -u nullglob
if (( ${#files[@]} == 0 )); then
return 0
fi
IFS=$'\n' files=( $(printf '%s\n' "${files[@]}" | sort) )
unset IFS
for f in "${files[@]}"; do
size=$(backup_archive_size_bytes "$f")
if [[ ! "$size" =~ ^[0-9]+$ ]] || (( size < MIN_RESTORABLE_BACKUP_BYTES )); then
echo "skip near-empty backup artifact: $(basename "$f") (${size:-0} bytes)" >&2
continue
fi
newest="$f"
done
if [[ -n "$newest" ]]; then
echo "$newest"
fi
}
remote_backup_archive_size_bytes() {
local remote_source=$1
local archive_name=$2
curl --ipv4 -fsSI "${remote_source}${archive_name}" 2>/dev/null \
| awk -F': ' 'tolower($1)=="content-length" {gsub(/\r/,"",$2); print $2; exit}'
}
# Newest restorable backup filename (not path) from a remote WebDAV listing on stdin.
select_newest_remote_backup_from_list() {
local remote_source=$1
local volume_name=$2
local newest="" f size
local -a files=()
while IFS= read -r f; do
[[ -n "$f" ]] && files+=("$f")
done
if (( ${#files[@]} == 0 )); then
return 0
fi
IFS=$'\n' files=( $(printf '%s\n' "${files[@]}" | sort) )
unset IFS
for f in "${files[@]}"; do
[[ "$f" == "${volume_name}-"* ]] || continue
[[ "$f" == *.tar.zst ]] || continue
size=$(remote_backup_archive_size_bytes "$remote_source" "$f")
if [[ -z "$size" || ! "$size" =~ ^[0-9]+$ ]] || (( size < MIN_RESTORABLE_BACKUP_BYTES )); then
echo "skip near-empty backup artifact: $f (${size:-unknown} bytes)" >&2
continue
fi
newest="$f"
done
if [[ -n "$newest" ]]; then
echo "$newest"
fi
}
compose_fence_marker_path() {
local compose_name=$1
local env_dir
env_dir=$(dirname "$RPC_ENV_FILE")
echo "${env_dir}/.env.fence-$(echo "$compose_name" | tr '/' '_')"
}
# Remove a compose yml segment from COMPOSE_FILE; store it in a sidecar marker for restore.
fence_compose_in_env() {
local compose_name=$1
local yml_segment="${compose_name}.yml"
local env_file="$RPC_ENV_FILE"
local marker
marker=$(compose_fence_marker_path "$compose_name")
[[ -f "$env_file" ]] || { echo "WARN: $env_file missing, cannot fence $compose_name" >&2; return 1; }
[[ -f "$marker" ]] && { echo "WARN: fence marker already exists: $marker" >&2; return 1; }
local line compose_file new_compose removed=0
line=$(grep -E '^COMPOSE_FILE=' "$env_file" | head -n 1)
[[ -n "$line" ]] || { echo "WARN: COMPOSE_FILE not found in $env_file" >&2; return 1; }
compose_file="${line#COMPOSE_FILE=}"
compose_file="${compose_file#\"}"
compose_file="${compose_file%\"}"
local part new_parts=()
IFS=':' read -ra parts <<< "$compose_file"
for part in "${parts[@]}"; do
if [[ "$part" == "$yml_segment" ]]; then
if ! printf '%s\n' "$part" > "$marker"; then
echo "WARN: failed to write fence marker $marker" >&2
return 1
fi
removed=1
else
new_parts+=("$part")
fi
done
unset IFS
if (( removed == 0 )); then
echo "WARN: $yml_segment not present in COMPOSE_FILE (already fenced?)" >&2
return 1
fi
new_compose=$(IFS=':'; echo "${new_parts[*]}")
if grep -q '^COMPOSE_FILE=' "$env_file"; then
sed -i "s|^COMPOSE_FILE=.*|COMPOSE_FILE=${new_compose}|" "$env_file"
else
echo "COMPOSE_FILE=${new_compose}" >> "$env_file"
fi
echo "Fenced $yml_segment from COMPOSE_FILE (marker: $marker)"
}
# Restore a fenced compose segment before service-scoped start (start needs the entry).
unfence_compose_in_env() {
local compose_name=$1
local yml_segment="${compose_name}.yml"
local env_file="$RPC_ENV_FILE"
local marker
marker=$(compose_fence_marker_path "$compose_name")
[[ -f "$marker" ]] || return 0
local segment line compose_file
segment=$(cat "$marker")
[[ -n "$segment" ]] || { rm -f "$marker"; return 0; }
if [[ -f "$env_file" ]]; then
line=$(grep -E '^COMPOSE_FILE=' "$env_file" | head -n 1)
compose_file="${line#COMPOSE_FILE=}"
compose_file="${compose_file#\"}"
compose_file="${compose_file%\"}"
case ":$compose_file:" in
*:"$segment":*) ;;
*)
if [[ -n "$compose_file" ]]; then
compose_file="${compose_file}:${segment}"
else
compose_file="$segment"
fi
sed -i "s|^COMPOSE_FILE=.*|COMPOSE_FILE=${compose_file}|" "$env_file"
;;
esac
else
echo "COMPOSE_FILE=${segment}" > "$env_file"
fi
rm -f "$marker"
echo "Unfenced $yml_segment into COMPOSE_FILE"
}
is_ephemeral_volume_key() { is_ephemeral_volume_key() {
local key=$1 local key=$1
local compose_file=$2 local compose_file=$2