108 lines
4.6 KiB
Python
108 lines
4.6 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
Fix Besu enode URLs by extracting first 128 chars and mapping to correct IPs
|
||
|
|
"""
|
||
|
|
|
||
|
|
import json
|
||
|
|
import re
|
||
|
|
import sys
|
||
|
|
|
||
|
|
# Container IP mapping (VMID -> IP)
|
||
|
|
# Note: IP addresses will be assigned via DHCP, this is a placeholder mapping
|
||
|
|
CONTAINER_IPS = {
|
||
|
|
1000: "192.168.11.100", # validator-1 (DHCP assigned)
|
||
|
|
1001: "192.168.11.101", # validator-2 (DHCP assigned)
|
||
|
|
1002: "192.168.11.102", # validator-3 (DHCP assigned)
|
||
|
|
1003: "192.168.11.103", # validator-4 (DHCP assigned)
|
||
|
|
1004: "192.168.11.104", # validator-5 (DHCP assigned)
|
||
|
|
1500: "192.168.11.150", # sentry-1 (DHCP assigned)
|
||
|
|
1501: "192.168.11.151", # sentry-2 (DHCP assigned)
|
||
|
|
1502: "192.168.11.152", # sentry-3 (DHCP assigned)
|
||
|
|
1503: "192.168.11.153", # sentry-4 (DHCP assigned)
|
||
|
|
2500: "192.168.11.250", # rpc-1 (DHCP assigned)
|
||
|
|
2501: "192.168.11.251", # rpc-2 (DHCP assigned)
|
||
|
|
2502: "192.168.11.252", # rpc-3 (DHCP assigned)
|
||
|
|
}
|
||
|
|
|
||
|
|
# Source validator node IDs (from source static-nodes.json, already 128 chars)
|
||
|
|
SOURCE_VALIDATOR_NODE_IDS = [
|
||
|
|
"889ba317e10114a035ef82248a26125fbc00b1cd65fb29a2106584dddd025aa3dda14657bc423e5e8bf7d91a9858e85a",
|
||
|
|
"2a827fcff14e548b761d18d0d7177745799d880be5ac54fb17d73aa06b105559527c97fec09005ac050e1363f16cb052",
|
||
|
|
"aeec2f2f7ee15da9bdbf11261d1d1e5526d2d1ca03d66393e131cc70dcea856a9a01ef3488031b769025447e36e14f4e",
|
||
|
|
"0f647faab18eb3cd1a334ddf397011af768b3311400923b670d9536f5a937aa04071801de095100142da03b233adb5db",
|
||
|
|
"037c0feeb799e7e98bc99f7c21b8993254cc48f3251c318b211a76aa40d9c373da8c0a1df60804b327b43a222940ebf0"
|
||
|
|
]
|
||
|
|
|
||
|
|
# Validator VMIDs (new ranges)
|
||
|
|
VALIDATOR_VMIDS = [1000, 1001, 1002, 1003, 1004]
|
||
|
|
|
||
|
|
def extract_node_id(enode_url):
|
||
|
|
"""Extract node ID from enode URL, taking first 128 chars"""
|
||
|
|
match = re.match(r'enode://([0-9a-fA-F]+)@', enode_url)
|
||
|
|
if not match:
|
||
|
|
return None
|
||
|
|
node_id_hex = match.group(1).lower()
|
||
|
|
# Take first 128 chars (removes trailing zeros padding)
|
||
|
|
return node_id_hex[:128] if len(node_id_hex) >= 128 else node_id_hex
|
||
|
|
|
||
|
|
def normalize_node_id(node_id):
|
||
|
|
"""Ensure node ID is exactly 128 hex characters (take first 128 if longer)"""
|
||
|
|
node_id = node_id.lower().strip()
|
||
|
|
if len(node_id) > 128:
|
||
|
|
# Take first 128 chars (removes trailing padding)
|
||
|
|
return node_id[:128]
|
||
|
|
elif len(node_id) < 128:
|
||
|
|
# If shorter, it's invalid - return as-is (will fail validation)
|
||
|
|
return node_id
|
||
|
|
return node_id
|
||
|
|
|
||
|
|
def create_enode(node_id, ip, port=30303):
|
||
|
|
"""Create enode URL from node ID and IP"""
|
||
|
|
# Source node IDs are already 128 chars, use as-is
|
||
|
|
normalized = normalize_node_id(node_id)
|
||
|
|
if len(normalized) != 128:
|
||
|
|
raise ValueError(f"Node ID must be exactly 128 chars, got {len(normalized)}")
|
||
|
|
return f"enode://{normalized}@{ip}:{port}"
|
||
|
|
|
||
|
|
def main():
|
||
|
|
# Map source validator node IDs to container IPs
|
||
|
|
validator_enodes = []
|
||
|
|
for i, node_id in enumerate(SOURCE_VALIDATOR_NODE_IDS):
|
||
|
|
vmid = VALIDATOR_VMIDS[i]
|
||
|
|
ip = CONTAINER_IPS[vmid]
|
||
|
|
enode = create_enode(node_id, ip)
|
||
|
|
validator_enodes.append(enode)
|
||
|
|
print(f"Validator {vmid} ({ip}): {enode[:80]}...", file=sys.stderr)
|
||
|
|
|
||
|
|
# For sentries and RPC nodes, we need to extract from deployed permissions-nodes.toml
|
||
|
|
# For now, we'll include validators only in static-nodes.json
|
||
|
|
# and generate permissions-nodes.toml with validators only (will need to add sentries/RPC later)
|
||
|
|
|
||
|
|
# Generate static-nodes.json (validators only)
|
||
|
|
static_nodes = sorted(validator_enodes)
|
||
|
|
with open('static-nodes.json', 'w') as f:
|
||
|
|
json.dump(static_nodes, f, indent=2)
|
||
|
|
print(f"Generated static-nodes.json with {len(static_nodes)} validators", file=sys.stderr)
|
||
|
|
|
||
|
|
# Generate permissions-nodes.toml (validators only for now)
|
||
|
|
toml_content = """# Node Permissioning Configuration
|
||
|
|
# Lists nodes that are allowed to connect to this node
|
||
|
|
# Generated from source static-nodes.json (first 128 chars of node IDs)
|
||
|
|
# Validators only (sentries and RPC nodes need to be added separately)
|
||
|
|
|
||
|
|
nodes-allowlist=[
|
||
|
|
"""
|
||
|
|
for enode in sorted(validator_enodes):
|
||
|
|
toml_content += f' "{enode}",\n'
|
||
|
|
toml_content = toml_content.rstrip(',\n') + '\n]'
|
||
|
|
|
||
|
|
with open('permissions-nodes.toml', 'w') as f:
|
||
|
|
f.write(toml_content)
|
||
|
|
print(f"Generated permissions-nodes.toml with {len(validator_enodes)} validators", file=sys.stderr)
|
||
|
|
print("", file=sys.stderr)
|
||
|
|
print("NOTE: Sentries and RPC nodes need to be added to permissions-nodes.toml", file=sys.stderr)
|
||
|
|
print(" after extracting their node IDs from running Besu instances.", file=sys.stderr)
|
||
|
|
|
||
|
|
if __name__ == '__main__':
|
||
|
|
main()
|