#!/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()