import argparse import base64 import http.client import json import os import time def rpc_call(host: str, port: int, cookie_path: str, method: str, params): with open(cookie_path, 'r', encoding='utf-8') as f: cookie = f.read().strip() auth = base64.b64encode(cookie.encode()).decode() conn = http.client.HTTPConnection(host, port, timeout=30) payload = json.dumps({"jsonrpc": "1.0", "id": "miner", "method": method, "params": params}) headers = {"Content-Type": "application/json", "Authorization": f"Basic {auth}"} conn.request("POST", "/", payload, headers) resp = conn.getresponse() body = resp.read() if resp.status != 200: raise RuntimeError(f"RPC HTTP {resp.status}: {body.decode(errors='ignore')}") data = json.loads(body) if data.get("error"): raise RuntimeError(str(data["error"])) return data["result"] def main(): p = argparse.ArgumentParser() p.add_argument('--cookie', required=True) p.add_argument('--rpc-host', default='bitcoin') p.add_argument('--rpc-port', type=int, default=38332) p.add_argument('--poll-interval', type=int, default=5) args = p.parse_args() # Paramètres via env challenge = os.environ.get('SIGNET_CHALLENGE', '') xprv = os.environ.get('SIGNET_MINER_XPRV', '') derivation = os.environ.get('DERIVATION_PATH', "48'/1'/0'/2'/0/0") coinbase_addr = os.environ.get('COINBASE_ADDRESS', '') if not challenge: raise SystemExit('SIGNET_CHALLENGE non défini') if not xprv: print('Avertissement: SIGNET_MINER_XPRV non défini (mode lecture gbt uniquement)') if not coinbase_addr: raise SystemExit('COINBASE_ADDRESS non défini') print('Miner signet: host=%s port=%d' % (args.rpc_host, args.rpc_port), flush=True) print('Challenge:', challenge, flush=True) print('Derivation:', derivation, flush=True) print('Coinbase address:', coinbase_addr, flush=True) try: bh = rpc_call(args.rpc_host, args.rpc_port, args.cookie, 'getblockcount', []) print('Hauteur actuelle:', bh, flush=True) except Exception as e: print('Erreur RPC initiale:', e, flush=True) while True: try: # Inclure la règle signet comme demandé par bitcoind en signet tmpl = rpc_call( args.rpc_host, args.rpc_port, args.cookie, 'getblocktemplate', [{"rules": ["segwit", "signet"]}] ) print('Template: height=%s nTx=%s' % (tmpl.get('height'), len(tmpl.get('transactions', []))), flush=True) # TODO: construire coinbase (coinbase_addr), header, signer selon le challenge signet puis submitblock except Exception as e: print('Erreur getblocktemplate:', e, flush=True) time.sleep(args.poll_interval) if __name__ == '__main__': main()