chore(prototype): move legacy python miner into prototype folder with usage docs
This commit is contained in:
101
prototype/rpc.py
Normal file
101
prototype/rpc.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import logging
|
||||
|
||||
from bitcoinrpc.authproxy import AuthServiceProxy
|
||||
|
||||
import config
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def connect_rpc() -> AuthServiceProxy:
|
||||
"""Create an RPC connection to the Bitcoin node."""
|
||||
return AuthServiceProxy(
|
||||
f"http://{config.RPC_USER}:{config.RPC_PASSWORD}@{config.RPC_HOST}:{config.RPC_PORT}"
|
||||
)
|
||||
|
||||
|
||||
def test_rpc_connection() -> None:
|
||||
"""Check the connection and show basic blockchain information."""
|
||||
log.info("Checking RPC connection")
|
||||
try:
|
||||
info = connect_rpc().getblockchaininfo()
|
||||
log.info(
|
||||
"RPC connection successful - chain=%s, blocks=%d, difficulty=%s",
|
||||
info["chain"], info["blocks"], info["difficulty"],
|
||||
)
|
||||
except Exception:
|
||||
log.exception("RPC connection error")
|
||||
raise
|
||||
|
||||
|
||||
def get_best_block_hash(rpc) -> str | None:
|
||||
"""Fetch the most recent block hash."""
|
||||
try:
|
||||
h = rpc.getbestblockhash()
|
||||
log.debug("Best block hash: %s", h)
|
||||
return h
|
||||
except Exception as e:
|
||||
log.error("RPC error getbestblockhash: %s", e)
|
||||
return None
|
||||
|
||||
|
||||
def get_block_template(rpc) -> dict | None:
|
||||
"""Request a block template with SegWit support."""
|
||||
try:
|
||||
tpl = rpc.getblocktemplate({"rules": ["segwit"]})
|
||||
log.debug("Template received - height=%d, tx=%d", tpl["height"], len(tpl["transactions"]))
|
||||
return tpl
|
||||
except Exception as e:
|
||||
log.error("RPC error getblocktemplate: %s", e)
|
||||
return None
|
||||
|
||||
|
||||
def ensure_witness_data(rpc, template: dict) -> None:
|
||||
"""
|
||||
Enrich template transactions with full witness data.
|
||||
Use a single HTTP batch call to reduce latency versus N single requests.
|
||||
"""
|
||||
txs = template["transactions"]
|
||||
if not txs:
|
||||
return
|
||||
|
||||
# JSON-RPC batch call: one HTTP request for all transactions
|
||||
try:
|
||||
batch = [["getrawtransaction", tx["txid"], False] for tx in txs]
|
||||
results = rpc._batch(batch)
|
||||
raw_map = {
|
||||
txs[r["id"]]["txid"]: r["result"]
|
||||
for r in results
|
||||
if r.get("result") is not None
|
||||
}
|
||||
except Exception as e:
|
||||
log.warning("RPC batch unavailable, falling back to single calls: %s", e)
|
||||
raw_map = {}
|
||||
for tx in txs:
|
||||
try:
|
||||
raw = rpc.getrawtransaction(tx["txid"], False)
|
||||
if raw:
|
||||
raw_map[tx["txid"]] = raw
|
||||
except Exception as e2:
|
||||
log.debug("Missing raw witness for %s: %s", tx["txid"], e2)
|
||||
|
||||
template["transactions"] = [
|
||||
{"hash": tx["txid"], "data": raw_map.get(tx["txid"], tx["data"])}
|
||||
for tx in txs
|
||||
]
|
||||
|
||||
|
||||
def submit_block(rpc, serialized_block: str) -> None:
|
||||
"""Submit the mined block to the Bitcoin node."""
|
||||
log.info("Submitting serialized block (%d bytes) to node", len(serialized_block) // 2)
|
||||
if not serialized_block:
|
||||
log.error("Block not serialized correctly - submission canceled")
|
||||
return
|
||||
try:
|
||||
result = rpc.submitblock(serialized_block)
|
||||
if result is None:
|
||||
log.info("Block accepted into the blockchain")
|
||||
else:
|
||||
log.error("submitblock returned: %s", result)
|
||||
except Exception:
|
||||
log.exception("RPC error during submitblock")
|
||||
Reference in New Issue
Block a user