1 Commits

Author SHA1 Message Date
a7135129eb fix: use admin_addPeer for op-geth peer reconciliation
op-geth does not support admin_addStaticPeer; classify op-geth via
compose path (admin_nodeInfo often still says Geth) and fall back on
go-ethereum-style "does not exist/is not available" errors so reinject
and connect-peers restore peers (e.g. hashkey-mainnet).
2026-07-30 11:58:12 +00:00
3 changed files with 37 additions and 15 deletions

View File

@@ -318,12 +318,19 @@ check_rpc_success() {
return 1
}
# Function to detect client type from node name
# Function to detect client type from node name (+ optional compose path hint).
# op-geth often still reports admin_nodeInfo.name as "Geth/…", so the compose
# path (…/op-geth/… or *-op-geth-*) is the reliable signal.
detect_client_type() {
local node_name="$1"
local compose_hint="${2:-}"
local name_lower=$(echo "$node_name" | tr '[:upper:]' '[:lower:]')
if [[ "$name_lower" == *"geth"* ]]; then
local hint_lower=$(echo "$compose_hint" | tr '[:upper:]' '[:lower:]')
# op-geth lacks admin_addStaticPeer — must use admin_addPeer
if [[ "$name_lower" == *"op-geth"* ]] || [[ "$hint_lower" == *"op-geth"* ]]; then
echo "op-geth"
elif [[ "$name_lower" == *"geth"* ]]; then
echo "geth"
elif [[ "$name_lower" == *"reth"* ]]; then
echo "reth"
@@ -346,12 +353,12 @@ add_static_peer() {
local response
local method
# Determine which method to try first based on client type
# Determine which method to try first based on client type.
# Only vanilla geth supports admin_addStaticPeer; op-geth does not.
if [[ "$client_type" == "geth" ]]; then
# Geth supports admin_addStaticPeer
method="admin_addStaticPeer"
else
# Reth and most other clients use admin_addPeer
# op-geth, reth, and most other clients use admin_addPeer
method="admin_addPeer"
fi
@@ -364,10 +371,11 @@ add_static_peer() {
return 1
}
# Check if method not found, try fallback
if echo "$response" | grep -qi "method not found"; then
# Fallback when the primary method is unsupported. go-ethereum-style errors
# say "the method X does not exist/is not available", not "method not found".
if echo "$response" | grep -qiE 'method not found|does not exist|not available|-32601'; then
if [[ "$method" == "admin_addStaticPeer" ]]; then
# Try admin_addPeer as fallback
# Try admin_addPeer as fallback (required for op-geth)
method="admin_addPeer"
response=$(curl --ipv4 -s -X POST "$url" \
-H "Content-Type: application/json" \
@@ -425,7 +433,7 @@ echo -e "${GREEN}OK${NC}"
SOURCE_ENODE=$(extract_enode "$SOURCE_INFO")
SOURCE_NAME=$(extract_name "$SOURCE_INFO")
SOURCE_PUBKEY=$(echo "$SOURCE_ENODE" | sed -E 's|enode://([^@]+)@.*|\1|')
SOURCE_CLIENT=$(detect_client_type "$SOURCE_NAME")
SOURCE_CLIENT=$(detect_client_type "$SOURCE_NAME" "$COMPOSE_FILE")
if [[ -z "$SOURCE_ENODE" ]]; then
echo -e "${RED}Could not extract enode from source${NC}"
@@ -457,7 +465,7 @@ echo -e "${GREEN}OK${NC}"
TARGET_ENODE=$(extract_enode "$TARGET_INFO")
TARGET_NAME=$(extract_name "$TARGET_INFO")
TARGET_PUBKEY=$(echo "$TARGET_ENODE" | sed -E 's|enode://([^@]+)@.*|\1|')
TARGET_CLIENT=$(detect_client_type "$TARGET_NAME")
TARGET_CLIENT=$(detect_client_type "$TARGET_NAME" "$TARGET_COMPOSE_FILE")
if [[ -z "$TARGET_ENODE" ]]; then
echo -e "${RED}Could not extract enode from target${NC}"

View File

@@ -78,16 +78,21 @@ CLIENT_NAME="$(echo "$INFO" | jq -r '.result.name // empty' 2>/dev/null || true)
PEERS_JSON="$(rpc admin_peers)"
PEER_COUNT="$(echo "$PEERS_JSON" | jq -r '.result | length' 2>/dev/null || echo 0)"
# Detect client type (connect-peers.sh logic)
# Detect client type (connect-peers.sh logic).
# op-geth often still reports as "Geth/…" — prefer compose path for op-geth.
NAME_LC="$(echo "$CLIENT_NAME" | tr '[:upper:]' '[:lower:]')"
CLIENT_TYPE="unknown"
case "$NAME_LC" in
*op-geth*) CLIENT_TYPE="op-geth" ;;
*geth*) CLIENT_TYPE="geth" ;;
*reth*) CLIENT_TYPE="reth" ;;
*erigon*) CLIENT_TYPE="erigon" ;;
*nethermind*) CLIENT_TYPE="nethermind" ;;
*besu*) CLIENT_TYPE="besu" ;;
esac
case "$COMPOSE_PATH" in
*op-geth*) CLIENT_TYPE="op-geth" ;;
esac
TS="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "$PEERS_JSON" | jq -c --arg path "$COMPOSE_PATH" --arg ts "$TS" \

View File

@@ -1,7 +1,8 @@
#!/bin/bash
# peer-reinject.sh — generic .after-start hook: re-seed peers from peer-capture state.
# Uses admin_addStaticPeer for geth, admin_addPeer otherwise (connect-peers.sh).
# In-network vantage (rpc_chains). Idempotent; best-effort (never fails the restart).
# Uses admin_addStaticPeer for vanilla geth, admin_addPeer for op-geth and others
# (connect-peers.sh). In-network vantage (rpc_chains). Idempotent; best-effort
# (never fails the restart).
#
# Seed order (one path for us and customers):
# 1. Own persisted peerset (peer-state/<compose>.json from peer-capture)
@@ -68,6 +69,12 @@ if [ "${#ENODES[@]}" -eq 0 ]; then
exit 0
fi
# op-geth lacks admin_addStaticPeer; compose path wins over stale capture state
# that classified the node as plain "geth" (admin_nodeInfo often still says Geth).
case "$COMPOSE_PATH" in
*op-geth*) CLIENT_TYPE="op-geth" ;;
esac
BASE="$(basename "$COMPOSE_PATH" | sed 's/--.*//')"
EL=""
# wait briefly for container after recreate
@@ -120,6 +127,7 @@ done
add_peer() {
local enode="$1"
local method
# Only vanilla geth supports admin_addStaticPeer; op-geth must use admin_addPeer
if [ "$CLIENT_TYPE" = "geth" ]; then
method="admin_addStaticPeer"
else
@@ -132,7 +140,8 @@ add_peer() {
resp="$(docker exec peer-hook-probe curl -s --max-time 8 -X POST \
-H 'Content-Type: application/json' --data "$payload" \
"http://${IP}:8545" 2>/dev/null || true)"
if echo "$resp" | grep -qi 'method not found'; then
# go-ethereum-style: "the method X does not exist/is not available" (not "method not found")
if echo "$resp" | grep -qiE 'method not found|does not exist|not available|-32601'; then
if [ "$method" = "admin_addStaticPeer" ]; then
method="admin_addPeer"
else