ripple: deployable mainnet + testnet rippled with health checks
Fix mainnet rippled.cfg (ws,http RPC, port_peer 13331), strip eth-isms from x-upstreams, add testnet chain assets/compose, and wire --ripple sync-status via check-health.sh server_info probe. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -10,10 +10,11 @@ fi
|
||||
RPC_URL=$1
|
||||
shift
|
||||
|
||||
# Check for --starknet / --aztec / --cosmos flag
|
||||
# Check for --starknet / --aztec / --cosmos / --ripple flag
|
||||
is_starknet=false
|
||||
is_aztec=false
|
||||
is_cosmos=false
|
||||
is_ripple=false
|
||||
if [ "$1" == "--starknet" ]; then
|
||||
is_starknet=true
|
||||
shift
|
||||
@@ -23,6 +24,9 @@ elif [ "$1" == "--aztec" ]; then
|
||||
elif [ "$1" == "--cosmos" ]; then
|
||||
is_cosmos=true
|
||||
shift
|
||||
elif [ "$1" == "--ripple" ]; then
|
||||
is_ripple=true
|
||||
shift
|
||||
fi
|
||||
|
||||
REF=""
|
||||
@@ -59,6 +63,45 @@ if $is_cosmos; then
|
||||
echo "online"; exit 0
|
||||
fi
|
||||
|
||||
# XRPL rippled: server_info — server_state full/proposing + fresh validated ledger = online.
|
||||
# Short-circuits here; the EVM/starknet/aztec block-comparison path below is not used.
|
||||
if $is_ripple; then
|
||||
status=$(curl -L --ipv4 -m $timeout -s -X POST -H "Content-Type: application/json" --data '{"method":"server_info"}' "$RPC_URL")
|
||||
if [ $? -ne 0 ] || [ -z "$status" ]; then echo "error"; exit 1; fi
|
||||
server_state=$(echo "$status" | jq -r '.result.info.server_state // .info.server_state' 2>/dev/null)
|
||||
ledger_age=$(echo "$status" | jq -r '.result.info.validated_ledger.age // .info.validated_ledger.age' 2>/dev/null)
|
||||
node_seq=$(echo "$status" | jq -r '.result.info.validated_ledger.seq // .info.validated_ledger.seq' 2>/dev/null)
|
||||
if [ -z "$server_state" ] || [ "$server_state" = "null" ]; then echo "error"; exit 1; fi
|
||||
case "$server_state" in
|
||||
connected|syncing|tracking)
|
||||
echo "syncing"; exit 1 ;;
|
||||
full|proposing)
|
||||
;;
|
||||
*)
|
||||
echo "error"; exit 1 ;;
|
||||
esac
|
||||
if [ -z "$ledger_age" ] || [ "$ledger_age" = "null" ] || [ "$ledger_age" -gt 20 ] 2>/dev/null; then
|
||||
echo "behind"; exit 1
|
||||
fi
|
||||
if [ -n "$ref" ]; then
|
||||
ref_status=$($BASEPATH/multicurl.sh -L --ipv4 -m $timeout -s -X POST -H "Content-Type: application/json" --data '{"method":"server_info"}' $ref)
|
||||
ref_seq=$(echo "$ref_status" | jq -r '.result.info.validated_ledger.seq // .info.validated_ledger.seq' 2>/dev/null)
|
||||
if [ -n "$ref_seq" ] && [ "$ref_seq" != "null" ] && [ "$ref_seq" -gt 0 ] 2>/dev/null && [ -n "$node_seq" ] && [ "$node_seq" != "null" ]; then
|
||||
lag=$(( ref_seq - node_seq ))
|
||||
lo=${LAGGING_LAG:-5}; hi=${SYNCING_LAG:-10}
|
||||
if [ "$lo" -gt "$hi" ]; then tmp=$lo; lo=$hi; hi=$tmp; fi
|
||||
if [ "$lag" -le "$lo" ]; then
|
||||
echo "online"; exit 0
|
||||
elif [ "$lag" -le "$hi" ]; then
|
||||
echo "lagging"; exit 0
|
||||
else
|
||||
echo "syncing"; exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
echo "online"; exit 0
|
||||
fi
|
||||
|
||||
response_file=$(mktemp)
|
||||
|
||||
# Use appropriate RPC method based on chain type
|
||||
|
||||
@@ -7901,6 +7901,22 @@
|
||||
"ripple-mainnet-rippled-pruned-nudb"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chain": "testnet",
|
||||
"client": "rippled",
|
||||
"compose_file": "ripple/rippled/ripple-testnet-rippled-pruned-nudb",
|
||||
"features": [
|
||||
"nudb"
|
||||
],
|
||||
"network": "ripple",
|
||||
"node": null,
|
||||
"relay": null,
|
||||
"stack": null,
|
||||
"type": "pruned",
|
||||
"volumes": [
|
||||
"ripple-testnet-rippled-pruned-nudb"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chain": "mainnet",
|
||||
"client": "ronin",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
[server]
|
||||
port_rpc_admin_local
|
||||
port_ws_public
|
||||
|
||||
# port_peer
|
||||
port_peer
|
||||
# port_ws_admin_local
|
||||
# ssl_key = /etc/ssl/private/server.key
|
||||
# ssl_cert = /etc/ssl/certs/server.crt
|
||||
@@ -16,12 +15,12 @@ protocol = http
|
||||
[port_ws_public]
|
||||
port = 8545
|
||||
ip = 0.0.0.0
|
||||
protocol = ws
|
||||
protocol = ws,http
|
||||
|
||||
# [port_peer]
|
||||
# port = 51235
|
||||
# ip = 0.0.0.0
|
||||
# protocol = peer
|
||||
[port_peer]
|
||||
port = 13331
|
||||
ip = 0.0.0.0
|
||||
protocol = peer
|
||||
|
||||
# [port_ws_admin_local]
|
||||
# port = 6006
|
||||
@@ -83,4 +82,4 @@ validators.txt
|
||||
# fatal
|
||||
|
||||
[ssl_verify]
|
||||
1
|
||||
1
|
||||
|
||||
@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
|
||||
|
||||
services:
|
||||
ripple-mainnet:
|
||||
image: ${RIPPLE_RIPPLED_IMAGE:-xrpllabsofficial/xrpld}:${RIPPLE_MAINNET_RIPPLED_VERSION:-3.1.3}
|
||||
image: ${RIPPLE_RIPPLED_IMAGE:-xrpllabsofficial/xrpld}:${RIPPLE_MAINNET_RIPPLED_VERSION:-3.2.0}
|
||||
sysctls:
|
||||
# TCP Performance
|
||||
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
|
||||
@@ -86,12 +86,4 @@ x-upstreams:
|
||||
msgSize: 50Mb
|
||||
url: $${WS_URL}
|
||||
chain: ripple
|
||||
method-groups:
|
||||
enabled:
|
||||
- debug
|
||||
- filter
|
||||
methods:
|
||||
disabled:
|
||||
enabled:
|
||||
- name: txpool_content # TODO: should be disabled for rollup nodes
|
||||
...
|
||||
89
ripple/rippled/ripple-testnet-rippled-pruned-nudb.yml
Normal file
89
ripple/rippled/ripple-testnet-rippled-pruned-nudb.yml
Normal file
@@ -0,0 +1,89 @@
|
||||
---
|
||||
x-logging-defaults: &logging-defaults
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
# Usage:
|
||||
#
|
||||
# mkdir rpc && cd rpc
|
||||
#
|
||||
# git init
|
||||
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
|
||||
# git fetch origin vibe
|
||||
# git checkout origin/vibe
|
||||
#
|
||||
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
|
||||
#
|
||||
# env
|
||||
# ...
|
||||
# IP=$(curl ipinfo.io/ip)
|
||||
# DOMAIN=${IP}.traefik.me
|
||||
# COMPOSE_FILE=base.yml:rpc.yml:ripple/rippled/ripple-testnet-rippled-pruned-nudb.yml
|
||||
#
|
||||
# docker compose up -d
|
||||
#
|
||||
# curl -X POST https://${IP}.traefik.me/ripple-testnet \
|
||||
# -H "Content-Type: application/json" \
|
||||
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
|
||||
|
||||
services:
|
||||
ripple-testnet:
|
||||
image: ${RIPPLE_RIPPLED_IMAGE:-xrpllabsofficial/xrpld}:${RIPPLE_TESTNET_RIPPLED_VERSION:-3.2.0}
|
||||
sysctls:
|
||||
# TCP Performance
|
||||
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
|
||||
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
|
||||
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
|
||||
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
|
||||
net.core.somaxconn: 32768 # Higher connection queue
|
||||
# Memory/Connection Management
|
||||
# net.core.netdev_max_backlog: 50000 # Increase network buffer
|
||||
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
|
||||
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
|
||||
ulimits:
|
||||
nofile: 1048576 # Max open files (for RPC/WS connections)
|
||||
user: root
|
||||
ports:
|
||||
- 12986:12986
|
||||
- 12986:12986/udp
|
||||
expose:
|
||||
- 8545
|
||||
restart: unless-stopped
|
||||
stop_grace_period: 5m
|
||||
networks:
|
||||
- chains
|
||||
volumes:
|
||||
- ${RIPPLE_TESTNET_RIPPLED_PRUNED_NUDB_DATA:-ripple-testnet-rippled-pruned-nudb}:/var/lib/rippled/db
|
||||
- ./ripple/testnet:/config
|
||||
- /slowdisk:/slowdisk
|
||||
logging: *logging-defaults
|
||||
labels:
|
||||
- prometheus-scrape.enabled=false
|
||||
- traefik.enable=true
|
||||
- traefik.http.middlewares.ripple-testnet-rippled-pruned-nudb-stripprefix.stripprefix.prefixes=/ripple-testnet
|
||||
- traefik.http.services.ripple-testnet-rippled-pruned-nudb.loadbalancer.server.port=8545
|
||||
- ${NO_SSL:-traefik.http.routers.ripple-testnet-rippled-pruned-nudb.entrypoints=websecure}
|
||||
- ${NO_SSL:-traefik.http.routers.ripple-testnet-rippled-pruned-nudb.tls.certresolver=myresolver}
|
||||
- ${NO_SSL:-traefik.http.routers.ripple-testnet-rippled-pruned-nudb.rule=Host(`$DOMAIN`) && (Path(`/ripple-testnet`) || Path(`/ripple-testnet/`))}
|
||||
- ${NO_SSL:+traefik.http.routers.ripple-testnet-rippled-pruned-nudb.rule=Path(`/ripple-testnet`) || Path(`/ripple-testnet/`)}
|
||||
- traefik.http.routers.ripple-testnet-rippled-pruned-nudb.middlewares=ripple-testnet-rippled-pruned-nudb-stripprefix, ipallowlist
|
||||
|
||||
volumes:
|
||||
ripple-testnet-rippled-pruned-nudb:
|
||||
|
||||
x-upstreams:
|
||||
- id: $${ID}
|
||||
labels:
|
||||
provider: $${PROVIDER}
|
||||
connection:
|
||||
generic:
|
||||
rpc:
|
||||
url: $${RPC_URL}
|
||||
ws:
|
||||
frameSize: 20Mb
|
||||
msgSize: 50Mb
|
||||
url: $${WS_URL}
|
||||
chain: ripple-testnet
|
||||
...
|
||||
88
ripple/testnet/rippled.cfg
Normal file
88
ripple/testnet/rippled.cfg
Normal file
@@ -0,0 +1,88 @@
|
||||
[server]
|
||||
port_rpc_admin_local
|
||||
port_ws_public
|
||||
port_peer
|
||||
# port_ws_admin_local
|
||||
# ssl_key = /etc/ssl/private/server.key
|
||||
# ssl_cert = /etc/ssl/certs/server.crt
|
||||
|
||||
[port_rpc_admin_local]
|
||||
port = 5005
|
||||
ip = 127.0.0.1
|
||||
admin = 127.0.0.1
|
||||
protocol = http
|
||||
|
||||
[port_ws_public]
|
||||
port = 8545
|
||||
ip = 0.0.0.0
|
||||
protocol = ws,http
|
||||
|
||||
[port_peer]
|
||||
port = 12986
|
||||
ip = 0.0.0.0
|
||||
protocol = peer
|
||||
|
||||
# [port_ws_admin_local]
|
||||
# port = 6006
|
||||
# ip = 127.0.0.1
|
||||
# admin = 127.0.0.1
|
||||
# protocol = ws
|
||||
|
||||
[node_size]
|
||||
small
|
||||
|
||||
# tiny
|
||||
# small
|
||||
# medium
|
||||
# large
|
||||
# huge
|
||||
|
||||
[node_db]
|
||||
type=NuDB
|
||||
path=/var/lib/rippled/db/nudb
|
||||
advisory_delete=0
|
||||
|
||||
# How many ledgers do we want to keep (history)?
|
||||
# Integer value that defines the number of ledgers
|
||||
# between online deletion events
|
||||
online_delete=256
|
||||
|
||||
[ledger_history]
|
||||
# How many ledgers do we want to keep (history)?
|
||||
# Integer value (ledger count)
|
||||
# or (if you have lots of TB SSD storage): 'full'
|
||||
256
|
||||
|
||||
[database_path]
|
||||
/var/lib/rippled/db
|
||||
|
||||
[debug_logfile]
|
||||
/var/lib/rippled/db/debug.log
|
||||
|
||||
[sntp_servers]
|
||||
time.windows.com
|
||||
time.apple.com
|
||||
time.nist.gov
|
||||
pool.ntp.org
|
||||
|
||||
[ips]
|
||||
s.altnet.rippletest.net 51235
|
||||
|
||||
[network_id]
|
||||
testnet
|
||||
|
||||
[validators_file]
|
||||
validators.txt
|
||||
|
||||
[rpc_startup]
|
||||
{ "command": "log_level", "severity": "info" }
|
||||
|
||||
# severity (order: lots of information .. only errors)
|
||||
# debug
|
||||
# info
|
||||
# warn
|
||||
# error
|
||||
# fatal
|
||||
|
||||
[ssl_verify]
|
||||
1
|
||||
5
ripple/testnet/validators.txt
Normal file
5
ripple/testnet/validators.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
[validator_list_sites]
|
||||
https://vl.altnet.rippletest.net
|
||||
|
||||
[validator_list_keys]
|
||||
ED264807102805220DA0F312E71FC2C69E1552C9C5790F6C25E3729DEB573D5860
|
||||
@@ -54,7 +54,7 @@ for path in $pathlist; do
|
||||
fi
|
||||
|
||||
case "$protocol" in
|
||||
eth|starknet|aztec|cosmos)
|
||||
eth|starknet|aztec|cosmos|ripple)
|
||||
;;
|
||||
*)
|
||||
# Protocol family known from the registry but no probe support
|
||||
@@ -68,9 +68,11 @@ for path in $pathlist; do
|
||||
is_starknet=false
|
||||
is_aztec=false
|
||||
is_cosmos=false
|
||||
is_ripple=false
|
||||
[ "$protocol" = "starknet" ] && is_starknet=true
|
||||
[ "$protocol" = "aztec" ] && is_aztec=true
|
||||
[ "$protocol" = "cosmos" ] && is_cosmos=true
|
||||
[ "$protocol" = "ripple" ] && is_ripple=true
|
||||
|
||||
ref=''
|
||||
if [ -n "$2" ]; then
|
||||
@@ -135,6 +137,12 @@ for path in $pathlist; do
|
||||
if [ -n "$chain_slug" ]; then
|
||||
ref=$($BASEPATH/reference-rpc-endpoint.sh --chain "$chain_slug" 2>/dev/null) || ref=""
|
||||
fi
|
||||
elif $is_ripple; then
|
||||
# XRPL: no chainid. Reference by drpc slug (optional — server_state is
|
||||
# authoritative; ref only adds a validated-ledger seq gap check).
|
||||
if [ -n "$chain_slug" ]; then
|
||||
ref=$($BASEPATH/reference-rpc-endpoint.sh --chain "$chain_slug" 2>/dev/null) || ref=""
|
||||
fi
|
||||
else
|
||||
# Ethereum chain ID detection
|
||||
chain_id_response=$(curl -L --ipv4 -m 1 -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' $RPC_URL)
|
||||
@@ -186,6 +194,8 @@ for path in $pathlist; do
|
||||
timeout "$HC_TIMEOUT" $BASEPATH/check-health.sh "$RPC_URL" --starknet $ref
|
||||
elif $is_cosmos; then
|
||||
timeout "$HC_TIMEOUT" $BASEPATH/check-health.sh "$RPC_URL" --cosmos $ref
|
||||
elif $is_ripple; then
|
||||
timeout "$HC_TIMEOUT" $BASEPATH/check-health.sh "$RPC_URL" --ripple $ref
|
||||
else
|
||||
timeout "$HC_TIMEOUT" $BASEPATH/check-health.sh "$RPC_URL" $ref
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user