#!/usr/bin/env python3 """ Generate IBFT 2.0 Genesis with Validator Addresses This script extracts validator addresses from keys and creates proper genesis.json """ import json import os import subprocess import sys from pathlib import Path def extract_address_from_key(key_path): """Extract Ethereum address from private key using Besu or fallback method""" if not os.path.exists(key_path): return None # Try Besu first try: result = subprocess.run( ['besu', 'public-key', 'export-address', '--node-private-key-file', key_path], capture_output=True, text=True, timeout=10 ) if result.returncode == 0: return result.stdout.strip() except: pass # Fallback: Read private key and derive address (simplified) # Note: This is a placeholder - proper address derivation requires secp256k1 try: with open(key_path, 'r') as f: priv_key = f.read().strip() # For now, return None - requires proper crypto library return None except: return None def generate_extra_data(validator_addresses): """ Generate IBFT 2.0 extraData Format: RLP([32 bytes Vanity, [][20 bytes]Validators, 65 bytes Signature]) This is a placeholder - proper encoding requires RLP library """ if not validator_addresses: return "0x" # This is a simplified placeholder # Proper implementation requires: # 1. RLP encoding library # 2. Vanity bytes (32 bytes of zeros or custom data) # 3. Validator addresses (20 bytes each) # 4. Signature (65 bytes) # For now, return placeholder that indicates validators exist # Actual encoding must be done with Besu CLI return "0x" + "00" * 32 + "".join([addr[2:] if addr.startswith("0x") else addr for addr in validator_addresses[:4]])[:80] def main(): project_root = Path(__file__).parent.parent.parent keys_dir = project_root / "keys" / "validators" config_dir = project_root / "config" # Find validator keys validator_addresses = [] for i in range(1, 5): key_path = keys_dir / f"validator-{i}" / "key.priv" if key_path.exists(): addr = extract_address_from_key(str(key_path)) if addr: validator_addresses.append(addr) print(f"Found validator {i}: {addr}") if not validator_addresses: print("⚠️ No validator addresses extracted") print("Note: Proper address extraction requires Besu CLI or secp256k1 library") return 1 # Read existing genesis genesis_path = config_dir / "genesis.json" if not genesis_path.exists(): print(f"❌ Genesis file not found: {genesis_path}") return 1 with open(genesis_path, 'r') as f: genesis = json.load(f) # Generate extraData (placeholder - requires proper RLP encoding) extra_data = generate_extra_data(validator_addresses) # Update genesis genesis['extraData'] = extra_data # Write updated genesis with open(genesis_path, 'w') as f: json.dump(genesis, f, indent=2) print(f"✅ Updated genesis.json with {len(validator_addresses)} validators") print(f"⚠️ Note: extraData is placeholder - use Besu CLI for proper encoding") print(f" Run: besu operator generate-blockchain-config --config-file=config/genesis-template.json --to=keys/validators") return 0 if __name__ == "__main__": sys.exit(main())