lecoffre_node/miner/signet_miner.py
2025-09-19 20:37:41 +00:00

79 lines
2.8 KiB
Python

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()